layla_log/
lib.rs

1//! A simple logger library. This library provides a simple log writer and simple log level control.
2//! It can be used to write logs in a program. The logs can be written to a dictionary.
3//! The log level can be set to different levels (Error, Warn, Debug, Info and Trace).
4
5mod logger;
6mod msg;
7mod setting;
8mod time;
9
10pub use logger::*;
11pub use setting::Setting;
12
13#[cfg(feature = "async")]
14pub use async_log::*;
15#[cfg(not(feature = "async"))]
16pub use log::*;
17
18use lazy_static::lazy_static;
19#[cfg(not(feature = "async"))]
20use std::sync::Mutex;
21#[cfg(feature = "async")]
22use tokio;
23#[cfg(feature = "async")]
24use tokio::sync::Mutex;
25
26lazy_static! {
27    /// The static logger.
28    /// If async feature is enabled, the mutex used is [``tokio::sync::mutex``], otherwise it is [`std::sync::Mutex`].
29    pub static ref LOGGER: Mutex<Logger> = Mutex::new(Logger::new());
30}
31
32/// A macro that returns the name of the function it is called in.
33#[macro_export]
34macro_rules! func {
35    () => {{
36        fn f() {}
37        fn type_name_of<T>(_: T) -> &'static str {
38            std::any::type_name::<T>()
39        }
40        let name = type_name_of(f);
41        // name.rsplit("::")
42        //     .find(|&part| part != "f" && part != "{{closure}}")
43        //     .expect("Short function name")
44        name.strip_suffix("::f")
45            .unwrap()
46            .rsplit("::")
47            .find(|&part| part != "{{closure}}")
48            .expect("Short function name")
49    }};
50}
51
52/// A macro that returns the current position in the code.
53#[macro_export]
54macro_rules! position {
55    () => {{
56        let function = $crate::func!();
57        let file = file!();
58        let line = line!();
59        format!("{}@{}:{}", function, file, line)
60    }};
61}
62
63#[cfg(feature = "async")]
64mod async_log {
65    use super::*;
66
67    /// Define a public asynchronous function named `init` that takes a `Setting` parameter.
68    pub async fn init(setting: Setting) {
69        // Acquire a mutable lock on the `LOGGER` (which is presumably a globally accessible logging utility).
70        // The `await` keyword is used here to asynchronously wait for the lock to be acquired.
71        let mut logger = LOGGER.lock().await;
72        // Call the `init` method on the locked logger, passing in the `setting` parameter.
73        // This initializes the logger with the provided settings.
74        logger.init(setting).await;
75    }
76
77    /// Define a public asynchronous function named `clean_log`
78    pub async fn clean_log() {
79        // Acquire a mutable lock on the LOGGER, which is presumably a globally accessible logging utility
80        // The `await` keyword is used here to asynchronously wait for the lock to be acquired
81        let mut writer = LOGGER.lock().await;
82        // Call the `clear_dir` method on the locked writer to clear the directory where logs are stored
83        // This method is also awaited asynchronously, indicating it performs an I/O operation or similar
84        writer.clear_dir().await;
85    }
86
87    /// Define a public asynchronous function named `set` that takes a `Setting` as a parameter.
88    pub async fn set(setting: Setting) {
89        // Acquire a mutable lock on the `LOGGER` using the `await` keyword to handle the asynchronous lock acquisition.
90        // This ensures that only one writer can access the LOGGER at a time.
91        let mut writer = LOGGER.lock().await;
92        // Call the `set` method on the locked writer, passing the `setting` parameter to it.
93        // This method call is also asynchronous and will await its completion.
94        writer.set(setting).await;
95    }
96
97    /// Macro to log error message.
98    /// First lock the logger in static, then log the message.
99    #[macro_export]
100    macro_rules! error {
101        ($($arg:tt)*) => {
102            let position = $crate::position!().to_string();
103            $crate::LOGGER.lock().await.error(format!($($arg)*).as_str(), position).await;
104        };
105    }
106
107    /// Macro to log warning message.
108    /// First lock the logger in static, then log the message.
109    #[macro_export]
110    macro_rules! warn {
111        ($($arg:tt)*) => {
112            let position = $crate::position!().to_string();
113            $crate::LOGGER.lock().await.warn(format!($($arg)*).as_str(), position).await;
114        };
115    }
116
117    /// Macro to log info message.
118    /// First lock the logger in static, then log the message.
119    #[macro_export]
120    macro_rules! info {
121        ($($arg:tt)*) => {
122            let position = $crate::position!().to_string();
123            $crate::LOGGER.lock().await.info(format!($($arg)*).as_str(), position).await;
124        };
125    }
126
127    /// Macro to log debug message.
128    /// First lock the logger in static, then log the message.
129    #[macro_export]
130    macro_rules! debug {
131        ($($arg:tt)*) => {
132            let position = $crate::position!().to_string();
133            $crate::LOGGER.lock().await.debug(format!($($arg)*).as_str(), position).await;
134        };
135    }
136
137    /// Macro to log trace message.
138    /// First lock the logger in static, then log the message.
139    #[macro_export]
140    macro_rules! trace {
141        ($($arg:tt)*) => {
142            let position = $crate::position!().to_string();
143            $crate::LOGGER.lock().await.trace(format!($($arg)*).as_str(), position).await;
144        };
145    }
146
147    /// Define a macro named `log` with two parameters: `$level` and `$($arg:tt)*`
148    #[macro_export]
149    macro_rules! log {
150        // Match the macro invocation with a level expression and a variable number of arguments
151        ($level:expr, $($arg:tt)*) => {
152            let position = $crate::position!().to_string();
153            $crate::LOGGER.lock().await.record($level, &format!($($arg)*), position).await;
154        }
155    }
156
157    /// Define a public asynchronous function named `enable_log`
158    pub async fn enable_log() {
159        // Acquire a mutable lock on the LOGGER, which is presumably a globally accessible logging utility
160        // The `await` keyword is used here to asynchronously wait for the lock to be acquired
161        let mut writer = LOGGER.lock().await;
162        // Call the `enable` method on the locked writer to enable logging
163        writer.enable();
164    }
165
166    /// Define a public asynchronous function named `disable_log`
167    pub async fn disable_log() {
168        // Acquire a mutable lock on the LOGGER, which is presumably a globally accessible logging mechanism
169        // The `await` keyword is used here to asynchronously wait for the lock to be acquired
170        let mut writer = LOGGER.lock().await;
171        // Call the `disable` method on the locked writer to disable logging
172        writer.disable();
173    }
174}
175
176#[cfg(not(feature = "async"))]
177mod log {
178    use super::*;
179
180    /// Macro to log error message.
181    /// First lock the logger in static, then log the message.
182    #[macro_export]
183    macro_rules! error {
184        ($($arg:tt)*) => {
185            let position = $crate::position!().to_string();
186            $crate::LOGGER.lock().expect("Cannot lock the logger.").error(&format!($($arg)*), position);
187        };
188    }
189
190    /// Macro to log warning message.
191    /// First lock the logger in static, then log the message.
192    #[macro_export]
193    macro_rules! warn {
194        ($($arg:tt)*) => {
195            let position = $crate::position!().to_string();
196            $crate::LOGGER.lock().expect("Cannot lock the logger.").warn(&format!($($arg)*), position);
197        };
198    }
199
200    /// Macro to log info message.
201    /// First lock the logger in static, then log the message.
202    #[macro_export]
203    macro_rules! info {
204        ($($arg:tt)*) => {
205            let position = $crate::position!().to_string();
206            $crate::LOGGER.lock().expect("Cannot lock the logger.").info(&format!($($arg)*), position);
207        };
208    }
209
210    /// Macro to log debug message.
211    /// First lock the logger in static, then log the message.
212    #[macro_export]
213    macro_rules! debug {
214        ($($arg:tt)*) => {
215            let position = $crate::position!().to_string();
216            $crate::LOGGER.lock().expect("Cannot lock the logger.").debug(&format!($($arg)*), position);
217        };
218    }
219
220    /// Macro to log trace message.
221    /// First lock the logger in static, then log the message.
222    #[macro_export]
223    macro_rules! trace {
224        ($($arg:tt)*) => {
225            let position = $crate::position!().to_string();
226            $crate::LOGGER.lock().expect("Cannot lock the logger.").trace(&format!($($arg)*), position);
227        };
228    }
229
230    #[macro_export]
231    macro_rules! log {
232        ($level:expr, $($arg:tt)*) => {
233            let position = $crate::position!().to_string();
234            $crate::LOGGER.lock().expect("Cannot lock the logger.").record($level, &format!($($arg)*));
235        }
236    }
237
238    /// Initialize the static logger with customized setting.
239    pub fn init(setting: Setting) {
240        let mut logger = LOGGER.lock().unwrap();
241        logger.init(setting);
242    }
243
244    /// Provide a easier way to clean all the existed logs.
245    pub fn clean_log() {
246        let mut writer = LOGGER.lock().expect("Cannot lock the logger.");
247        writer.clear_dir();
248    }
249
250    /// Public function to set a specific logging setting
251    pub fn set(setting: Setting) {
252        // Lock the LOGGER to ensure thread-safe access
253        let mut writer = LOGGER.lock().expect("Cannot lock the logger.");
254        // Set the provided logging setting using the writer
255        writer.set(setting);
256    }
257
258    /// Public function to enable logging
259    pub fn enable_log() {
260        // Lock the LOGGER to ensure thread-safe access
261        let mut writer = LOGGER.lock().expect("Cannot lock the logger.");
262        // Enable logging using the writer
263        writer.enable();
264    }
265
266    /// Public function to disable logging
267    pub fn disable_log() {
268        // Lock the LOGGER to ensure thread-safe access
269        let mut writer = LOGGER.lock().expect("Cannot lock the logger.");
270        // Disable logging using the writer
271        writer.disable();
272    }
273}
274
275/// Enumeration of log levels.
276/// This defines the emergency of the log.
277/// (the corresponding number is used to compare the log level to decide write to the log file or not.)
278#[derive(Copy, Clone, Debug)]
279pub enum LogLevel {
280    Trace = 0,
281    Debug = 1,
282    Info = 2,
283    Warn = 3,
284    Error = 4,
285}
286
287impl std::fmt::Display for LogLevel {
288    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
289        match self {
290            LogLevel::Info => write!(f, "INFO"),
291            LogLevel::Debug => write!(f, "DEBUG"),
292            LogLevel::Warn => write!(f, "WARN"),
293            LogLevel::Error => write!(f, "ERROR"),
294            LogLevel::Trace => write!(f, "TRACE"),
295        }
296    }
297}
298
299impl LogLevel {
300    pub fn get_level(&self) -> usize {
301        *self as usize
302    }
303}
304
305unsafe impl Send for LogLevel {}