1use serde::Serialize;
21use std::collections::HashSet;
22use std::error::Error;
23use std::fmt;
24use std::rc::Rc;
25use std::sync::{mpsc, Arc};
26use std::thread;
27
28use crate::handler::{Handler, LevelAware, Handlers};
29
30mod context;
31mod item;
32mod level;
33mod record;
34
35pub use self::context::Context;
36pub use self::item::Item;
37pub use self::level::Level;
38pub use self::record::Record;
39
40pub struct Logger {
43 handlers: Arc<Handlers>,
44 context: Context,
45 levels: HashSet<Level>,
46 q: Option<mpsc::SyncSender<Record>>,
47 worker: Option<thread::JoinHandle<()>>,
48 print_errors: bool,
49}
50
51impl Logger {
52 pub fn new() -> Logger {
53 Logger {
54 handlers: Arc::new(Handlers::new()),
55 context: Context::new(),
56 levels: Level::all_set(),
57 q: None,
58 worker: None,
59 print_errors: false,
60 }
61 }
62
63 pub fn into_rc(self) -> Rc<Logger> {
64 Rc::new(self)
65 }
66
67 pub fn into_arc(self) -> Arc<Logger> {
68 Arc::new(self)
69 }
70
71 pub fn set_print_errors(&mut self, print_errors: bool) -> &mut Self {
72 self.print_errors = print_errors;
73 self
74 }
75
76 pub fn print_errors(mut self, print_errors: bool) -> Self {
77 self.set_print_errors(print_errors);
78 self
79 }
80
81 pub fn push_handler<T>(&mut self, handler: T) -> &mut Self
82 where
83 T: Handler + Sync + Send + 'static,
84 {
85 self.handlers.push(handler);
86 self
87 }
88
89 pub fn with_handler<T>(mut self, handler: T) -> Self
90 where
91 T: Handler + Sync + Send + 'static,
92 {
93 self.push_handler(handler);
94 self
95 }
96
97 pub fn set_global<V>(&mut self, k: &str, v: V) -> &mut Self
98 where
99 V: Serialize,
100 {
101 self.context.set(k, v);
102 self
103 }
104
105 pub fn with_global<V>(mut self, k: &str, v: V) -> Self
106 where
107 V: Serialize,
108 {
109 self.set_global(k, v);
110 self
111 }
112
113 pub fn make_sync(&mut self) -> &mut Self {
114 if let Some(q) = self.q.take() {
115 drop(q);
116 if let Some(worker) = self.worker.take() {
117 worker.join().expect("Unable to join logger worker");
118 }
119 }
120 self
121 }
122
123 pub fn sync(mut self) -> Self {
124 self.make_sync();
125 self
126 }
127
128 pub fn make_async(&mut self) -> &mut Self {
129 if let Some(_) = self.q {
130 return self;
131 }
132
133 let handlers = self.handlers.clone();
134 let (sender, receiver) = mpsc::sync_channel(256);
135 let print_errors = self.print_errors;
136 self.q = Some(sender);
137
138 let worker = thread::spawn(move || {
139 for record in receiver {
140 handlers.handle(&record, print_errors);
141 }
142 });
143 self.worker = Some(worker);
144
145 self
146 }
147
148 pub fn r#async(mut self) -> Self {
149 self.make_async();
150 self
151 }
152
153 pub fn with<V>(&self, k: &str, v: V) -> Item
154 where
155 V: Serialize,
156 {
157 Item::new(self).with(k, v)
158 }
159
160 pub fn with_multi<V: Into<Context>>(&self, ctx: V) -> Item {
161 Item::new(self).with_multi(ctx.into())
162 }
163
164 pub fn with_error(&self, e: &Error) -> Item {
165 Item::new(self).with_error(e)
166 }
167
168 pub fn with_new_context(&self, ctx: Context) -> Item {
169 Item::new(self).with_new_context(ctx)
170 }
171
172 pub fn log<S: ToString>(&self, level: Level, msg: S) {
173 if !self.levels.contains(&level) {
174 return;
175 }
176 let record = Record::new(level, msg.to_string());
177 self.dispatch(record);
178 }
179
180 pub fn trace<S: ToString>(&self, msg: S) {
181 self.log(Level::Trace, msg);
182 }
183 pub fn profile<S: ToString>(&self, msg: S) {
184 self.log(Level::Profile, msg);
185 }
186 pub fn debug<S: ToString>(&self, msg: S) {
187 self.log(Level::Debug, msg);
188 }
189 pub fn info<S: ToString>(&self, msg: S) {
190 self.log(Level::Info, msg);
191 }
192 pub fn notice<S: ToString>(&self, msg: S) {
193 self.log(Level::Notice, msg);
194 }
195 pub fn warning<S: ToString>(&self, msg: S) {
196 self.log(Level::Warning, msg);
197 }
198 pub fn error<S: ToString>(&self, msg: S) {
199 self.log(Level::Error, msg);
200 }
201 pub fn critical<S: ToString>(&self, msg: S) {
202 self.log(Level::Critical, msg);
203 }
204 pub fn alert<S: ToString>(&self, msg: S) {
205 self.log(Level::Alert, msg);
206 }
207 pub fn emergency<S: ToString>(&self, msg: S) {
208 self.log(Level::Emergency, msg);
209 }
210
211 fn dispatch(&self, mut record: Record) {
212 record.merge_context(&self.context);
213
214 if let Some(ref q) = self.q {
215 let _ = q.try_send(record);
217 } else {
218 self.handlers.handle(&record, self.print_errors);
219 }
220 }
221}
222
223impl LevelAware for Logger {
224 fn set_levels(&mut self, new_levels: &[Level]) -> &mut Self {
225 self.levels = new_levels.iter().cloned().collect();
226 self
227 }
228}
229
230impl fmt::Debug for Logger {
231 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
232 write!(
233 f,
234 "Logger {{ Handlers: {} Context: {:?} }}",
235 self.handlers.len(),
236 self.context
237 )
238 }
239}
240
241#[cfg(test)]
242mod tests {
243 use super::*;
244 use crate::handler::{null::NullHandler, vec::VecHandler, LevelAware};
245
246 #[test]
247 fn test_build_with_no_handler() {
248 let logger = Logger::new();
249
250 logger.debug("a debug message");
251 logger.log(Level::Emergency, "an emergency message");
252 }
253
254 #[test]
255 fn test_build_with_null_handler() {
256 let logger = Logger::new().with_handler(NullHandler {});
257
258 logger.debug("a debug message");
259 logger.log(Level::Emergency, "an emergency message");
260 }
261
262 #[test]
263 fn test_build_with_async_dispatcher() {
264 let logger = Logger::new().r#async().with_handler(NullHandler {});
265
266 logger.debug("a debug message");
267 logger.log(Level::Emergency, "an emergency message");
268 }
269
270 #[test]
271 fn test_context() {
272 let logger = Logger::new()
273 .with_global("string", "some string")
274 .with_global("bool", true)
275 .with_global("array", vec!["a", "b"]);
276
277 let context = &logger.context;
278 assert!(context.contains_key("string"));
279 assert_eq!("some string", context.get("string").unwrap());
280
281 assert!(context.contains_key("bool"));
282 assert_eq!(true, context.get("bool").unwrap().as_bool().unwrap());
283
284 assert!(context.contains_key("array"));
285 assert_eq!("a", context.get("array").unwrap().as_array().unwrap()[0]);
286 assert_eq!("b", context.get("array").unwrap().as_array().unwrap()[1]);
287 }
288
289 #[test]
290 fn test_levels() {
291 let handler = VecHandler::new();
292 let store = handler.get_store();
293 let logger = Logger::new().with_handler(handler);
294
295 logger.trace("Trace message");
296 logger.profile("Profile message");
297 logger.debug("Debug message");
298 logger.info("Info message");
299 logger.notice("Notice message");
300 logger.warning("Warning message");
301 logger.error("Error message");
302 logger.critical("Critical message");
303 logger.alert("Alert message");
304 logger.emergency("Emergency message");
305
306 let logs = store.take();
307
308 assert_eq!(10, logs.len());
309
310 assert_eq!("Trace message", logs[0].msg);
311 assert_eq!(Level::Trace, logs[0].level);
312
313 assert_eq!("Profile message", logs[1].msg);
314 assert_eq!(Level::Profile, logs[1].level);
315
316 assert_eq!("Debug message", logs[2].msg);
317 assert_eq!(Level::Debug, logs[2].level);
318
319 assert_eq!("Info message", logs[3].msg);
320 assert_eq!(Level::Info, logs[3].level);
321
322 assert_eq!("Notice message", logs[4].msg);
323 assert_eq!(Level::Notice, logs[4].level);
324
325 assert_eq!("Warning message", logs[5].msg);
326 assert_eq!(Level::Warning, logs[5].level);
327
328 assert_eq!("Error message", logs[6].msg);
329 assert_eq!(Level::Error, logs[6].level);
330
331 assert_eq!("Critical message", logs[7].msg);
332 assert_eq!(Level::Critical, logs[7].level);
333
334 assert_eq!("Alert message", logs[8].msg);
335 assert_eq!(Level::Alert, logs[8].level);
336
337 assert_eq!("Emergency message", logs[9].msg);
338 assert_eq!(Level::Emergency, logs[9].level);
339 }
340
341 #[test]
342 fn test_with_levels() {
343 let handler = VecHandler::new();
344 let store = handler.get_store();
345 let logger = Logger::new()
346 .with_levels(&[Level::Warning, Level::Emergency])
347 .with_handler(handler);
348
349 logger.trace("Trace message");
350 logger.profile("Profile message");
351 logger.debug("Debug message");
352 logger.info("Info message");
353 logger.notice("Notice message");
354 logger.warning("Warning message");
355 logger.error("Error message");
356 logger.critical("Critical message");
357 logger.alert("Alert message");
358 logger.emergency("Emergency message");
359
360 let logs = store.take();
361
362 assert_eq!(2, logs.len());
363
364 assert_eq!("Warning message", logs[0].msg);
365 assert_eq!(Level::Warning, logs[0].level);
366
367 assert_eq!("Emergency message", logs[1].msg);
368 assert_eq!(Level::Emergency, logs[1].level);
369 }
370
371 #[test]
372 fn test_with_handler_levels() {
373 let handler = VecHandler::new().with_levels(&[Level::Warning, Level::Emergency]);
374
375 let store = handler.get_store();
376 let logger = Logger::new().with_handler(handler);
377
378 logger.trace("Trace message");
379 logger.profile("Profile message");
380 logger.debug("Debug message");
381 logger.info("Info message");
382 logger.notice("Notice message");
383 logger.warning("Warning message");
384 logger.error("Error message");
385 logger.critical("Critical message");
386 logger.alert("Alert message");
387 logger.emergency("Emergency message");
388
389 let logs = store.take();
390
391 assert_eq!(2, logs.len());
392
393 assert_eq!("Warning message", logs[0].msg);
394 assert_eq!(Level::Warning, logs[0].level);
395
396 assert_eq!("Emergency message", logs[1].msg);
397 assert_eq!(Level::Emergency, logs[1].level);
398 }
399
400 #[test]
401 fn multi_thread_logger() {
402 use std::thread;
403
404 let handler = VecHandler::new();
405 let store = handler.get_store();
406 let logger = Logger::new().with_handler(handler).into_arc();
407 let tlogger = logger.clone();
408
409 let th = thread::spawn(move || {
410 tlogger.debug("Thread debug message");
411 });
412
413 logger.warning("Main warning message");
414
415 let _ = th.join();
416
417 let logs = store.take();
418
419 assert!(logs.iter().position(|v| v.msg.contains("Thread debug")).is_some());
420 assert!(logs.iter().position(|v| v.msg.contains("Main warning")).is_some());
421 }
422
423 #[test]
424 fn test_levels_with_item() {
425 let handler = VecHandler::new();
426 let store = handler.get_store();
427 let logger = Logger::new().with_handler(handler);
428
429 logger.with("kt", "vt").trace("Trace message");
430 logger.with("kp", "vp").profile("Profile message");
431 logger.with("kd", "vd").debug("Debug message");
432 logger.with("ki", "vi").info("Info message");
433 logger.with("kn", "vn").notice("Notice message");
434 logger.with("kw", "vw").warning("Warning message");
435 logger.with("ke", "ve").error("Error message");
436 logger.with("kc", "vc").critical("Critical message");
437 logger.with("ka", "va").alert("Alert message");
438 logger.with("km", "vm").emergency("Emergency message");
439
440 let logs = store.take();
441
442 assert_eq!(10, logs.len());
443
444 assert_eq!("Trace message", logs[0].msg);
445 assert_eq!(Level::Trace, logs[0].level);
446 assert_eq!("vt", logs[0].context.get("kt").expect("Missing expected context vt"));
447
448 assert_eq!("Profile message", logs[1].msg);
449 assert_eq!(Level::Profile, logs[1].level);
450 assert_eq!("vp", logs[1].context.get("kp").expect("Missing expected context vp"));
451
452 assert_eq!("Debug message", logs[2].msg);
453 assert_eq!(Level::Debug, logs[2].level);
454 assert_eq!("vd", logs[2].context.get("kd").expect("Missing expected context vd"));
455
456 assert_eq!("Info message", logs[3].msg);
457 assert_eq!(Level::Info, logs[3].level);
458 assert_eq!("vi", logs[3].context.get("ki").expect("Missing expected context vi"));
459
460 assert_eq!("Notice message", logs[4].msg);
461 assert_eq!(Level::Notice, logs[4].level);
462 assert_eq!("vn", logs[4].context.get("kn").expect("Missing expected context vn"));
463
464 assert_eq!("Warning message", logs[5].msg);
465 assert_eq!(Level::Warning, logs[5].level);
466 assert_eq!("vw", logs[5].context.get("kw").expect("Missing expected context vw"));
467
468 assert_eq!("Error message", logs[6].msg);
469 assert_eq!(Level::Error, logs[6].level);
470 assert_eq!("ve", logs[6].context.get("ke").expect("Missing expected context ve"));
471
472 assert_eq!("Critical message", logs[7].msg);
473 assert_eq!(Level::Critical, logs[7].level);
474 assert_eq!("vc", logs[7].context.get("kc").expect("Missing expected context vc"));
475
476 assert_eq!("Alert message", logs[8].msg);
477 assert_eq!(Level::Alert, logs[8].level);
478 assert_eq!("va", logs[8].context.get("ka").expect("Missing expected context va"));
479
480 assert_eq!("Emergency message", logs[9].msg);
481 assert_eq!(Level::Emergency, logs[9].level);
482 assert_eq!("vm", logs[9].context.get("km").expect("Missing expected context vm"));
483 }
484
485 #[test]
486 fn multi_thread_logger_with_item() {
487 use std::thread;
488
489 let handler = VecHandler::new();
490 let store = handler.get_store();
491 let logger = Logger::new().with_handler(handler).into_arc();
492 let tlogger = logger.clone();
493
494 let th = thread::spawn(move || {
495 tlogger.with("kt", "vt").debug("Thread debug message");
496 });
497
498 logger.with("km", "vm").warning("Main warning message");
499
500 let _ = th.join();
501
502 let logs = store.take();
503
504 assert!(logs
505 .iter()
506 .position(|v| v.msg.contains("Thread debug") && v.context.get("kt").expect("Missing thread context") == "vt")
507 .is_some());
508 assert!(logs
509 .iter()
510 .position(|v| v.msg.contains("Main warning") && v.context.get("km").expect("Missing main context") == "vm")
511 .is_some());
512 }
513
514 #[test]
515 fn multi_with_error() {
516 use std::io::{Error as IoError, ErrorKind as IoErrorKind};
517
518 let handler = VecHandler::new();
519 let store = handler.get_store();
520 let logger = Logger::new().with_handler(handler);
521
522 let err = IoError::new(IoErrorKind::PermissionDenied, IoError::from_raw_os_error(1));
524
525 logger.with_error(&err).trace("Trace message");
526
527 let logs = store.take();
528
529 assert!(logs
530 .iter()
531 .position(|v| v.msg.contains("Trace message")
532 && v.context.get("error").expect("Missing error in context") == "permission denied")
533 .is_some());
534 }
535}