tracing_setup/
file_logging_configuration.rs

1crate::ix!();
2
3pub struct FileLoggingConfiguration {
4    log_path:  Option<PathBuf>,
5    log_level: Level,
6    rotation:  Option<Rotation>,
7    temporary: bool,
8}
9
10impl FileLoggingConfiguration {
11
12    pub fn default_temporary() -> Self {
13        Self {
14            log_path:  Some(PathBuf::from("default.log")),
15            log_level: Level::INFO,
16            rotation:  Some(Rotation::DAILY),
17            temporary: true,
18        }
19    }
20
21    pub fn new(log_path: Option<PathBuf>, log_level: Level, rotation: Option<Rotation>) -> Self {
22        Self {
23            log_path,
24            log_level,
25            rotation,
26            temporary: false,
27        }
28    }
29
30    pub fn new_temporary(
31        log_path:  Option<PathBuf>, 
32        log_level: Level, 
33        rotation:  Option<Rotation>
34
35    ) -> Self {
36
37        Self {
38            log_path,
39            log_level,
40            rotation,
41            temporary: true,
42        }
43    }
44
45    pub fn create_writer(&self) -> BoxMakeWriter {
46        match &self.log_path {
47            Some(log_path) => {
48                if let Some(rotation) = &self.rotation {
49                    let file_appender = RollingFileAppender::new(rotation.clone(), ".", log_path);
50                    BoxMakeWriter::new(file_appender)
51                } else {
52                    let file = File::create(log_path).expect("Could not create log file");
53                    BoxMakeWriter::new(Arc::new(file))
54                }
55            }
56            None => BoxMakeWriter::new(io::stderr),
57        }
58    }
59
60    //----------------------------------------[access]
61    pub fn log_level(&self) -> &Level {
62        &self.log_level
63    }
64
65    pub fn log_path(&self) -> &Option<PathBuf> {
66        &self.log_path
67    }
68
69    pub fn rotation(&self) -> &Option<Rotation> {
70        &self.rotation
71    }
72
73    pub fn info_level(&self) -> bool {
74        self.log_level == Level::INFO
75    }
76
77    pub fn log_path_root_is(&self, path: impl AsRef<Path>) -> bool {
78        self.log_path == Some(path.as_ref().to_path_buf())
79    }
80
81    pub fn rotates_daily(&self) -> bool {
82        matches!(self.rotation(), Some(Rotation::DAILY))
83    }
84
85    pub fn remove_logs(&self) {
86        if let Some(path) = &self.log_path {
87            match std::fs::remove_file(path) {
88                Ok(()) => {},
89                Err(ref e) if e.kind() == std::io::ErrorKind::NotFound => {
90                    // File does not exist, no problem
91                },
92                Err(e) => {
93                    panic!("Failed to remove log file: {:?}", e);
94                }
95            }
96        }
97    }
98
99    pub fn is_temporary(&self) -> bool {
100        self.temporary
101    }
102}
103
104impl Default for FileLoggingConfiguration {
105
106    fn default() -> Self {
107        Self {
108            log_path: Some(PathBuf::from("default.log")),
109            log_level: Level::INFO,
110            rotation: Some(Rotation::DAILY),
111            temporary: false,
112        }
113    }
114}
115
116impl Drop for FileLoggingConfiguration {
117
118    fn drop(&mut self) {
119        if self.is_temporary() {
120            self.remove_logs();
121        }
122    }
123}