lightspeed_logger/
config.rs

1use crate::LoggerError;
2use serde::Deserialize;
3use std::str::FromStr;
4
5/// Defines the Logger configuration.
6#[derive(Debug, Clone, Deserialize)]
7#[serde(default)]
8pub struct LoggerConfig {
9    /// Sets the logger [`EnvFilter`].
10    /// Valid values: trace, debug, info, warn, error
11    /// Example of a valid filter: "warn,my_crate=info,my_crate::my_mod=debug,[my_span]=trace"
12    pub env_filter: String,
13    pub stdout_output: StandardOutputConfig,
14    pub file_output: FileOutputConfig,
15}
16
17impl Default for LoggerConfig {
18    fn default() -> Self {
19        Self {
20            env_filter: "debug".to_owned(),
21            stdout_output: StandardOutputConfig::default(),
22            file_output: FileOutputConfig::default(),
23        }
24    }
25}
26
27#[derive(Debug, Clone, Deserialize)]
28#[serde(default)]
29pub struct StandardOutputConfig {
30    /// Determines whether the Logger should print to standard output.
31    /// Valid values: true, false
32    pub stdout_enabled: bool,
33    pub stdout_use_ansi_colors: bool,
34}
35
36impl Default for StandardOutputConfig {
37    fn default() -> Self {
38        Self { stdout_use_ansi_colors: true, stdout_enabled: true }
39    }
40}
41
42#[derive(Debug, Clone, Deserialize)]
43#[serde(default)]
44pub struct FileOutputConfig {
45    /// Determines whether the Logger should print to a file.
46    /// Valid values: true, false
47    pub file_output_enabled: bool,
48
49    /// The log file location
50    pub file_output_directory: String,
51
52    /// The log file name's _prefix_
53    pub file_output_name_prefix: String,
54
55    /// The log file rotation strategy
56    pub file_output_rotation: Rotation,
57}
58
59impl Default for FileOutputConfig {
60    fn default() -> Self {
61        Self {
62            file_output_enabled: false,
63            file_output_directory: ".".to_owned(),
64            file_output_name_prefix: "output.log".to_owned(),
65            file_output_rotation: Rotation::Never,
66        }
67    }
68}
69
70#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize)]
71pub enum Rotation {
72    Minutely,
73    Hourly,
74    Daily,
75    Never,
76}
77
78impl FromStr for Rotation {
79    type Err = LoggerError;
80
81    fn from_str(val: &str) -> Result<Self, Self::Err> {
82        match val.to_lowercase().as_ref() {
83            "minutely" => Ok(Rotation::Minutely),
84            "hourly" => Ok(Rotation::Hourly),
85            "daily" => Ok(Rotation::Daily),
86            "never" => Ok(Rotation::Never),
87            _ => Err(LoggerError::LoggerConfigurationError { message: format!("Could not parse rotation [{val}]") }),
88        }
89    }
90}
91
92impl Rotation {
93    pub fn to_tracing_appender_rotation(&self) -> tracing_appender::rolling::Rotation {
94        match self {
95            Rotation::Minutely => tracing_appender::rolling::Rotation::MINUTELY,
96            Rotation::Hourly => tracing_appender::rolling::Rotation::HOURLY,
97            Rotation::Daily => tracing_appender::rolling::Rotation::DAILY,
98            Rotation::Never => tracing_appender::rolling::Rotation::NEVER,
99        }
100    }
101}
102
103#[cfg(test)]
104mod test {
105
106    use super::*;
107
108    #[test]
109    fn should_build_config() {
110        let config: LoggerConfig = config::Config::builder().build().unwrap().try_deserialize().unwrap();
111        assert!(config.stdout_output.stdout_enabled);
112    }
113}