1use chrono::Local;
6use once_cell::sync::Lazy;
7use serde::Deserialize;
8use std::io::Write;
9use std::sync::Mutex;
10use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
13#[serde(rename_all = "lowercase")]
14pub enum LogLevel {
15 Error, Warn, Info, Debug, }
20
21impl LogLevel {
22 fn as_u8(&self) -> u8 {
23 match self {
24 LogLevel::Error => 1,
25 LogLevel::Warn => 2,
26 LogLevel::Info => 3,
27 LogLevel::Debug => 4,
28 }
29 }
30}
31
32static LOG_LEVEL: Lazy<Mutex<LogLevel>> = Lazy::new(|| Mutex::new(LogLevel::Info));
33
34pub fn set_log_level(new_level: LogLevel) {
35 let mut level = LOG_LEVEL.lock().unwrap();
36 *level = new_level;
37}
38
39pub fn log(level: LogLevel, content: &str) {
40 let current_level = LOG_LEVEL.lock().unwrap();
41 if level.as_u8() > current_level.as_u8() {
42 return;
43 }
44
45 let mut stream = match level {
46 LogLevel::Warn | LogLevel::Error => StandardStream::stderr(ColorChoice::Auto),
47 _ => StandardStream::stdout(ColorChoice::Auto),
48 };
49
50 let now = Local::now().format("%H:%M:%S").to_string();
51
52 match level {
53 LogLevel::Info => {
54 let _ = stream.set_color(ColorSpec::new().set_fg(Some(Color::White)));
55 let _ = write!(stream, "{} ", now);
56 let _ = stream.reset();
57 let _ = writeln!(stream, "{}", content);
58 }
59 LogLevel::Debug => {
60 let _ = stream.set_color(ColorSpec::new().set_fg(Some(Color::Blue)));
61 let _ = writeln!(stream, "{} {}", now, content);
62 }
63 LogLevel::Warn => {
64 let _ = stream.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)));
65 let _ = writeln!(stream, "{} {}", now, content);
66 }
67 LogLevel::Error => {
68 let _ = stream.set_color(ColorSpec::new().set_fg(Some(Color::Red)));
69 let _ = writeln!(stream, "{} {}", now, content);
70 }
71 }
72
73 let _ = stream.reset();
74}