scsys_config/types/
log_level.rs

1/*
2    Appellation: log_level <module>
3    Contrib: @FL03
4*/
5#[derive(
6    Clone,
7    Copy,
8    Debug,
9    Default,
10    Eq,
11    Hash,
12    Ord,
13    PartialEq,
14    PartialOrd,
15    strum::AsRefStr,
16    strum::Display,
17    strum::EnumCount,
18    strum::EnumIs,
19    strum::EnumIter,
20    strum::EnumString,
21    strum::VariantNames,
22)]
23#[cfg_attr(
24    feature = "serde",
25    derive(serde::Deserialize, serde::Serialize),
26    serde(rename_all = "lowercase")
27)]
28#[strum(serialize_all = "lowercase")]
29pub enum LogLevel {
30    /// the debug designation (rank 1) often used for development
31    Debug = 1,
32    /// the error designation (rank 4) is used for errors that are not fatal to the program
33    Error = 4,
34    /// the info designation (rank 2) is used for useful information
35    #[default]
36    Info = 2,
37    /// the trace designation (rank 0) is used for very low-level (often extremely verbose)
38    /// information
39    Trace = 0,
40    /// The warn designation (rank 3)
41    Warn = 3,
42    /// the off designation (rank -1) is used to turn off logging
43    Off = -1,
44}
45
46impl LogLevel {
47    pub fn from_isize(level: isize) -> Self {
48        match level % 5 {
49            0 => Self::Trace,
50            1 => Self::Debug,
51            2 => Self::Info,
52            3 => Self::Warn,
53            4 => Self::Error,
54            lvl if lvl < 0 => Self::Off,
55            _ => unreachable!(
56                "modular arithmetic error; accepted values are between, but not including, the range of: (+/- 5)"
57            ),
58        }
59    }
60    /// returns true if the log-level is not [`Off`](LogLevel::Off)
61    pub fn is_enabled(&self) -> bool {
62        match self {
63            Self::Off => false,
64            _ => true,
65        }
66    }
67
68    pub fn as_log_string<T>(&self, name: T) -> String
69    where
70        T: core::fmt::Display,
71    {
72        format!("{name}={lvl}", lvl = self.as_ref())
73    }
74}
75
76unsafe impl Send for LogLevel {}
77
78unsafe impl Sync for LogLevel {}
79
80impl From<isize> for LogLevel {
81    fn from(level: isize) -> Self {
82        Self::from_isize(level)
83    }
84}
85
86impl From<LogLevel> for isize {
87    fn from(level: LogLevel) -> Self {
88        level as isize
89    }
90}
91
92#[cfg(feature = "config")]
93impl From<LogLevel> for config::Value {
94    fn from(level: LogLevel) -> Self {
95        level.to_string().into()
96    }
97}
98
99#[cfg(feature = "tracing")]
100mod impl_tracing {
101    use super::LogLevel;
102    use tracing::Level;
103
104    impl LogLevel {
105        pub fn from_tracing(level: Level) -> Self {
106            match level {
107                Level::DEBUG => Self::Debug,
108                Level::ERROR => Self::Error,
109                Level::INFO => Self::Info,
110                Level::TRACE => Self::Trace,
111                Level::WARN => Self::Warn,
112            }
113        }
114        /// convert the configured log level into a tracing [level](tracing::Level)
115        pub fn as_tracing_level(&self) -> Option<Level> {
116            match self {
117                Self::Debug => Some(Level::DEBUG),
118                Self::Error => Some(Level::ERROR),
119                Self::Info => Some(Level::INFO),
120                Self::Trace => Some(Level::TRACE),
121                Self::Warn => Some(Level::WARN),
122                Self::Off => None,
123            }
124        }
125    }
126
127    impl From<Level> for LogLevel {
128        fn from(level: Level) -> Self {
129            Self::from_tracing(level)
130        }
131    }
132
133    impl From<LogLevel> for Level {
134        fn from(level: LogLevel) -> Self {
135            level.as_tracing_level().unwrap_or(Level::INFO)
136        }
137    }
138}