1use crate::{
2 FileError,
3 WriteMode,
4 copy_file,
5 exists,
6 write_string,
7};
8use chrono::Local;
9use std::sync::OnceLock;
10
11static LOG_FILE_PATH: OnceLock<Option<String>> = OnceLock::new();
12static DUMP_TO_STDOUT: OnceLock<bool> = OnceLock::new();
13static DUMP_TO_STDERR: OnceLock<bool> = OnceLock::new();
14
15pub fn initialize_log(
16 dump_to_file: Option<String>,
17 dump_to_stdout: bool,
18 dump_to_stderr: bool,
19 keep_previous_file: bool,
20) -> Result<(), FileError> {
21 if let Some(path) = &dump_to_file {
22 if !keep_previous_file {
23 if exists(path) {
24 copy_file(path, &format!("{path}-backup"))?;
25 }
26
27 write_string(path, "", WriteMode::Atomic)?;
28 }
29 }
30
31 LOG_FILE_PATH.set(dump_to_file).unwrap();
32 DUMP_TO_STDOUT.set(dump_to_stdout).unwrap();
33 DUMP_TO_STDERR.set(dump_to_stderr).unwrap();
34 Ok(())
35}
36
37fn get_log_file_path() -> Option<String> {
38 LOG_FILE_PATH.get().map(|p| p.clone()).unwrap_or(None)
39}
40
41pub fn write_log(owner: &str, msg: &str) {
42 let dump_to_stdout = DUMP_TO_STDOUT.get().map(|b| *b).unwrap_or(false);
43 let dump_to_stderr = DUMP_TO_STDERR.get().map(|b| *b).unwrap_or(false);
44
45 let path = get_log_file_path();
46
47 if path.is_none() && !dump_to_stdout && !dump_to_stderr {
48 return;
49 }
50
51 let message = format!(
52 "{} | {} | {msg}\n",
53 Local::now().to_rfc2822(),
54 if owner.len() < 32 {
55 format!("{}{owner}", " ".repeat(32 - owner.len()))
56 } else {
57 owner.to_string()
58 },
59 );
60
61 if let Some(path) = path {
62 write_string(
63 &path,
64 &message,
65 WriteMode::AlwaysAppend,
66 ).unwrap();
67 }
68
69 if dump_to_stdout {
70 print!("{message}");
71 }
72
73 if dump_to_stderr {
74 eprint!("{message}");
75 }
76}