1use std::{io, time::SystemTime};
3
4use chrono::prelude::*;
5use colored::*;
6use log::{Level, Log, Metadata, Record, SetLoggerError};
7
8struct Logger {
9 level: Level,
10}
11
12impl Log for Logger {
13 fn enabled(&self, metadata: &Metadata) -> bool {
14 metadata.level() <= self.level
15 }
16
17 fn log(&self, record: &Record) {
18 if self.enabled(record.metadata()) {
19 let target = record.target();
20
21 if record.level() == Level::Error {
22 write(record, target, io::stderr());
23 } else {
24 write(record, target, io::stdout());
25 }
26
27 fn write(record: &log::Record, target: &str, mut stream: impl io::Write) {
28 let message = format!("{} {} {}", record.level(), target.bold(), record.args());
29 let message = match record.level() {
30 Level::Error => message.red(),
31 Level::Warn => message.yellow(),
32 Level::Info => message.normal(),
33 Level::Debug => message.dimmed(),
34 Level::Trace => message.white().dimmed(),
35 };
36
37 writeln!(
38 stream,
39 "{} {}",
40 DateTime::from(SystemTime::now())
41 .to_rfc3339_opts(SecondsFormat::Millis, true)
42 .white(),
43 message,
44 )
45 .expect("write shouldn't fail");
46 }
47 }
48 }
49
50 fn flush(&self) {}
51}
52
53pub fn init(level: Level) -> Result<(), SetLoggerError> {
55 let logger = Logger { level };
56
57 log::set_boxed_logger(Box::new(logger))?;
58 log::set_max_level(level.to_level_filter());
59
60 Ok(())
61}