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