22//! A simple logging library for lambda-rs crates.
33
44use std:: {
5+ fmt,
56 sync:: {
67 atomic:: {
78 AtomicU8 ,
@@ -107,6 +108,20 @@ impl Logger {
107108 }
108109
109110 fn log_inner ( & self , level : LogLevel , message : & str ) {
111+ if !self . compare_levels ( level) {
112+ return ;
113+ }
114+ self . log_inner_with_meta ( level, message, None , None , None ) ;
115+ }
116+
117+ fn log_inner_with_meta (
118+ & self ,
119+ level : LogLevel ,
120+ message : & str ,
121+ module_path : Option < & ' static str > ,
122+ file : Option < & ' static str > ,
123+ line : Option < u32 > ,
124+ ) {
110125 if !self . compare_levels ( level) {
111126 return ;
112127 }
@@ -115,9 +130,9 @@ impl Logger {
115130 level,
116131 target : & self . name ,
117132 message,
118- module_path : None ,
119- file : None ,
120- line : None ,
133+ module_path,
134+ file,
135+ line,
121136 } ;
122137 let lock = self . handlers . read ( ) . expect ( "poisoned handlers lock" ) ;
123138 for handler in lock. iter ( ) {
@@ -161,49 +176,87 @@ impl Logger {
161176pub enum InitError {
162177 AlreadyInitialized ,
163178}
179+ /// Returns whether the global logger would log at `level`.
180+ pub fn enabled ( level : LogLevel ) -> bool {
181+ Logger :: global ( ) . compare_levels ( level)
182+ }
183+
184+ /// Logs using the global logger, formatting only after an enabled check.
185+ pub fn log_args (
186+ level : LogLevel ,
187+ module_path : & ' static str ,
188+ file : & ' static str ,
189+ line : u32 ,
190+ args : fmt:: Arguments ,
191+ ) {
192+ let logger = Logger :: global ( ) . clone ( ) ;
193+ if !logger. compare_levels ( level) {
194+ return ;
195+ }
196+ let message = args. to_string ( ) ;
197+ logger. log_inner_with_meta (
198+ level,
199+ & message,
200+ Some ( module_path) ,
201+ Some ( file) ,
202+ Some ( line) ,
203+ ) ;
204+ }
164205/// Trace logging macro using the global logger instance.
165206#[ macro_export]
166207macro_rules! trace {
167208 ( $( $arg: tt) * ) => {
168- logging:: Logger :: global( ) . trace( format!( "{}" , format_args!( $( $arg) * ) ) ) ;
209+ if $crate:: enabled( $crate:: LogLevel :: TRACE ) {
210+ $crate:: log_args( $crate:: LogLevel :: TRACE , module_path!( ) , file!( ) , line!( ) , format_args!( $( $arg) * ) ) ;
211+ }
169212 } ;
170213}
171214
172215/// Trace logging macro using the global logger instance.
173216#[ macro_export]
174217macro_rules! debug {
175218 ( $( $arg: tt) * ) => {
176- logging:: Logger :: global( ) . debug( format!( "{}" , format_args!( $( $arg) * ) ) ) ;
219+ if $crate:: enabled( $crate:: LogLevel :: DEBUG ) {
220+ $crate:: log_args( $crate:: LogLevel :: DEBUG , module_path!( ) , file!( ) , line!( ) , format_args!( $( $arg) * ) ) ;
221+ }
177222 } ;
178223}
179224
180225/// Trace logging macro using the global logger instance.
181226#[ macro_export]
182227macro_rules! info {
183228 ( $( $arg: tt) * ) => {
184- logging:: Logger :: global( ) . info( format!( "{}" , format_args!( $( $arg) * ) ) ) ;
229+ if $crate:: enabled( $crate:: LogLevel :: INFO ) {
230+ $crate:: log_args( $crate:: LogLevel :: INFO , module_path!( ) , file!( ) , line!( ) , format_args!( $( $arg) * ) ) ;
231+ }
185232 } ;
186233}
187234
188235// Define logging macros that use the global logger instance
189236#[ macro_export]
190237macro_rules! warn {
191238 ( $( $arg: tt) * ) => {
192- logging:: Logger :: global( ) . warn( format!( "{}" , format_args!( $( $arg) * ) ) ) ;
239+ if $crate:: enabled( $crate:: LogLevel :: WARN ) {
240+ $crate:: log_args( $crate:: LogLevel :: WARN , module_path!( ) , file!( ) , line!( ) , format_args!( $( $arg) * ) ) ;
241+ }
193242 } ;
194243}
195244
196245#[ macro_export]
197246macro_rules! error {
198247 ( $( $arg: tt) * ) => {
199- logging:: Logger :: global( ) . error( format!( "{}" , format_args!( $( $arg) * ) ) ) ;
248+ if $crate:: enabled( $crate:: LogLevel :: ERROR ) {
249+ $crate:: log_args( $crate:: LogLevel :: ERROR , module_path!( ) , file!( ) , line!( ) , format_args!( $( $arg) * ) ) ;
250+ }
200251 } ;
201252}
202253
203254#[ macro_export]
204255macro_rules! fatal {
205256 ( $( $arg: tt) * ) => {
206- logging:: Logger :: global( ) . fatal( format!( "{}" , format_args!( $( $arg) * ) ) ) ;
257+ if $crate:: enabled( $crate:: LogLevel :: FATAL ) {
258+ $crate:: log_args( $crate:: LogLevel :: FATAL , module_path!( ) , file!( ) , line!( ) , format_args!( $( $arg) * ) ) ;
259+ }
207260 } ;
208261}
209262
@@ -356,4 +409,20 @@ mod tests {
356409 fs:: read_to_string ( & tmp) . expect ( "file must exist after flush" ) ;
357410 assert ! ( !content. is_empty( ) ) ;
358411 }
412+
413+ #[ test]
414+ fn macro_early_guard_avoids_formatting ( ) {
415+ // Ensure TRACE is disabled by setting level to INFO.
416+ super :: Logger :: global ( ) . set_level ( super :: LogLevel :: INFO ) ;
417+
418+ struct Boom ;
419+ impl fmt:: Display for Boom {
420+ fn fmt ( & self , _f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
421+ panic ! ( "should not be formatted when level disabled" ) ;
422+ }
423+ }
424+
425+ // If guard fails, formatting Boom would panic.
426+ super :: trace!( "{}" , Boom ) ;
427+ }
359428}
0 commit comments