Skip to main content

rustauth_core/env/
logger.rs

1use std::sync::Arc;
2
3/// Log severity level.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum LogLevel {
6    Debug,
7    Info,
8    Success,
9    Warn,
10    Error,
11}
12
13impl LogLevel {
14    const fn rank(self) -> u8 {
15        match self {
16            Self::Debug => 0,
17            Self::Info | Self::Success => 1,
18            Self::Warn => 2,
19            Self::Error => 3,
20        }
21    }
22
23    const fn handler_level(self) -> Self {
24        match self {
25            Self::Success => Self::Info,
26            level => level,
27        }
28    }
29}
30
31type LogHandler = dyn Fn(LogLevel, &str, &[&str]) + Send + Sync;
32
33/// Logger configuration.
34#[derive(Clone)]
35pub struct LoggerOptions {
36    level: LogLevel,
37    disabled: bool,
38    handler: Option<Arc<LogHandler>>,
39}
40
41impl LoggerOptions {
42    pub fn new(level: LogLevel) -> Self {
43        Self {
44            level,
45            disabled: false,
46            handler: None,
47        }
48    }
49
50    /// Whether logging is disabled.
51    pub fn is_disabled(&self) -> bool {
52        self.disabled
53    }
54
55    /// Configured minimum log level.
56    pub fn level(&self) -> LogLevel {
57        self.level
58    }
59
60    /// Whether a custom log handler is configured.
61    pub fn has_custom_handler(&self) -> bool {
62        self.handler.is_some()
63    }
64
65    pub fn disabled(mut self, disabled: bool) -> Self {
66        self.disabled = disabled;
67        self
68    }
69
70    pub fn with_handler(
71        mut self,
72        handler: impl Fn(LogLevel, &str, &[&str]) + Send + Sync + 'static,
73    ) -> Self {
74        self.handler = Some(Arc::new(handler));
75        self
76    }
77}
78
79impl Default for LoggerOptions {
80    fn default() -> Self {
81        Self::new(LogLevel::Warn)
82    }
83}
84
85/// Core logger.
86#[derive(Clone)]
87pub struct Logger {
88    options: LoggerOptions,
89}
90
91impl Logger {
92    pub fn level(&self) -> LogLevel {
93        self.options.level
94    }
95
96    pub fn debug(&self, message: &str, args: &[&str]) {
97        self.log(LogLevel::Debug, message, args);
98    }
99
100    pub fn info(&self, message: &str, args: &[&str]) {
101        self.log(LogLevel::Info, message, args);
102    }
103
104    pub fn success(&self, message: &str, args: &[&str]) {
105        self.log(LogLevel::Success, message, args);
106    }
107
108    pub fn warn(&self, message: &str, args: &[&str]) {
109        self.log(LogLevel::Warn, message, args);
110    }
111
112    pub fn error(&self, message: &str, args: &[&str]) {
113        self.log(LogLevel::Error, message, args);
114    }
115
116    fn log(&self, level: LogLevel, message: &str, args: &[&str]) {
117        if self.options.disabled || !should_publish_log(self.options.level, level) {
118            return;
119        }
120
121        if let Some(handler) = &self.options.handler {
122            handler(level.handler_level(), message, args);
123        }
124    }
125}
126
127/// Create a logger from options.
128pub fn create_logger(options: LoggerOptions) -> Logger {
129    Logger { options }
130}
131
132/// Return whether a log event should be published for the configured level.
133pub fn should_publish_log(current_log_level: LogLevel, log_level: LogLevel) -> bool {
134    log_level.rank() >= current_log_level.rank()
135}