thin_logger/
lib.rs

1use anyhow::{Context, Result};
2use chrono::Local;
3use colored::*;
4use env_logger::{Builder, WriteStyle};
5use log::LevelFilter;
6use std::io::Write;
7
8pub struct ThinLogger {
9    app_level_logs: LevelFilter,
10    external_level_logs: LevelFilter,
11}
12
13impl ThinLogger {
14    pub fn new(app_level_logs: LevelFilter) -> Self {
15        ThinLogger {
16            app_level_logs,
17            external_level_logs: LevelFilter::Off,
18        }
19    }
20
21    pub fn external_logs(mut self, level: LevelFilter) -> Self {
22        self.external_level_logs = level;
23        self
24    }
25
26    pub fn init(self) -> Result<()> {
27        let mut builder = Builder::new();
28
29        builder
30            .format(|buf, record| {
31                let timestamp = Local::now()
32                    .format("%H:%M:%S%p")
33                    .to_string()
34                    .yellow()
35                    .dimmed();
36                let style = buf.default_level_style(record.level());
37                let level_style = format!("{style}{}{style:#}", record.level());
38
39                let target_pretty = record.target().split("::").next().unwrap();
40
41                writeln!(
42                    buf,
43                    "[{}] [{}] [{}]: {}",
44                    timestamp,
45                    level_style,
46                    target_pretty,
47                    record.args()
48                )
49            })
50            .format_level(true)
51            .write_style(WriteStyle::Always);
52
53        if self.external_level_logs != LevelFilter::Off {
54            builder.filter(None, self.external_level_logs);
55        } else {
56            let crate_mod = env!("CARGO_PKG_NAME").replace('-', "_");
57            builder
58                .filter(None, LevelFilter::Off)
59                .filter_module(&crate_mod, self.app_level_logs);
60        }
61
62        builder.try_init().context("Failed to initialize logger")
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn test_logger_logs() -> Result<()> {
72        ThinLogger::new(LevelFilter::Trace).init()?;
73        log::trace!("This is a test log");
74        log::debug!("This is a test log");
75        log::info!("This is a test log");
76        log::warn!("This is a test log");
77        log::error!("This is a test log");
78        Ok(())
79    }
80}