cpp_linter/
logger.rs

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
//! A module to initialize and customize the logger object used in (most) stdout.

use std::env;

use anyhow::{Error, Result};
use colored::{control::set_override, Colorize};
use log::{Level, LevelFilter, Metadata, Record};

#[derive(Default)]
struct SimpleLogger;

impl SimpleLogger {
    fn level_color(level: &Level) -> String {
        let name = format!("{:>5}", level.as_str().to_uppercase());
        match level {
            Level::Error => name.red().bold().to_string(),
            Level::Warn => name.yellow().bold().to_string(),
            Level::Info => name.green().bold().to_string(),
            Level::Debug => name.blue().bold().to_string(),
            Level::Trace => name.magenta().bold().to_string(),
        }
    }
}

impl log::Log for SimpleLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= log::max_level()
    }

    fn log(&self, record: &Record) {
        if record.target() == "CI_LOG_GROUPING" {
            // this log is meant to manipulate a CI workflow's log grouping
            println!("{}", record.args());
        } else if self.enabled(record.metadata()) {
            println!(
                "[{}]: {}",
                Self::level_color(&record.level()),
                record.args()
            );
        }
    }

    fn flush(&self) {}
}

/// A function to initialize the private `LOGGER`.
///
/// The logging level defaults to [`LevelFilter::Info`].
/// Returns a [`SetLoggerError`] if the `LOGGER` is already initialized.
pub fn init() -> Result<()> {
    let logger: SimpleLogger = SimpleLogger;
    if matches!(
        env::var("CPP_LINTER_COLOR").as_deref(),
        Ok("on" | "1" | "true")
    ) {
        set_override(true);
    }
    log::set_boxed_logger(Box::new(logger))
        .map(|()| log::set_max_level(LevelFilter::Info))
        .map_err(Error::from)
}

#[cfg(test)]
mod test {
    use std::env;

    use super::{init, SimpleLogger};

    #[test]
    fn trace_log() {
        env::set_var("CPP_LINTER_COLOR", "true");
        init().unwrap_or(());
        assert!(SimpleLogger::level_color(&log::Level::Trace).contains("TRACE"));
        log::set_max_level(log::LevelFilter::Trace);
        log::trace!("A dummy log statement for code coverage");
    }
}