graph_simulation/utils/
logger.rs1use std::{env, fs::File, io, sync::{Mutex, OnceLock}};
2use env_logger::Target;
3use log::LevelFilter;
4
5struct MultiWriter {
7 file: Mutex<File>,
8 stdout: io::Stdout,
9}
10
11impl io::Write for MultiWriter {
12 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
13 let mut file = self.file.lock().unwrap();
15 file.write_all(buf)?;
16 self.stdout.write_all(buf)?;
17 Ok(buf.len())
18 }
19
20 fn flush(&mut self) -> io::Result<()> {
21 let mut file = self.file.lock().unwrap();
22 file.flush()?;
23 self.stdout.flush()?;
24 Ok(())
25 }
26}
27
28static LOGGER_INIT: OnceLock<()> = OnceLock::new();
30
31pub fn init_global_logger_once(output_file: &'static str) {
33 LOGGER_INIT.get_or_init(|| {
34 let log_file = File::create(output_file)
35 .expect("Failed to create log file");
36
37 let multi_writer = MultiWriter {
38 file: Mutex::new(log_file),
39 stdout: io::stdout(),
40 };
41
42 let level = if let Ok(level) = env::var("RUST_LOG") {
43 match level.to_lowercase().as_str() {
44 "error" => LevelFilter::Error,
45 "warn" | "warning" => LevelFilter::Warn,
46 "info" => LevelFilter::Info,
47 "debug" => LevelFilter::Debug,
48 "trace" => LevelFilter::Trace,
49 _ => LevelFilter::Info, }
51 } else {
52 LevelFilter::Info
53 };env_logger::Builder::new()
57 .target(Target::Pipe(Box::new(multi_writer)))
58 .filter_level(level)
59 .init();
60
61 log::info!("Logger initialized successfully");
62 });
63}