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 {}