lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

options.rs (3014B)


      1 use chrono::Local;
      2 use std::path::PathBuf;
      3 
      4 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
      5 pub enum LogFileLayout {
      6     PrefixedDate,
      7     DatedFileName,
      8 }
      9 
     10 #[derive(Debug, Clone)]
     11 pub struct LoggingOptions {
     12     pub dir: Option<PathBuf>,
     13     pub file_name: String,
     14     pub stdout: bool,
     15     pub default_level: Option<String>,
     16     pub file_layout: LogFileLayout,
     17 }
     18 
     19 impl LoggingOptions {
     20     pub fn also_stdout(&self) -> bool {
     21         self.stdout
     22     }
     23 
     24     pub fn resolved_log_file_name_for_date(&self, date: &str) -> String {
     25         match self.file_layout {
     26             LogFileLayout::PrefixedDate => format!("{}.{}", self.file_name, date),
     27             LogFileLayout::DatedFileName => format!("{}.{}", date, self.file_name),
     28         }
     29     }
     30 
     31     pub fn resolved_current_log_file_path(&self) -> Option<PathBuf> {
     32         let dir = self.dir.as_ref()?;
     33         let date = Local::now().format("%Y-%m-%d").to_string();
     34         Some(dir.join(self.resolved_log_file_name_for_date(date.as_str())))
     35     }
     36 }
     37 
     38 impl Default for LoggingOptions {
     39     fn default() -> Self {
     40         Self {
     41             dir: None,
     42             file_name: "radroots.log".into(),
     43             stdout: true,
     44             default_level: None,
     45             file_layout: LogFileLayout::PrefixedDate,
     46         }
     47     }
     48 }
     49 
     50 #[cfg(test)]
     51 mod tests {
     52     use super::{LogFileLayout, LoggingOptions};
     53     use std::path::PathBuf;
     54 
     55     #[test]
     56     fn prefixed_date_layout_resolves_expected_file_name() {
     57         let options = LoggingOptions {
     58             dir: Some(PathBuf::from("/tmp/logs")),
     59             file_name: "myc.log".to_owned(),
     60             stdout: false,
     61             default_level: None,
     62             file_layout: LogFileLayout::PrefixedDate,
     63         };
     64 
     65         assert_eq!(
     66             options.resolved_log_file_name_for_date("2026-03-23"),
     67             "myc.log.2026-03-23"
     68         );
     69     }
     70 
     71     #[test]
     72     fn dated_file_name_layout_resolves_expected_file_name() {
     73         let options = LoggingOptions {
     74             dir: Some(PathBuf::from("/tmp/logs")),
     75             file_name: "log".to_owned(),
     76             stdout: false,
     77             default_level: None,
     78             file_layout: LogFileLayout::DatedFileName,
     79         };
     80 
     81         assert_eq!(
     82             options.resolved_log_file_name_for_date("2026-03-23"),
     83             "2026-03-23.log"
     84         );
     85     }
     86 
     87     #[test]
     88     fn current_log_file_path_joins_dir_and_layout_shape() {
     89         let options = LoggingOptions {
     90             dir: Some(PathBuf::from("/tmp/logs")),
     91             file_name: "log".to_owned(),
     92             stdout: false,
     93             default_level: None,
     94             file_layout: LogFileLayout::DatedFileName,
     95         };
     96 
     97         let path = options
     98             .resolved_current_log_file_path()
     99             .expect("resolved path");
    100 
    101         assert_eq!(path.parent(), Some(PathBuf::from("/tmp/logs").as_path()));
    102         assert!(
    103             path.file_name()
    104                 .and_then(|value| value.to_str())
    105                 .is_some_and(|value| value.ends_with(".log"))
    106         );
    107     }
    108 }