1use log::{kv, LevelFilter, Log, Metadata, Record};
4use std::io::{self, StdoutLock, Write};
5use std::time;
6
7pub(crate) fn start(level: LevelFilter) {
9 let logger = Box::new(Logger {});
10 log::set_boxed_logger(logger).expect("Could not start logging");
11 log::set_max_level(level);
12}
13
14#[derive(Debug)]
15pub(crate) struct Logger {}
16
17impl Log for Logger {
18 fn enabled(&self, metadata: &Metadata<'_>) -> bool {
19 metadata.level() <= log::max_level()
20 }
21
22 fn log(&self, record: &Record<'_>) {
23 if self.enabled(record.metadata()) {
24 let stdout = io::stdout();
25 let mut handle = stdout.lock();
26 let level = get_level(record.level());
27 let time = time::UNIX_EPOCH.elapsed().unwrap().as_millis();
28 write!(&mut handle, "{{\"level\":{},\"time\":{},\"msg\":", level, time).unwrap();
29 serde_json::to_writer(&mut handle, record.args()).unwrap();
30 format_kv_pairs(&mut handle, &record);
31 writeln!(&mut handle, "}}").unwrap();
32 }
33 }
34 fn flush(&self) {}
35}
36
37fn get_level(level: log::Level) -> u8 {
38 use log::Level::*;
39 match level {
40 Trace => 10,
41 Debug => 20,
42 Info => 30,
43 Warn => 40,
44 Error => 50,
45 }
46}
47
48fn format_kv_pairs<'b>(mut out: &mut StdoutLock<'b>, record: &Record) {
49 struct Visitor<'a, 'b> {
50 string: &'a mut StdoutLock<'b>,
51 }
52
53 impl<'kvs, 'a, 'b> kv::Visitor<'kvs> for Visitor<'a, 'b> {
54 fn visit_pair(
55 &mut self,
56 key: kv::Key<'kvs>,
57 val: kv::Value<'kvs>,
58 ) -> Result<(), kv::Error> {
59 write!(self.string, ",\"{}\":\"{}\"", key, val)?;
60 Ok(())
61 }
62 }
63
64 let mut visitor = Visitor { string: &mut out };
65 record.key_values().visit(&mut visitor).unwrap();
66}