rust_loguru/
macros.rs

1//! Macros for convenient logging.
2//!
3//! This module provides macros for each log level that make it easy to log messages
4//! with source location information and formatting support.
5
6/// Logs a message at the TRACE level.
7///
8/// # Examples
9///
10/// ```rust
11/// use rust_loguru::trace;
12///
13/// trace!("This is a trace message");
14/// trace!("Formatted message: {}", 42);
15/// ```
16#[macro_export]
17macro_rules! trace {
18    ($($arg:tt)*) => {
19        $crate::log(&$crate::Record::new(
20            $crate::LogLevel::Trace,
21            format!($($arg)*),
22            Some(module_path!().to_string()),
23            Some(file!().to_string()),
24            Some(line!()),
25        ))
26    };
27}
28
29/// Logs a message at the DEBUG level.
30///
31/// # Examples
32///
33/// ```rust
34/// use rust_loguru::debug;
35///
36/// debug!("This is a debug message");
37/// debug!("Formatted message: {}", 42);
38/// ```
39#[macro_export]
40macro_rules! debug {
41    ($($arg:tt)*) => {
42        $crate::log(&$crate::Record::new(
43            $crate::LogLevel::Debug,
44            format!($($arg)*),
45            Some(module_path!().to_string()),
46            Some(file!().to_string()),
47            Some(line!()),
48        ))
49    };
50}
51
52/// Logs a message at the INFO level.
53///
54/// # Examples
55///
56/// ```rust
57/// use rust_loguru::info;
58///
59/// info!("This is an info message");
60/// info!("Formatted message: {}", 42);
61/// ```
62#[macro_export]
63macro_rules! info {
64    ($($arg:tt)*) => {
65        $crate::log(&$crate::Record::new(
66            $crate::LogLevel::Info,
67            format!($($arg)*),
68            Some(module_path!().to_string()),
69            Some(file!().to_string()),
70            Some(line!()),
71        ))
72    };
73}
74
75/// Logs a message at the SUCCESS level.
76///
77/// # Examples
78///
79/// ```rust
80/// use rust_loguru::success;
81///
82/// success!("This is a success message");
83/// success!("Formatted message: {}", 42);
84/// ```
85#[macro_export]
86macro_rules! success {
87    ($($arg:tt)*) => {
88        $crate::log(&$crate::Record::new(
89            $crate::LogLevel::Success,
90            format!($($arg)*),
91            Some(module_path!().to_string()),
92            Some(file!().to_string()),
93            Some(line!()),
94        ))
95    };
96}
97
98/// Logs a message at the WARNING level.
99///
100/// # Examples
101///
102/// ```rust
103/// use rust_loguru::warn;
104///
105/// warn!("This is a warning message");
106/// warn!("Formatted message: {}", 42);
107/// ```
108#[macro_export]
109macro_rules! warn {
110    ($($arg:tt)*) => {
111        $crate::log(&$crate::Record::new(
112            $crate::LogLevel::Warning,
113            format!($($arg)*),
114            Some(module_path!().to_string()),
115            Some(file!().to_string()),
116            Some(line!()),
117        ))
118    };
119}
120
121/// Logs a message at the ERROR level.
122///
123/// # Examples
124///
125/// ```rust
126/// use rust_loguru::error;
127///
128/// error!("This is an error message");
129/// error!("Formatted message: {}", 42);
130/// ```
131#[macro_export]
132macro_rules! error {
133    ($($arg:tt)*) => {
134        $crate::log(&$crate::Record::new(
135            $crate::LogLevel::Error,
136            format!($($arg)*),
137            Some(module_path!().to_string()),
138            Some(file!().to_string()),
139            Some(line!()),
140        ))
141    };
142}
143
144/// Logs a message at the CRITICAL level.
145///
146/// # Examples
147///
148/// ```rust
149/// use rust_loguru::critical;
150///
151/// critical!("This is a critical message");
152/// critical!("Formatted message: {}", 42);
153/// ```
154#[macro_export]
155macro_rules! critical {
156    ($($arg:tt)*) => {
157        $crate::log(&$crate::Record::new(
158            $crate::LogLevel::Critical,
159            format!($($arg)*),
160            Some(module_path!().to_string()),
161            Some(file!().to_string()),
162            Some(line!()),
163        ))
164    };
165}
166
167/// Logs a message with metadata at the specified level.
168///
169/// # Examples
170///
171/// ```rust
172/// use rust_loguru::{log_with_metadata, LogLevel};
173///
174/// log_with_metadata!(LogLevel::Info, "key" => "value"; "This is a message");
175/// log_with_metadata!(LogLevel::Error, "error_code" => "E123"; "Failed to process: {}", 42);
176/// ```
177#[macro_export]
178macro_rules! log_with_metadata {
179    ($level:expr, $($key:expr => $value:expr),+; $($arg:tt)*) => {
180        {
181            let mut record = $crate::Record::new(
182                $level,
183                format!($($arg)*),
184                Some(module_path!().to_string()),
185                Some(file!().to_string()),
186                Some(line!()),
187            );
188            $(
189                record = record.with_metadata($key, $value);
190            )+
191            let result = $crate::log(&record);
192            println!("Log with metadata result: {}", result);
193            result
194        }
195    };
196}
197
198// --- Context Macros ---
199/// Push a new context map onto the stack.
200/// Usage: push_context! { "key1" => val1, "key2" => val2 }
201#[macro_export]
202macro_rules! push_context {
203    ( $( $key:expr => $val:expr ),* $(,)? ) => {
204        {
205            let mut ctx = ::std::collections::HashMap::new();
206            $( ctx.insert($key.to_string(), $crate::context::ContextValue::String($val.to_string())); )*
207            $crate::context::push_context(ctx);
208        }
209    };
210}
211
212/// Pop the top context map from the stack.
213#[macro_export]
214macro_rules! pop_context {
215    () => {
216        $crate::context::pop_context();
217    };
218}
219
220/// Set a key-value pair in the current context.
221#[macro_export]
222macro_rules! set_context {
223    ($key:expr, $val:expr) => {
224        $crate::context::set_context_value(
225            $key,
226            $crate::context::ContextValue::String($val.to_string()),
227        );
228    };
229}
230
231/// Get a value from the current context.
232#[macro_export]
233macro_rules! get_context {
234    ($key:expr) => {
235        $crate::context::get_context_value($key)
236    };
237}
238
239// --- Scope Macros ---
240/// Enter a new scope. Returns a guard that times and manages indentation.
241/// Usage: let _scope = scope!("my_scope");
242#[macro_export]
243macro_rules! scope {
244    ($name:expr) => {
245        $crate::scope::ScopeGuard::enter($name)
246    };
247}
248
249/// Log entering and exiting a scope at INFO level, with timing.
250/// Usage: let _scope = scoped_info!("my_scope");
251#[macro_export]
252macro_rules! scoped_info {
253    ($name:expr) => {{
254        $crate::info!("Entering scope: {}", $name);
255        let _guard = $crate::scope::ScopeGuard::enter($name);
256        struct ScopeLogger<'a> {
257            name: &'a str,
258            start: ::std::time::Instant,
259        }
260        impl<'a> ::std::ops::Drop for ScopeLogger<'a> {
261            fn drop(&mut self) {
262                let elapsed = self.start.elapsed();
263                $crate::info!("Exiting scope: {} (elapsed: {:?})", self.name, elapsed);
264            }
265        }
266        ScopeLogger {
267            name: $name,
268            start: ::std::time::Instant::now(),
269        }
270    }};
271}
272
273// --- Error Integration Macros ---
274/// Log an error with source location (uses error! macro)
275#[macro_export]
276macro_rules! log_error {
277    ($err:expr) => {
278        $crate::error!("{}", $err);
279    };
280    ($err:expr, $msg:expr) => {
281        $crate::error!("{}: {}", $msg, $err);
282    };
283}
284
285/// Log an error with context (uses error! macro)
286#[macro_export]
287macro_rules! log_error_with_context {
288    ($err:expr, $ctx:expr) => {
289        $crate::error!("{} (context: {:?})", $err, $ctx);
290    };
291}
292
293/// Try to log an error if Result is Err or Option is None, then return the value.
294#[macro_export]
295macro_rules! try_log {
296    ($expr:expr, $msg:expr) => {{
297        match $expr {
298            Ok(val) => Ok(val),
299            Err(e) => {
300                $crate::error!("{}: {}", $msg, e);
301                Err(e)
302            }
303        }
304    }};
305    (option $expr:expr, $msg:expr) => {{
306        match $expr {
307            Some(val) => Some(val),
308            None => {
309                $crate::error!("{}: None value", $msg);
310                None
311            }
312        }
313    }};
314}
315
316// --- Compile-time Level Filtering ---
317// Usage: static LEVEL: LogLevel = LogLevel::Info; (in lib.rs or build.rs)
318// Macros will only emit code if $level >= STATIC_LEVEL
319#[macro_export]
320macro_rules! log_if_enabled {
321    ($level:expr, $($arg:tt)*) => {
322        if $level >= $crate::STATIC_LEVEL {
323            $crate::log(&$crate::Record::new(
324                $level,
325                format!($($arg)*),
326                Some(module_path!().to_string()),
327                Some(file!().to_string()),
328                Some(line!()),
329            ))
330        } else {
331            false
332        }
333    };
334}
335
336// --- Structured Data in Level Macros ---
337// Usage: info!("msg"; "key1" => val1, "key2" => val2)
338#[macro_export]
339macro_rules! info_kv {
340    ($msg:expr; $( $key:expr => $val:expr ),+ ) => {{
341        let mut record = $crate::Record::new(
342            $crate::LogLevel::Info,
343            $msg.to_string(),
344            Some(module_path!().to_string()),
345            Some(file!().to_string()),
346            Some(line!()),
347        );
348        $( record = record.with_metadata($key, $val); )+
349        $crate::log(&record)
350    }};
351}