cargo hollywood
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use comat::{cformat_args, cwriteln};
use log::{Level, Metadata, Record};
use std::{
    fs::File,
    io::Write,
    path::PathBuf,
    sync::{Mutex, OnceLock, PoisonError},
    time::Instant,
};

#[derive(Debug)]
pub struct Logger {
    start: Instant,
    file: Mutex<File>,
}

impl Logger {
    pub fn init(level: Level, f: PathBuf) {
        static LOGGER: OnceLock<Logger> = OnceLock::new();
        LOGGER
            .set(Self {
                start: Instant::now(),
                file: Mutex::new(File::create(f).unwrap()),
            })
            .unwrap();
        log::set_logger(LOGGER.get().unwrap())
            .map(|()| log::set_max_level(level.to_level_filter()))
            .unwrap();
    }
}

impl log::Log for Logger {
    fn enabled(&self, _: &Metadata) -> bool {
        true
    }

    fn log(&self, record: &Record) {
        cwriteln!(
            self.file.lock().unwrap_or_else(PoisonError::into_inner),
            "[{} {:bold_blue}:{:blue}{green}@{:yellow}] {}",
            match record.level() {
                Level::Error => cformat_args!("{bold_red}err{reset}"),
                Level::Warn => cformat_args!("{bold_yellow}wrn{reset}"),
                Level::Trace => cformat_args!("{magenta}trc{reset}"),
                Level::Debug => cformat_args!("{green}dbg{reset}"),
                Level::Info => cformat_args!("{blue}inf{reset}"),
            },
            record.file().unwrap_or("<source>"),
            record.line().unwrap_or(0),
            humantime::format_duration(self.start.elapsed()),
            record.args(),
        )
        .unwrap();
    }

    fn flush(&self) {}
}