1#![allow(clippy::unwrap_used)] use chrono::Local;
3use log::{Level, LevelFilter, Metadata, Record};
4use once_cell::sync::Lazy;
5use std::fs::OpenOptions;
6use std::io::Write;
7use std::sync::Mutex;
8
9struct GitIrisLogger;
10
11static LOGGER: GitIrisLogger = GitIrisLogger;
12static LOGGING_ENABLED: Lazy<Mutex<bool>> = Lazy::new(|| Mutex::new(false));
13static LOG_FILE: Lazy<Mutex<Option<std::fs::File>>> = Lazy::new(|| Mutex::new(None));
14static LOG_TO_STDOUT: Lazy<Mutex<bool>> = Lazy::new(|| Mutex::new(false));
15
16impl log::Log for GitIrisLogger {
17 fn enabled(&self, metadata: &Metadata) -> bool {
18 *LOGGING_ENABLED.lock().unwrap() && metadata.level() <= Level::Debug
19 }
20
21 fn log(&self, record: &Record) {
22 if self.enabled(record.metadata()) {
23 let timestamp = Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
24 let message = format!("{} {} - {}\n", timestamp, record.level(), record.args());
25
26 if let Some(file) = LOG_FILE.lock().unwrap().as_mut() {
27 let _ = file.write_all(message.as_bytes());
28 let _ = file.flush();
29 }
30
31 if *LOG_TO_STDOUT.lock().unwrap() {
32 print!("{message}");
33 }
34 }
35 }
36
37 fn flush(&self) {}
38}
39
40pub fn init() -> Result<(), log::SetLoggerError> {
41 log::set_logger(&LOGGER).map(|()| log::set_max_level(LevelFilter::Debug))
42}
43
44pub fn enable_logging() {
45 let mut logging_enabled = LOGGING_ENABLED.lock().unwrap();
46 *logging_enabled = true;
47}
48
49pub fn disable_logging() {
50 let mut logging_enabled = LOGGING_ENABLED.lock().unwrap();
51 *logging_enabled = false;
52}
53
54pub fn set_log_file(file_path: &str) -> std::io::Result<()> {
55 let file = OpenOptions::new()
56 .create(true)
57 .append(true)
58 .open(file_path)?;
59
60 let mut log_file = LOG_FILE.lock().unwrap();
61 *log_file = Some(file);
62 Ok(())
63}
64
65pub fn set_log_to_stdout(enabled: bool) {
66 let mut log_to_stdout = LOG_TO_STDOUT.lock().unwrap();
67 *log_to_stdout = enabled;
68}
69
70#[macro_export]
71macro_rules! log_debug {
72 ($($arg:tt)*) => {
73 log::debug!($($arg)*)
74 };
75}
76
77#[macro_export]
78macro_rules! log_error {
79 ($($arg:tt)*) => {
80 log::error!($($arg)*)
81 };
82}