ig_client/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 `LOGLEVEL` 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("LOGLEVEL")
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("LOGLEVEL", "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("LOGLEVEL", "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("LOGLEVEL");
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("LOGLEVEL", "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::subscriber::with_default;
107    use tracing_subscriber::Layer;
108    use tracing_subscriber::layer::SubscriberExt;
109
110    static TEST_MUTEX: Mutex<()> = Mutex::new(());
111
112    #[derive(Clone)]
113    struct TestLayer {
114        level: std::sync::Arc<Mutex<Option<Level>>>,
115    }
116
117    impl<S> Layer<S> for TestLayer
118    where
119        S: tracing::Subscriber,
120    {
121        fn on_event(
122            &self,
123            event: &tracing::Event<'_>,
124            _ctx: tracing_subscriber::layer::Context<'_, S>,
125        ) {
126            let mut level = self.level.lock().unwrap();
127            *level = Some(*event.metadata().level());
128        }
129    }
130
131    fn create_test_layer() -> (TestLayer, std::sync::Arc<Mutex<Option<Level>>>) {
132        let level = std::sync::Arc::new(Mutex::new(None));
133        (
134            TestLayer {
135                level: level.clone(),
136            },
137            level,
138        )
139    }
140
141    #[test]
142    fn test_default_log_level() {
143        let _lock = TEST_MUTEX.lock().unwrap();
144        unsafe {
145            env::remove_var("LOGLEVEL");
146        }
147
148        let (layer, level) = create_test_layer();
149        let subscriber = tracing_subscriber::registry().with(layer);
150
151        with_default(subscriber, || {
152            setup_logger();
153            tracing::info!("Test log");
154        });
155
156        assert_eq!(*level.lock().unwrap(), Some(Level::INFO));
157    }
158
159    #[test]
160    fn test_debug_log_level() {
161        let _lock = TEST_MUTEX.lock().unwrap();
162        unsafe {
163            env::set_var("LOGLEVEL", "DEBUG");
164        }
165
166        let (layer, level) = create_test_layer();
167        let subscriber = tracing_subscriber::registry().with(layer);
168
169        with_default(subscriber, || {
170            setup_logger();
171            tracing::debug!("Test log");
172        });
173
174        assert_eq!(*level.lock().unwrap(), Some(Level::DEBUG));
175
176        unsafe {
177            env::remove_var("LOGLEVEL");
178        }
179    }
180
181    #[test]
182    fn test_error_log_level() {
183        let _lock = TEST_MUTEX.lock().unwrap();
184        unsafe {
185            env::set_var("LOGLEVEL", "ERROR");
186        }
187
188        let (layer, level) = create_test_layer();
189        let subscriber = tracing_subscriber::registry().with(layer);
190
191        with_default(subscriber, || {
192            setup_logger();
193            tracing::error!("Test log");
194        });
195
196        assert_eq!(*level.lock().unwrap(), Some(Level::ERROR));
197        unsafe {
198            env::remove_var("LOGLEVEL");
199        }
200    }
201
202    #[test]
203    fn test_warn_log_level() {
204        let _lock = TEST_MUTEX.lock().unwrap();
205        unsafe {
206            env::set_var("LOGLEVEL", "WARN");
207        }
208
209        let (layer, level) = create_test_layer();
210        let subscriber = tracing_subscriber::registry().with(layer);
211
212        with_default(subscriber, || {
213            setup_logger();
214            tracing::warn!("Test log");
215        });
216
217        assert_eq!(*level.lock().unwrap(), Some(Level::WARN));
218        unsafe {
219            env::remove_var("LOGLEVEL");
220        }
221    }
222
223    #[test]
224    fn test_trace_log_level() {
225        let _lock = TEST_MUTEX.lock().unwrap();
226        unsafe {
227            env::set_var("LOGLEVEL", "TRACE");
228        }
229
230        let (layer, level) = create_test_layer();
231        let subscriber = tracing_subscriber::registry().with(layer);
232
233        with_default(subscriber, || {
234            setup_logger();
235            tracing::trace!("Test log");
236        });
237
238        assert_eq!(*level.lock().unwrap(), Some(Level::TRACE));
239        unsafe {
240            env::remove_var("LOGLEVEL");
241        }
242    }
243
244    #[test]
245    fn test_invalid_log_level() {
246        let _lock = TEST_MUTEX.lock().unwrap();
247        unsafe {
248            env::set_var("LOGLEVEL", "INVALID");
249        }
250
251        let (layer, level) = create_test_layer();
252        let subscriber = tracing_subscriber::registry().with(layer);
253
254        with_default(subscriber, || {
255            setup_logger();
256            tracing::info!("Test log");
257        });
258
259        assert_eq!(*level.lock().unwrap(), Some(Level::INFO));
260        unsafe {
261            env::remove_var("LOGLEVEL");
262        }
263    }
264}