deribit_base/utils/
logger.rs

1use std::env;
2use std::sync::Once;
3use tracing::Level;
4use tracing_subscriber::FmtSubscriber;
5
6static INIT: Once = Once::new();
7/// Sets up the logger for the application.
8///
9/// The logger level is determined by the `DERIBIT_LOG_LEVEL` environment variable.
10/// If the variable is not set, it defaults to `INFO`.
11pub fn setup_logger() {
12    INIT.call_once(|| {
13        let log_level = env::var("DERIBIT_LOG_LEVEL")
14            .unwrap_or_else(|_| "INFO".to_string())
15            .to_uppercase();
16
17        let level = match log_level.as_str() {
18            "DEBUG" => Level::DEBUG,
19            "ERROR" => Level::ERROR,
20            "WARN" => Level::WARN,
21            "TRACE" => Level::TRACE,
22            _ => Level::INFO,
23        };
24
25        let subscriber = FmtSubscriber::builder().with_max_level(level).finish();
26
27        tracing::subscriber::set_global_default(subscriber)
28            .expect("Error setting default subscriber");
29
30        tracing::debug!("Log level set to: {}", level);
31    });
32}
33
34#[cfg(test)]
35mod tests_setup_logger {
36    use super::setup_logger;
37    use std::env;
38    use tracing::subscriber::set_global_default;
39    use tracing_subscriber::FmtSubscriber;
40
41    #[test]
42    fn test_logger_initialization_info() {
43        unsafe {
44            env::set_var("DERIBIT_LOG_LEVEL", "INFO");
45        }
46        setup_logger();
47
48        // After setting up the logger, you would typically assert that the logger is working
49        // However, due to the nature of logging, it's difficult to directly assert on log output.
50        // You can, however, check that set_global_default has been called successfully without panic.
51        assert!(
52            set_global_default(FmtSubscriber::builder().finish()).is_err(),
53            "Logger should already be set"
54        );
55    }
56
57    #[test]
58    fn test_logger_initialization_debug() {
59        unsafe {
60            env::set_var("DERIBIT_LOG_LEVEL", "DEBUG");
61        }
62        setup_logger();
63
64        // Similar to the previous test, check that the global logger has been set
65        assert!(
66            set_global_default(FmtSubscriber::builder().finish()).is_err(),
67            "Logger should already be set"
68        );
69    }
70
71    #[test]
72    fn test_logger_initialization_default() {
73        unsafe {
74            env::remove_var("DERIBIT_LOG_LEVEL");
75        }
76        setup_logger();
77
78        // Check that the global logger has been set
79        assert!(
80            set_global_default(FmtSubscriber::builder().finish()).is_err(),
81            "Logger should already be set"
82        );
83    }
84
85    #[test]
86    fn test_logger_called_once() {
87        unsafe {
88            env::set_var("DERIBIT_LOG_LEVEL", "INFO");
89        }
90
91        setup_logger(); // First call should set up the logger
92        setup_logger(); // Second call should not re-initialize
93
94        // Check that the global logger has been set only once
95        assert!(
96            set_global_default(FmtSubscriber::builder().finish()).is_err(),
97            "Logger should already be set and should not be reset"
98        );
99    }
100}
101
102#[cfg(test)]
103mod tests_setup_logger_bis {
104    use super::*;
105    use std::sync::Mutex;
106    use tracing::info;
107    use tracing::subscriber::with_default;
108    use tracing_subscriber::Layer;
109    use tracing_subscriber::layer::SubscriberExt;
110
111    static TEST_MUTEX: Mutex<()> = Mutex::new(());
112
113    #[derive(Clone)]
114    struct TestLayer {
115        level: std::sync::Arc<Mutex<Option<Level>>>,
116    }
117
118    impl<S> Layer<S> for TestLayer
119    where
120        S: tracing::Subscriber,
121    {
122        fn on_event(
123            &self,
124            event: &tracing::Event<'_>,
125            _ctx: tracing_subscriber::layer::Context<'_, S>,
126        ) {
127            let mut level = self.level.lock().unwrap();
128            *level = Some(*event.metadata().level());
129        }
130    }
131
132    fn create_test_layer() -> (TestLayer, std::sync::Arc<Mutex<Option<Level>>>) {
133        let level = std::sync::Arc::new(Mutex::new(None));
134        (
135            TestLayer {
136                level: level.clone(),
137            },
138            level,
139        )
140    }
141
142    #[test]
143    fn test_default_log_level() {
144        let _lock = TEST_MUTEX.lock().unwrap();
145        unsafe {
146            env::remove_var("DERIBIT_LOG_LEVEL");
147        }
148
149        let (layer, level) = create_test_layer();
150        let subscriber = tracing_subscriber::registry().with(layer);
151
152        with_default(subscriber, || {
153            setup_logger();
154            info!("Test log");
155        });
156
157        assert_eq!(*level.lock().unwrap(), Some(Level::INFO));
158    }
159
160    #[test]
161    fn test_debug_log_level() {
162        let _lock = TEST_MUTEX.lock().unwrap();
163        unsafe {
164            env::set_var("DERIBIT_LOG_LEVEL", "DEBUG");
165        }
166
167        let (layer, level) = create_test_layer();
168        let subscriber = tracing_subscriber::registry().with(layer);
169
170        with_default(subscriber, || {
171            setup_logger();
172            tracing::debug!("Test log");
173        });
174
175        assert_eq!(*level.lock().unwrap(), Some(Level::DEBUG));
176
177        unsafe {
178            env::remove_var("DERIBIT_LOG_LEVEL");
179        }
180    }
181
182    #[test]
183    fn test_error_log_level() {
184        let _lock = TEST_MUTEX.lock().unwrap();
185        unsafe {
186            env::set_var("DERIBIT_LOG_LEVEL", "ERROR");
187        }
188
189        let (layer, level) = create_test_layer();
190        let subscriber = tracing_subscriber::registry().with(layer);
191
192        with_default(subscriber, || {
193            setup_logger();
194            tracing::error!("Test log");
195        });
196
197        assert_eq!(*level.lock().unwrap(), Some(Level::ERROR));
198        unsafe {
199            env::remove_var("DERIBIT_LOG_LEVEL");
200        }
201    }
202
203    #[test]
204    fn test_warn_log_level() {
205        let _lock = TEST_MUTEX.lock().unwrap();
206        unsafe {
207            env::set_var("DERIBIT_LOG_LEVEL", "WARN");
208        }
209
210        let (layer, level) = create_test_layer();
211        let subscriber = tracing_subscriber::registry().with(layer);
212
213        with_default(subscriber, || {
214            setup_logger();
215            tracing::warn!("Test log");
216        });
217
218        assert_eq!(*level.lock().unwrap(), Some(Level::WARN));
219        unsafe {
220            env::remove_var("DERIBIT_LOG_LEVEL");
221        }
222    }
223
224    #[test]
225    fn test_trace_log_level() {
226        let _lock = TEST_MUTEX.lock().unwrap();
227        unsafe {
228            env::set_var("DERIBIT_LOG_LEVEL", "TRACE");
229        }
230
231        let (layer, level) = create_test_layer();
232        let subscriber = tracing_subscriber::registry().with(layer);
233
234        with_default(subscriber, || {
235            setup_logger();
236            tracing::trace!("Test log");
237        });
238
239        assert_eq!(*level.lock().unwrap(), Some(Level::TRACE));
240        unsafe {
241            env::remove_var("DERIBIT_LOG_LEVEL");
242        }
243    }
244
245    #[test]
246    fn test_invalid_log_level() {
247        let _lock = TEST_MUTEX.lock().unwrap();
248        unsafe {
249            env::set_var("DERIBIT_LOG_LEVEL", "INVALID");
250        }
251
252        let (layer, level) = create_test_layer();
253        let subscriber = tracing_subscriber::registry().with(layer);
254
255        with_default(subscriber, || {
256            setup_logger();
257            info!("Test log");
258        });
259
260        assert_eq!(*level.lock().unwrap(), Some(Level::INFO));
261        unsafe {
262            env::remove_var("DERIBIT_LOG_LEVEL");
263        }
264    }
265}