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}