cassandra_cpp/cassandra/
log.rs1use crate::cassandra_sys::CassLogLevel_;
2use crate::cassandra_sys::CassLogMessage;
3use crate::cassandra::util::ProtectedInner;
5use crate::cassandra_sys::cass_log_set_callback;
6use crate::cassandra_sys::cass_log_set_level;
7
8#[cfg(feature = "slog")]
11use slog;
12
13use std::boxed::Box;
14use std::ffi::CStr;
15use std::os::raw;
16use std::ptr;
17
18#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Copy, Clone, Hash)]
20#[allow(missing_docs)] #[allow(non_camel_case_types)] pub enum LogLevel {
23 DISABLED,
24 CRITICAL,
25 ERROR,
26 WARN,
27 INFO,
28 DEBUG,
29 TRACE,
30 LAST_ENTRY,
31}
32
33enhance_nullary_enum!(LogLevel, CassLogLevel_, {
34 (DISABLED, CASS_LOG_DISABLED, "DISABLED"),
35 (CRITICAL, CASS_LOG_CRITICAL, "CRITICAL"),
36 (ERROR, CASS_LOG_ERROR, "ERROR"),
37 (WARN, CASS_LOG_WARN, "WARN"),
38 (INFO, CASS_LOG_INFO, "INFO"),
39 (DEBUG, CASS_LOG_DEBUG, "DEBUG"),
40 (TRACE, CASS_LOG_TRACE, "TRACE"),
41 (LAST_ENTRY, CASS_LOG_LAST_ENTRY, "LAST_ENTRY"),
42});
43
44pub fn set_level(level: LogLevel) {
50 unsafe { cass_log_set_level(level.inner()) }
51}
52
53pub fn unset_logger() {
55 unsafe { cass_log_set_callback(None, ptr::null_mut()) }
56}
57
58#[cfg(feature = "slog")]
59unsafe extern "C" fn slog_callback(log: *const CassLogMessage, data: *mut raw::c_void) {
62 let log = &*log;
63 let logger: &slog::Logger = &*(data as *const _);
64
65 let message: &str = &CStr::from_ptr(log.message.as_ptr()).to_string_lossy();
66 let time_ms: u64 = log.time_ms;
67 let file: &str = &CStr::from_ptr(log.file).to_string_lossy();
68 let line: i32 = log.line;
69 let function: &str = &CStr::from_ptr(log.function).to_string_lossy();
70 let kv = o!(
71 "time_ms" => time_ms,
72 "file" => file,
73 "line" => line,
74 "function" => function
75 );
76
77 match log.severity {
81 CassLogLevel_::CASS_LOG_DISABLED | CassLogLevel_::CASS_LOG_CRITICAL => {
82 crit!(logger, "{}", message; kv)
83 }
84 CassLogLevel_::CASS_LOG_ERROR => error!(logger, "{}", message; kv),
85 CassLogLevel_::CASS_LOG_WARN => warn!(logger, "{}", message; kv),
86 CassLogLevel_::CASS_LOG_INFO => info!(logger, "{}", message; kv),
87 CassLogLevel_::CASS_LOG_DEBUG => debug!(logger, "{}", message; kv),
88 CassLogLevel_::CASS_LOG_TRACE | CassLogLevel_::CASS_LOG_LAST_ENTRY => {
89 trace!(logger, "{}", message; kv)
90 }
91 };
92}
93
94#[doc(hidden)]
95#[deprecated(note = "Please use set_slog_logger instead")]
96#[cfg(feature = "slog")]
97pub fn set_logger(logger: Option<slog::Logger>) {
99 if let Some(logger) = logger {
100 set_slog_logger(logger);
101 } else {
102 unset_logger();
103 }
104}
105
106#[cfg(feature = "slog")]
107pub fn set_slog_logger(logger: slog::Logger) {
109 unsafe {
110 let data = Box::new(logger);
113 cass_log_set_callback(Some(slog_callback), Box::into_raw(data) as _)
114 }
115}
116
117#[cfg(feature = "log")]
118unsafe extern "C" fn log_callback(log: *const CassLogMessage, _data: *mut raw::c_void) {
121 use log::{logger, Level, Record};
122
123 let log = &*log;
124 let message: &str = &CStr::from_ptr(log.message.as_ptr()).to_string_lossy();
125 let file = &CStr::from_ptr(log.file).to_string_lossy();
126 let line = log.line as u32;
127 let function = &CStr::from_ptr(log.function).to_string_lossy();
128 let module_and_function_name = function_definition_to_module_name(function).unwrap_or(function);
129
130 let level = match log.severity {
131 CassLogLevel_::CASS_LOG_DISABLED | CassLogLevel_::CASS_LOG_CRITICAL => Level::Error,
132 CassLogLevel_::CASS_LOG_ERROR => Level::Error,
133 CassLogLevel_::CASS_LOG_WARN => Level::Warn,
134 CassLogLevel_::CASS_LOG_INFO => Level::Info,
135 CassLogLevel_::CASS_LOG_DEBUG => Level::Debug,
136 CassLogLevel_::CASS_LOG_TRACE | CassLogLevel_::CASS_LOG_LAST_ENTRY => Level::Trace,
137 };
138
139 logger().log(
140 &Record::builder()
141 .level(level)
142 .args(format_args!("{}", message))
143 .line(Some(line))
144 .file(Some(file))
145 .module_path(Some(module_and_function_name))
146 .target(module_and_function_name)
147 .build(),
148 );
149}
150
151fn function_definition_to_module_name(definition: &str) -> Option<&str> {
153 let mut definition_iter = definition.split(' ');
156 definition_iter.next()?;
158 definition_iter.next()?.split('(').next()
161}
162
163#[cfg(feature = "log")]
164pub fn set_log_logger() {
167 unsafe { cass_log_set_callback(Some(log_callback), ptr::null_mut()) }
168}