1use lazy_static::lazy_static;
2use parking_lot::RwLock;
3use std::sync::atomic::{AtomicBool, Ordering};
4use std::sync::Arc;
5
6use crate::handler::Handler;
7use crate::level::LogLevel;
8use crate::record::Record;
9use crate::AsyncLoggerBuilder;
10use crate::AsyncLoggerHandle;
11
12#[macro_export]
14macro_rules! debug_println {
15 ($($arg:tt)*) => {
16 #[cfg(feature = "debug_logging")]
17 println!(
18 "log_sync: record level = {:?}, logger level = {:?}",
19 record.level(),
20 self.level
21 );
22 };
23}
24
25#[derive(Debug)]
27pub struct Logger {
28 level: LogLevel,
30 handlers: Vec<Arc<RwLock<dyn Handler>>>,
32 async_mode: bool,
34 async_handle: Option<AsyncLoggerHandle>,
36 active: Arc<AtomicBool>,
38}
39
40impl Logger {
41 pub fn new(level: LogLevel) -> Self {
43 Self {
44 level,
45 handlers: Vec::new(),
46 async_mode: false,
47 async_handle: None,
48 active: Arc::new(AtomicBool::new(true)),
49 }
50 }
51
52 pub fn level(&self) -> LogLevel {
54 self.level
55 }
56
57 pub fn set_level(&mut self, level: LogLevel) -> &mut Self {
59 self.level = level;
60 self
61 }
62
63 pub fn add_handler(&mut self, handler: Arc<RwLock<dyn Handler>>) -> &mut Self {
65 self.handlers.push(handler);
66 self
67 }
68
69 pub fn remove_handler(&mut self, handler: Arc<RwLock<dyn Handler>>) -> &mut Self {
71 self.handlers.retain(|h| !Arc::ptr_eq(h, &handler));
72 self
73 }
74
75 pub fn set_async(&mut self, enable: bool, queue_size: Option<usize>) -> &mut Self {
77 if self.async_mode == enable {
79 return self;
80 }
81
82 if enable {
83 let builder = AsyncLoggerBuilder::new()
85 .with_queue_size(queue_size.unwrap_or(10000))
86 .with_handlers(self.handlers.clone())
87 .with_level(self.level);
88
89 self.async_handle = Some(builder.build());
90 self.async_mode = true;
91 } else {
92 if let Some(handle) = self.async_handle.take() {
94 handle.shutdown();
95 }
96 self.async_mode = false;
97 }
98
99 self
100 }
101
102 pub fn set_worker_threads(&mut self, count: usize) -> &mut Self {
104 if self.async_mode && self.async_handle.is_some() {
105 self.set_async(false, None);
107 let builder = AsyncLoggerBuilder::new()
108 .with_queue_size(10000)
109 .with_handlers(self.handlers.clone())
110 .with_level(self.level)
111 .with_workers(count);
112
113 self.async_handle = Some(builder.build());
114 self.async_mode = true;
115 }
116 self
117 }
118
119 pub fn log(&self, record: &Record) -> bool {
121 if record.level() >= self.level() && self.active.load(Ordering::Relaxed) {
122 if self.async_mode {
124 if let Some(handle) = &self.async_handle {
125 return handle.log(record.clone());
126 }
127 }
128
129 return self.log_sync(record);
131 }
132 false
133 }
134
135 fn log_sync(&self, record: &Record) -> bool {
137 let mut any_handled = false;
138 for handler in &self.handlers {
139 let guard = handler.write();
140 if guard.is_enabled() && record.level() >= guard.level() && guard.handle(record).is_ok()
141 {
142 any_handled = true;
143 }
144 }
145 any_handled
146 }
147
148 pub fn log_message(&self, level: LogLevel, message: impl Into<String>) -> bool {
150 let record = Record::new(level, message, None::<String>, None::<String>, None);
151 self.log(&record)
152 }
153
154 pub fn debug(&self, message: impl Into<String>) -> bool {
156 self.log_message(LogLevel::Debug, message)
157 }
158
159 pub fn info(&self, message: impl Into<String>) -> bool {
161 self.log_message(LogLevel::Info, message)
162 }
163
164 pub fn warn(&self, message: impl Into<String>) -> bool {
166 self.log_message(LogLevel::Warning, message)
167 }
168
169 pub fn error(&self, message: impl Into<String>) -> bool {
171 self.log_message(LogLevel::Error, message)
172 }
173
174 pub fn set_enabled(&self, enabled: bool) -> &Self {
176 self.active.store(enabled, Ordering::Relaxed);
177 self
178 }
179
180 pub fn is_enabled(&self) -> bool {
182 self.active.load(Ordering::Relaxed)
183 }
184
185 pub fn handlers(&self) -> &[Arc<RwLock<dyn Handler>>] {
187 &self.handlers
188 }
189
190 pub fn is_async(&self) -> bool {
192 self.async_mode
193 }
194}
195
196impl Clone for Logger {
197 fn clone(&self) -> Self {
198 Self {
199 level: self.level,
200 handlers: self.handlers.clone(),
201 async_mode: self.async_mode,
202 async_handle: self.async_handle.clone(),
203 active: Arc::new(AtomicBool::new(self.active.load(Ordering::Relaxed))),
204 }
205 }
206}
207
208lazy_static! {
209 static ref GLOBAL_LOGGER: RwLock<Logger> = RwLock::new(Logger::new(LogLevel::Info));
211}
212
213pub fn init(logger: Logger) -> Logger {
215 let mut global = GLOBAL_LOGGER.write();
216 global.set_level(logger.level());
217 global.set_enabled(logger.is_enabled());
218 global.handlers.clear();
220 for handler in logger.handlers() {
222 global.add_handler(handler.clone());
223 }
224 logger
225}
226
227pub fn global() -> &'static RwLock<Logger> {
229 &GLOBAL_LOGGER
230}
231
232pub fn log(record: &Record) -> bool {
242 GLOBAL_LOGGER.read().log(record)
243}
244
245#[cfg(test)]
246mod tests {
247 use super::*;
248 use crate::handler::NullHandler;
249
250 #[test]
251 fn test_logger_creation() {
252 let logger = Logger::new(LogLevel::Info);
253 assert_eq!(logger.level(), LogLevel::Info);
254 assert!(logger.handlers.is_empty());
255 }
256
257 #[test]
258 fn test_logger_level() {
259 let mut logger = Logger::new(LogLevel::Info);
260 logger.set_level(LogLevel::Debug);
261 assert_eq!(logger.level(), LogLevel::Debug);
262 }
263
264 #[test]
265 fn test_logger_handler() {
266 let mut logger = Logger::new(LogLevel::Info);
267 let handler = Arc::new(RwLock::new(NullHandler::new(LogLevel::Info)));
268 logger.add_handler(handler.clone());
269 assert_eq!(logger.handlers.len(), 1);
270 logger.remove_handler(handler);
271 assert!(logger.handlers.is_empty());
272 }
273
274 #[test]
275 fn test_logger_log() {
276 let mut logger = Logger::new(LogLevel::Info);
277 let handler = Arc::new(RwLock::new(NullHandler::new(LogLevel::Info)));
278 logger.add_handler(handler);
279
280 assert!(!logger.debug("Debug message")); assert!(logger.info("Info message")); assert!(logger.warn("Warning message")); assert!(logger.error("Error message")); }
286
287 #[test]
288 fn test_logger_level_filtering() {
289 let mut logger = Logger::new(LogLevel::Warning);
290 let handler = Arc::new(RwLock::new(NullHandler::new(LogLevel::Info)));
291 logger.add_handler(handler);
292
293 assert!(!logger.debug("Debug message")); assert!(!logger.info("Info message")); assert!(logger.warn("Warning message")); assert!(logger.error("Error message")); }
299
300 #[test]
301 fn test_logger_handler_filtering() {
302 let mut logger = Logger::new(LogLevel::Info);
303 let mut handler = NullHandler::new(LogLevel::Info);
304 handler.set_level(LogLevel::Warning);
305 let handler = Arc::new(RwLock::new(handler));
306 logger.add_handler(handler);
307
308 assert!(!logger.debug("Debug message")); assert!(!logger.info("Info message")); assert!(logger.warn("Warning message")); assert!(logger.error("Error message")); }
314
315 #[test]
316 fn test_logger_disabled_handler() {
317 let mut logger = Logger::new(LogLevel::Info);
318 let mut handler = NullHandler::new(LogLevel::Info);
319 handler.set_enabled(false);
320 let handler = Arc::new(RwLock::new(handler));
321 logger.add_handler(handler);
322
323 assert!(!logger.info("Info message")); }
326
327 #[test]
328 fn test_logger_init() {
329 let logger = Logger::new(LogLevel::Info);
330 let logger = init(logger);
331 assert_eq!(logger.level(), LogLevel::Info);
332 }
333
334 #[test]
335 fn test_logger_enabled() {
336 let logger = Logger::new(LogLevel::Info);
337 assert!(logger.is_enabled());
338
339 logger.set_enabled(false);
340 assert!(!logger.is_enabled());
341
342 logger.set_enabled(true);
343 assert!(logger.is_enabled());
344 }
345
346 #[test]
347 fn test_async_logging() {
348 let mut logger = Logger::new(LogLevel::Info);
349 let handler = Arc::new(RwLock::new(NullHandler::new(LogLevel::Info)));
350 logger.add_handler(handler);
351
352 assert!(logger.info("Sync message"));
354 assert!(!logger.is_async());
355
356 logger.set_async(true, Some(1000));
358 assert!(logger.is_async());
359
360 assert!(logger.info("Async message"));
362
363 logger.set_worker_threads(2);
365 assert!(logger.info("Message with 2 workers"));
366
367 logger.set_async(false, None);
369 assert!(!logger.is_async());
370
371 assert!(logger.info("Sync message again"));
373 }
374
375 #[test]
376 fn test_compile_time_filtering() {
377 let logger = Logger::new(LogLevel::Info);
378
379 if !crate::compile_time_level_enabled!(LogLevel::Debug) {
381 assert!(!logger.debug("Debug message"));
382 }
383
384 if crate::compile_time_level_enabled!(LogLevel::Info) {
386 let handler = Arc::new(RwLock::new(NullHandler::new(LogLevel::Info)));
388 let mut logger = Logger::new(LogLevel::Info);
389 logger.add_handler(handler);
390 assert!(logger.info("Info message"));
391 }
392 }
393}