|
1 | 1 | use crate::files::config::get_config;
|
2 |
| -use colored::Colorize; |
3 |
| -use env_logger::{Builder, Target}; |
4 |
| -use log::Level; |
5 |
| -use log::LevelFilter; |
6 |
| -use std::env; |
| 2 | +use crate::files::variables::AppConfig; |
| 3 | +use chrono::Local; |
| 4 | +use log::{Level, LevelFilter, Log, Metadata, Record}; |
7 | 5 | use std::error::Error;
|
| 6 | +use std::fs::{File, OpenOptions}; |
8 | 7 | use std::io::Write;
|
| 8 | +use std::sync::{Arc, Mutex}; |
9 | 9 |
|
10 | 10 | pub fn setup_logger() -> Result<(), Box<dyn Error>> {
|
11 |
| - let log_level = match get_config() { |
12 |
| - Ok(config) => match config.log_level.to_lowercase().as_str() { |
13 |
| - "info" => LevelFilter::Info, |
14 |
| - "warn" => LevelFilter::Warn, |
15 |
| - "debug" => LevelFilter::Debug, |
16 |
| - "trace" => LevelFilter::Trace, |
17 |
| - _ => LevelFilter::Error, |
18 |
| - }, |
19 |
| - Err(_) => LevelFilter::Error, |
| 11 | + let (log_level, log_strategy) = if let Ok(config) = get_config() { |
| 12 | + ( |
| 13 | + match config.logs.level.to_lowercase().as_str() { |
| 14 | + "info" => LevelFilter::Info, |
| 15 | + "warn" => LevelFilter::Warn, |
| 16 | + "debug" => LevelFilter::Debug, |
| 17 | + "trace" => LevelFilter::Trace, |
| 18 | + _ => LevelFilter::Error, |
| 19 | + }, |
| 20 | + config.logs.strategy, |
| 21 | + ) |
| 22 | + } else { |
| 23 | + (LevelFilter::Info, "truncate".to_string()) |
20 | 24 | };
|
21 | 25 |
|
22 |
| - let mut builder = Builder::new(); |
| 26 | + let config = AppConfig::new(); |
| 27 | + let log_file_path = config.logs_path(); |
23 | 28 |
|
24 |
| - // Log the errors to stderr |
25 |
| - builder.filter_level(LevelFilter::Error); |
26 |
| - builder.target(Target::Stderr); |
| 29 | + // Ensure the logs directory exists |
| 30 | + if let Some(parent) = log_file_path.parent() { |
| 31 | + std::fs::create_dir_all(parent)?; |
| 32 | + } |
| 33 | + |
| 34 | + // Open or create the log file |
| 35 | + let file = OpenOptions::new() |
| 36 | + .create(true) |
| 37 | + .write(true) |
| 38 | + .truncate(log_strategy == "truncate") |
| 39 | + .append(log_strategy == "append") |
| 40 | + .open(log_file_path)?; |
| 41 | + |
| 42 | + let file = Arc::new(Mutex::new(file)); |
| 43 | + |
| 44 | + // Set the logger |
| 45 | + log::set_boxed_logger(Box::new(Logger { |
| 46 | + file: file.clone(), |
| 47 | + level: log_level, |
| 48 | + }))?; |
| 49 | + log::set_max_level(log_level); |
| 50 | + |
| 51 | + Ok(()) |
| 52 | +} |
| 53 | + |
| 54 | +struct Logger { |
| 55 | + file: Arc<Mutex<File>>, |
| 56 | + level: LevelFilter, |
| 57 | +} |
| 58 | + |
| 59 | +impl Log for Logger { |
| 60 | + fn enabled(&self, metadata: &Metadata) -> bool { |
| 61 | + metadata.level() <= self.level |
| 62 | + } |
| 63 | + |
| 64 | + fn log(&self, record: &Record) { |
| 65 | + if !self.enabled(record.metadata()) { |
| 66 | + return; |
| 67 | + } |
| 68 | + |
| 69 | + let now = Local::now(); |
| 70 | + let timestamp = now.format("%Y-%m-%d %H:%M:%S%.3f"); |
27 | 71 |
|
28 |
| - // Customize format |
29 |
| - builder.format(move |buf, record| { |
30 | 72 | let file_info = match (record.file(), record.line()) {
|
31 | 73 | (Some(file), Some(line)) => format!("{}:{}", file, line),
|
32 | 74 | _ => String::from("unknown"),
|
33 | 75 | };
|
34 | 76 |
|
35 |
| - let now = chrono::Local::now(); |
36 |
| - let timestamp = now.format("%Y-%m-%d %H:%M:%S%.3f"); |
| 77 | + let log_line = format!( |
| 78 | + "[{} {} {}] - {}", |
| 79 | + timestamp, |
| 80 | + record.level(), |
| 81 | + file_info, |
| 82 | + record.args() |
| 83 | + ); |
| 84 | + |
| 85 | + if self.level <= LevelFilter::Debug |
| 86 | + && (record.level() == Level::Info |
| 87 | + || record.level() == Level::Warn |
| 88 | + || record.level() == Level::Error) |
| 89 | + { |
| 90 | + let mut file = self.file.lock().unwrap(); |
| 91 | + writeln!(file, "{}", log_line).unwrap(); |
| 92 | + } |
37 | 93 |
|
38 | 94 | match record.level() {
|
39 |
| - Level::Trace => { |
40 |
| - let log_line = format!("[{} TRACE {}] - {}", timestamp, file_info, record.args()); |
41 |
| - writeln!(buf, "{}", log_line.italic()) |
42 |
| - } |
43 |
| - Level::Debug => { |
44 |
| - let log_line = format!("[{} DEBUG {}] - {}", timestamp, file_info, record.args()); |
45 |
| - writeln!(buf, "{}", log_line.italic()) |
| 95 | + Level::Trace | Level::Debug => { |
| 96 | + let mut file = self.file.lock().unwrap(); |
| 97 | + writeln!(file, "{}", log_line).unwrap(); |
46 | 98 | }
|
47 | 99 | Level::Info => {
|
48 |
| - let log_line = format!("{}", record.args()); |
49 |
| - writeln!(buf, "{}", log_line) |
| 100 | + println!("{}", record.args()); |
50 | 101 | }
|
51 | 102 | Level::Warn => {
|
52 |
| - let log_line = format!("{}", record.args()); |
53 |
| - writeln!(buf, "{}", log_line.underline()) |
| 103 | + println!("{}", record.args()); |
54 | 104 | }
|
55 | 105 | Level::Error => {
|
56 |
| - let log_line = format!("{}", record.args()); |
57 |
| - writeln!(buf, "{}", log_line.red().bold()) |
| 106 | + eprintln!("{}", record.args()); |
58 | 107 | }
|
59 | 108 | }
|
60 |
| - }); |
| 109 | + } |
61 | 110 |
|
62 |
| - // Log all other stuff to stdout |
63 |
| - builder.filter(Some("hbox"), log_level); |
64 |
| - builder.target(Target::Stdout); |
65 |
| - |
66 |
| - if env::var("RUST_LOG").is_ok() { |
67 |
| - builder.parse_filters(&env::var("RUST_LOG").unwrap()); |
68 |
| - }; |
69 |
| - |
70 |
| - builder.init(); |
71 |
| - |
72 |
| - Ok(()) |
| 111 | + fn flush(&self) { |
| 112 | + let mut file = self.file.lock().unwrap(); |
| 113 | + file.flush().unwrap(); |
| 114 | + } |
73 | 115 | }
|
0 commit comments