cpp_linter/
logger.rs

1//! A module to initialize and customize the logger object used in (most) stdout.
2
3use std::env;
4
5use anyhow::{Error, Result};
6use colored::{control::set_override, Colorize};
7use log::{Level, LevelFilter, Metadata, Record};
8
9#[derive(Default)]
10struct SimpleLogger;
11
12impl SimpleLogger {
13    fn level_color(level: &Level) -> String {
14        let name = format!("{:>5}", level.as_str().to_uppercase());
15        match level {
16            Level::Error => name.red().bold().to_string(),
17            Level::Warn => name.yellow().bold().to_string(),
18            Level::Info => name.green().bold().to_string(),
19            Level::Debug => name.blue().bold().to_string(),
20            Level::Trace => name.magenta().bold().to_string(),
21        }
22    }
23}
24
25impl log::Log for SimpleLogger {
26    fn enabled(&self, metadata: &Metadata) -> bool {
27        metadata.level() <= log::max_level()
28    }
29
30    fn log(&self, record: &Record) {
31        if record.target() == "CI_LOG_GROUPING" {
32            // this log is meant to manipulate a CI workflow's log grouping
33            println!("{}", record.args());
34        } else if self.enabled(record.metadata()) {
35            println!(
36                "[{}]: {}",
37                Self::level_color(&record.level()),
38                record.args()
39            );
40        }
41    }
42
43    fn flush(&self) {}
44}
45
46/// A function to initialize the private `LOGGER`.
47///
48/// The logging level defaults to [`LevelFilter::Info`].
49/// Returns a [`SetLoggerError`] if the `LOGGER` is already initialized.
50pub fn init() -> Result<()> {
51    let logger: SimpleLogger = SimpleLogger;
52    if matches!(
53        env::var("CPP_LINTER_COLOR").as_deref(),
54        Ok("on" | "1" | "true")
55    ) {
56        set_override(true);
57    }
58    log::set_boxed_logger(Box::new(logger))
59        .map(|()| log::set_max_level(LevelFilter::Info))
60        .map_err(Error::from)
61}
62
63#[cfg(test)]
64mod test {
65    use std::env;
66
67    use super::{init, SimpleLogger};
68
69    #[test]
70    fn trace_log() {
71        env::set_var("CPP_LINTER_COLOR", "true");
72        init().unwrap_or(());
73        assert!(SimpleLogger::level_color(&log::Level::Trace).contains("TRACE"));
74        log::set_max_level(log::LevelFilter::Trace);
75        log::trace!("A dummy log statement for code coverage");
76    }
77}