drive_abci/logging/
config.rs

1use crate::config::FromEnv;
2use crate::logging::level::LogLevel;
3use crate::logging::{LogDestination, LogFormat};
4use regex::Regex;
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8/// Logging configuration.
9#[derive(Serialize, Deserialize, Debug, Clone, Default)]
10pub struct LogConfig {
11    /// Destination of logs.
12    pub destination: LogDestination,
13    /// Log level
14    #[serde(default)]
15    pub level: LogLevel,
16    /// Whether or not to use colorful output; defaults to autodetect
17    #[serde(default)]
18    pub color: Option<bool>,
19    /// Output format to use.
20    #[serde(default)]
21    pub format: LogFormat,
22    /// Max number of daily files to store, excluding active one; only used when storing logs in file; defaults to 0 - rotation disabled
23    #[serde(default)]
24    pub max_files: usize,
25}
26
27/// Configuration of log destinations.
28///
29/// Logs can be sent to multiple destinations. Configuration of each of them is prefixed with `ABCI_LOG_<key>_`,
30/// where `<key>` is some arbitrary alphanumeric name of log configuration.
31///
32/// Key must match pattern `[A-Za-z0-9]+`.
33///
34/// Note that parsing of LogConfigs is implemented in [PlatformConfig::from_env()] due to limitations of [envy] crate.
35///
36/// ## Example
37///
38/// ```bash
39/// # First logger, logging to stderr on verbosity level 5
40/// ABCI_LOG_STDERR_DESTINATION=stderr
41/// ABCI_LOG_STDERR_LEVEL=trace
42///
43/// # Second logger, logging to stdout on verbosity level 1
44/// ABCI_LOG_STDOUT_DESTINATION=stdout
45/// ABCI_LOG_STDOUT_LEVEL=info
46/// ```
47///
48///
49/// [PlatformConfig::from_env()]: crate::config::PlatformConfig::from_env()
50pub type LogConfigs = HashMap<String, LogConfig>;
51
52impl FromEnv for LogConfigs {
53    /// create new object using values from environment variables
54    fn from_env() -> Result<Self, crate::error::Error>
55    where
56        Self: Sized,
57    {
58        let re: Regex = Regex::new(r"^ABCI_LOG_([0-9a-zA-Z]+)_DESTINATION$").unwrap();
59        let keys = std::env::vars().filter_map(|(key, _)| {
60            re.captures(&key)
61                .and_then(|capt| capt.get(1))
62                .map(|m| m.as_str().to_string())
63        });
64
65        let mut configs: HashMap<String, LogConfig> = HashMap::new();
66        for key in keys {
67            let config: LogConfig = envy::prefixed(format! {"ABCI_LOG_{}_", key.as_str()})
68                .from_env()
69                .map_err(crate::error::Error::from)?;
70
71            configs.insert(key, config);
72        }
73
74        Ok(configs)
75    }
76}