Skip to main content

session_log/
logger.rs

1use crate::*;
2
3
4/// Logger is the base type that actually handle the loggings
5pub struct Logger {
6  pub(crate) name       : String,
7  pub(crate) write_level: Level,
8  pub(crate) print_level: Level,
9  pub(crate) writer     : Writer,
10  pub(crate) for_write  : fn(&Context) -> String,
11  pub(crate) for_print  : fn(&Context) -> String,
12}
13
14
15impl Logger {
16  /// Creating a new logger with the given name & default configurations.
17  pub fn default(name: impl Into<String>) -> Self {
18    Self::new::<DefaultFormatter>(name, Config::default())
19  }
20}
21
22
23impl Logger {
24  /// Creating a new logger with the given name.
25  pub fn new<F: Formatter>(name: impl Into<String>, config: Config) -> Self {
26    Logger {
27      name       : name.into(),
28      write_level: config.write_level,
29      print_level: config.print_level,
30      writer     : Writer::new(config),
31      for_write  : F::for_write,
32      for_print  : F::for_print,
33    }
34  }
35
36  /// Create a new session from the logger.
37  ///
38  /// There are two types of session: silent & non-silent. Silent session will not print the header
39  /// and footer of the session when no message is logged before the session is dropped. It's useful
40  /// session that may potentially not log anything. Non-silent session will always print the header
41  /// and footer of the session.
42  ///
43  /// Due to the uncertainty of if the session will log anything, the header will be deferred until
44  /// the first log. If the session logged anything, it'll act like a non-silent session.
45  #[track_caller]
46  pub fn session(&self, name: impl Into<String>, silent: bool) -> Session {
47    Session::new(name, SessionSrc::Logger(self), silent)
48  }
49
50  /// Create a new session from the session and execute the callable with the session passed in.
51  ///
52  /// This can be handy for isolating the environment of each callable while also providing a common
53  /// logging interface for any callable that needs to be logged.
54  #[track_caller]
55  pub fn session_then<F, T>(&self, name: impl Into<String>, silent: bool, callable: F) -> T
56  where F: FnOnce(Session) -> T
57  {
58    callable(self.session(name, silent))
59  }
60}
61
62
63impl LoggableInner for Logger {
64  fn log(&self, level: Level, message: &str) {
65    let ctx = Context::new_message(
66      Source::new(&self.name),
67      level,
68      message
69    );
70
71    if level >= self.print_level {
72      println!("{}", (self.for_print)(&ctx));
73    }
74
75    if level >= self.write_level {
76      self.writer.lock().unwrap()
77        .write((self.for_write)(&ctx));
78    }
79  }
80}
81
82
83impl Loggable for Logger {
84  fn root_name(&self) -> &str {
85    &self.name
86  }
87
88  fn name(&self) -> &str {
89    &self.name
90  }
91
92  fn path(&self) -> String {
93    self.writer.lock().unwrap().path.clone()
94  }
95
96  fn write_level(&self) -> Level {
97    self.write_level
98  }
99
100  fn print_level(&self) -> Level {
101    self.print_level
102  }
103}