Skip to main content

xan_log/
lib.rs

1use log::{Level, LevelFilter, Log, Metadata, Record, SetLoggerError};
2
3#[allow(dead_code)]
4static DEFAULT_BG_RED_TEXT: &str = "\x1b[31m";
5#[allow(dead_code)]
6static DEFAULT_BG_GREEN_TEXT: &str = "\x1b[32m";
7#[allow(dead_code)]
8static DEFAULT_BG_YELLOW_TEXT: &str = "\x1b[33m";
9#[allow(dead_code)]
10static DEFAULT_BG_BLUE_TEXT: &str = "\x1b[34m";
11static DEFAULT_BG_GRAY_TEXT: &str = "\x1b[90m";
12
13static RED_BG_BLACK_TEXT: &str = "\x1b[41;30m";
14static YELLOW_BG_BLACK_TEXT: &str = "\x1b[43;30m";
15static BLUE_BG_WHITE_TEXT: &str = "\x1b[44;37m";
16static GREEN_BG_BLACK_TEXT: &str = "\x1b[42;30m";
17static CYAN_BG_BLACK_TEXT: &str = "\x1b[46;30m";
18static DEFAULT_BG_DEFAULT_TEXT: &str = "\x1b[49;39m";
19
20pub extern crate log;
21
22#[cfg(not(feature = "tracing"))]
23static LOGGER: XanLogger = XanLogger {
24    log_level: LevelFilter::Off,
25};
26
27pub struct XanLogger {
28    log_level: LevelFilter,
29}
30
31impl XanLogger {
32    pub fn new(log_level: LevelFilter) -> Self {
33        Self { log_level }
34    }
35}
36
37impl Log for XanLogger {
38    fn enabled(&self, metadata: &Metadata) -> bool {
39        metadata.level() <= self.log_level
40    }
41
42    fn log(&self, r: &Record) {
43        let metadata = r.metadata();
44        let args = r.args();
45        let module_path = r.module_path();
46        let file = r.file();
47        let line = r.line();
48        let kv = r.key_values();
49        println!(
50            "[{}] [{}@{}:{}] [target:{}] [module_path:{}] {}",
51            chrono::Utc::now()
52                .format("%Y-%m-%dT%H:%M:%S.%3fZ")
53                .to_string(),
54            if let Some(lv) = kv.get("level".into()) {
55                format!(
56                    "{}{}{}",
57                    CYAN_BG_BLACK_TEXT,
58                    lv.to_string().to_uppercase(),
59                    DEFAULT_BG_DEFAULT_TEXT
60                )
61            } else {
62                match metadata.level() {
63                    Level::Error => {
64                        format!("{}ERROR{}", RED_BG_BLACK_TEXT, DEFAULT_BG_DEFAULT_TEXT)
65                    }
66                    Level::Warn => {
67                        format!("{}WARN{}", YELLOW_BG_BLACK_TEXT, DEFAULT_BG_DEFAULT_TEXT)
68                    }
69                    Level::Info => format!("{}INFO{}", BLUE_BG_WHITE_TEXT, DEFAULT_BG_DEFAULT_TEXT),
70                    Level::Debug => {
71                        format!("{}DEBUG{}", GREEN_BG_BLACK_TEXT, DEFAULT_BG_DEFAULT_TEXT)
72                    }
73                    Level::Trace => {
74                        format!("{}TRACE{}", DEFAULT_BG_GRAY_TEXT, DEFAULT_BG_DEFAULT_TEXT)
75                    }
76                }
77            },
78            file.unwrap_or(""),
79            line.unwrap_or(0),
80            metadata.target().to_string(),
81            module_path.unwrap_or(""),
82            args,
83        );
84    }
85
86    fn flush(&self) {}
87}
88
89#[cfg(not(feature = "tracing"))]
90pub fn init_logger() -> Result<(), SetLoggerError> {
91    let log_level = std::env::var("LOG_LEVEL").unwrap_or("off".to_string());
92    let log_level = match log_level.to_lowercase().as_str() {
93        "trace" => LevelFilter::Trace,
94        "debug" => LevelFilter::Debug,
95        "info" => LevelFilter::Info,
96        "warn" => LevelFilter::Warn,
97        "error" => LevelFilter::Error,
98        _ => LevelFilter::Off,
99    };
100    log::set_logger(&LOGGER).map(|()| log::set_max_level(log_level))
101}
102
103#[cfg(feature = "tracing")]
104pub fn init_logger() -> Result<(), SetLoggerError> {
105    let log_level = std::env::var("LOG_LEVEL").unwrap_or("off".to_string());
106
107    let env_filter = tracing_subscriber::EnvFilter::try_from_default_env()
108        .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(log_level));
109
110    let _ = tracing_subscriber::fmt()
111        .with_env_filter(env_filter)
112        .try_init();
113
114    Ok(())
115}
116
117#[test]
118fn test() {
119    unsafe {
120        std::env::set_var("LOG_LEVEL", "INFO");
121    }
122    let _ = init_logger();
123    log::error!("This is an error message");
124    log::warn!("This is a warning message");
125    log::info!("This is an info message");
126    log::debug!("This is a debug message");
127    log::trace!("This is a trace message");
128    log::log!(target: "my_target", Level::Info, level = "CUSTOM"; "test log {}", "TEST");
129}