json_log/
lib.rs

1mod msg;
2mod test_all;
3
4use log::{Metadata, Record};
5use serde::Serialize;
6
7#[non_exhaustive]
8pub struct JsonLogger;
9
10const LOGGER: JsonLogger = JsonLogger;
11
12impl log::Log for JsonLogger {
13    fn enabled(&self, _: &Metadata) -> bool {
14        true
15    }
16
17    fn log(&self, record: &Record) {
18        if !self.enabled(record.metadata()) {
19            return
20        }
21
22        let line = format!("{}", record.args());
23
24        LOGGER.do_log(record.level(), line);
25    }
26
27    fn flush(&self) {}
28}
29
30impl JsonLogger {
31    #[allow(clippy::only_used_in_recursion)]
32    fn do_log<T: Serialize>(&self, level: log::Level, custom: T) {
33        let msg = msg::Msg::new(level, &custom);
34
35        match serde_json::to_string(&msg) {
36            Ok(line) => {
37                if level <= log::Level::Warn {
38                    println!("{}", line);
39                } else {
40                    eprintln!("{}", line);
41                }
42            },
43            Err(e) => {
44                let marshal_error = format!("Marshal Error: {}", e);
45                self.do_log(level, marshal_error)
46            }
47        }
48    }
49}
50
51impl JsonLogger {
52    #[inline]
53    fn should_log(&self, level: log::LevelFilter) -> bool {
54        if log::max_level() == log::LevelFilter::Off {
55            return false;
56        }
57
58        return log::max_level() >= level;
59    }
60
61    #[inline]
62    pub fn trace<T: Serialize>(&self, msg: T) {
63        if !self.should_log(log::LevelFilter::Trace) {
64            return
65        }
66
67        self.do_log(log::Level::Trace, msg)
68    }
69
70    #[inline]
71    pub fn debug<T: Serialize>(&self, msg: T) {
72        if !self.should_log(log::LevelFilter::Debug) {
73            return
74        }
75
76        self.do_log(log::Level::Debug, msg)
77    }
78
79    #[inline]
80    pub fn info<T: Serialize>(&self, msg: T) {
81        if !self.should_log(log::LevelFilter::Info) {
82            return
83        }
84
85        self.do_log(log::Level::Info, msg)
86    }
87
88    #[inline]
89    pub fn warn<T: Serialize>(&self, msg: T) {
90        if !self.should_log(log::LevelFilter::Warn) {
91            return
92        }
93
94        self.do_log(log::Level::Warn, msg)
95    }
96
97    #[inline]
98    pub fn error<T: Serialize>(&self, msg: T) {
99        if !self.should_log(log::LevelFilter::Error) {
100            return
101        }
102
103        self.do_log(log::Level::Error, msg)
104    }
105}
106
107pub const fn get_default_logger() -> &'static JsonLogger {
108    &LOGGER
109}
110
111pub fn init_with_level(level: log::LevelFilter) -> Result<(), log::SetLoggerError> {
112    log::set_logger(&LOGGER)
113        .map(|()| log::set_max_level(level))
114}
115
116pub fn init_from_env() -> Result<(), log::SetLoggerError> {
117    let level = match std::env::var("RUST_LOG") {
118        Err(_) => log::LevelFilter::Off,
119        Ok(s) => match s.to_lowercase().as_str() {
120            "trace" => log::LevelFilter::Trace,
121            "debug" => log::LevelFilter::Debug,
122            "info" => log::LevelFilter::Info,
123            "warn" => log::LevelFilter::Warn,
124            "error" => log::LevelFilter::Error,
125            _ => log::LevelFilter::Off,
126        }
127    };
128
129    init_with_level(level)
130}