@@ -152,6 +152,19 @@ macro_rules! debug {
152152 } ;
153153}
154154
155+ /// Emit a log at the TRACE level.
156+ ///
157+ /// See the [`log!`][macro@crate::log] macro for more details.
158+ #[ macro_export]
159+ macro_rules! trace {
160+ ( parent: $parent: expr, $format: expr $( , $( $path: ident) .+ $( = $value: expr) ?) * $( , ) ?) => {
161+ $crate:: log!( parent: $parent, tracing:: Level :: TRACE , $format, $( $( $path) .+ $( = $value) ?) ,* )
162+ } ;
163+ ( $format: expr $( , $( $path: ident) .+ $( = $value: expr) ?) * $( , ) ?) => {
164+ $crate:: log!( tracing:: Level :: TRACE , $format, $( $( $path) .+ $( = $value) ?) ,* )
165+ } ;
166+ }
167+
155168/// Export a log message at the specified level.
156169///
157170/// # Syntax
@@ -255,3 +268,249 @@ macro_rules! log {
255268 $crate:: __macros_impl:: log!( parent: tracing:: Span :: current( ) , $level, $format, $( $( $path) .+ $( = $value) ?) ,* )
256269 } ;
257270}
271+
272+ #[ cfg( test) ]
273+ mod tests {
274+ use crate :: config:: { ConsoleOptions , Target } ;
275+ use std:: sync:: { Arc , Mutex } ;
276+ use tracing:: Level ;
277+
278+ #[ test]
279+ fn test_error_macro ( ) {
280+ let output = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
281+ let console_options = ConsoleOptions {
282+ target : Target :: Pipe ( output. clone ( ) ) ,
283+ ..ConsoleOptions :: default ( ) . with_min_log_level ( Level :: ERROR )
284+ } ;
285+
286+ let handler = crate :: configure ( )
287+ . local ( )
288+ . send_to_logfire ( false )
289+ . with_console ( Some ( console_options) )
290+ . install_panic_handler ( )
291+ . with_default_level_filter ( tracing:: level_filters:: LevelFilter :: TRACE )
292+ . finish ( )
293+ . unwrap ( ) ;
294+
295+ let guard = crate :: set_local_logfire ( handler) ;
296+
297+ tracing:: subscriber:: with_default ( guard. subscriber ( ) . clone ( ) , || {
298+ crate :: error!( "Test error message" ) ;
299+ crate :: error!( "Test error with value" , field = 42 ) ;
300+ } ) ;
301+
302+ guard. shutdown_handler . shutdown ( ) . unwrap ( ) ;
303+
304+ let output = output. lock ( ) . unwrap ( ) ;
305+ let output = std:: str:: from_utf8 ( & output) . unwrap ( ) ;
306+
307+ assert ! ( output. contains( "Test error message" ) ) ;
308+ assert ! ( output. contains( "Test error with value" ) ) ;
309+ assert ! ( output. contains( "field" ) && output. contains( "42" ) ) ;
310+ }
311+
312+ #[ test]
313+ fn test_warn_macro ( ) {
314+ let output = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
315+ let console_options = ConsoleOptions {
316+ target : Target :: Pipe ( output. clone ( ) ) ,
317+ ..ConsoleOptions :: default ( ) . with_min_log_level ( Level :: WARN )
318+ } ;
319+
320+ let handler = crate :: configure ( )
321+ . local ( )
322+ . send_to_logfire ( false )
323+ . with_console ( Some ( console_options) )
324+ . install_panic_handler ( )
325+ . with_default_level_filter ( tracing:: level_filters:: LevelFilter :: TRACE )
326+ . finish ( )
327+ . unwrap ( ) ;
328+
329+ let guard = crate :: set_local_logfire ( handler) ;
330+
331+ tracing:: subscriber:: with_default ( guard. subscriber ( ) . clone ( ) , || {
332+ crate :: warn!( "Test warn message" ) ;
333+ crate :: warn!( "Test warn with value" , field = "test" ) ;
334+ } ) ;
335+
336+ guard. shutdown_handler . shutdown ( ) . unwrap ( ) ;
337+
338+ let output = output. lock ( ) . unwrap ( ) ;
339+ let output = std:: str:: from_utf8 ( & output) . unwrap ( ) ;
340+
341+ assert ! ( output. contains( "Test warn message" ) ) ;
342+ assert ! ( output. contains( "Test warn with value" ) ) ;
343+ assert ! ( output. contains( "field" ) && output. contains( "test" ) ) ;
344+ }
345+
346+ #[ test]
347+ fn test_info_macro ( ) {
348+ let output = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
349+ let console_options = ConsoleOptions {
350+ target : Target :: Pipe ( output. clone ( ) ) ,
351+ ..ConsoleOptions :: default ( ) . with_min_log_level ( Level :: INFO )
352+ } ;
353+
354+ let handler = crate :: configure ( )
355+ . local ( )
356+ . send_to_logfire ( false )
357+ . with_console ( Some ( console_options) )
358+ . install_panic_handler ( )
359+ . with_default_level_filter ( tracing:: level_filters:: LevelFilter :: TRACE )
360+ . finish ( )
361+ . unwrap ( ) ;
362+
363+ let guard = crate :: set_local_logfire ( handler) ;
364+
365+ tracing:: subscriber:: with_default ( guard. subscriber ( ) . clone ( ) , || {
366+ crate :: info!( "Test info message" ) ;
367+ crate :: info!( "Test info with value" , field = true ) ;
368+ } ) ;
369+
370+ guard. shutdown_handler . shutdown ( ) . unwrap ( ) ;
371+
372+ let output = output. lock ( ) . unwrap ( ) ;
373+ let output = std:: str:: from_utf8 ( & output) . unwrap ( ) ;
374+
375+ assert ! ( output. contains( "Test info message" ) ) ;
376+ assert ! ( output. contains( "Test info with value" ) ) ;
377+ assert ! ( output. contains( "field" ) && output. contains( "true" ) ) ;
378+ }
379+
380+ #[ test]
381+ fn test_debug_macro ( ) {
382+ let output = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
383+ let console_options = ConsoleOptions {
384+ target : Target :: Pipe ( output. clone ( ) ) ,
385+ ..ConsoleOptions :: default ( ) . with_min_log_level ( Level :: TRACE )
386+ } ;
387+
388+ let handler = crate :: configure ( )
389+ . local ( )
390+ . send_to_logfire ( false )
391+ . with_console ( Some ( console_options) )
392+ . install_panic_handler ( )
393+ . with_default_level_filter ( tracing:: level_filters:: LevelFilter :: TRACE )
394+ . finish ( )
395+ . unwrap ( ) ;
396+
397+ let guard = crate :: set_local_logfire ( handler) ;
398+
399+ tracing:: subscriber:: with_default ( guard. subscriber ( ) . clone ( ) , || {
400+ crate :: debug!( "Test debug message" ) ;
401+ crate :: debug!( "Test debug with value" , field = 3.14 ) ;
402+ } ) ;
403+
404+ guard. shutdown_handler . shutdown ( ) . unwrap ( ) ;
405+
406+ let output = output. lock ( ) . unwrap ( ) ;
407+ let output = std:: str:: from_utf8 ( & output) . unwrap ( ) ;
408+
409+ assert ! ( output. contains( "Test debug message" ) ) ;
410+ assert ! ( output. contains( "Test debug with value" ) ) ;
411+ assert ! ( output. contains( "field" ) && output. contains( "3.14" ) ) ;
412+ }
413+
414+ #[ test]
415+ fn test_trace_macro ( ) {
416+ let output = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
417+ let console_options = ConsoleOptions {
418+ target : Target :: Pipe ( output. clone ( ) ) ,
419+ ..ConsoleOptions :: default ( ) . with_min_log_level ( Level :: TRACE )
420+ } ;
421+
422+ let handler = crate :: configure ( )
423+ . local ( )
424+ . send_to_logfire ( false )
425+ . with_console ( Some ( console_options) )
426+ . install_panic_handler ( )
427+ . with_default_level_filter ( tracing:: level_filters:: LevelFilter :: TRACE )
428+ . finish ( )
429+ . unwrap ( ) ;
430+
431+ let guard = crate :: set_local_logfire ( handler) ;
432+
433+ tracing:: subscriber:: with_default ( guard. subscriber ( ) . clone ( ) , || {
434+ crate :: trace!( "Test trace message" ) ;
435+ crate :: trace!( "Test trace with value" , field = "debug_info" ) ;
436+ } ) ;
437+
438+ guard. shutdown_handler . shutdown ( ) . unwrap ( ) ;
439+
440+ let output = output. lock ( ) . unwrap ( ) ;
441+ let output = std:: str:: from_utf8 ( & output) . unwrap ( ) ;
442+
443+ assert ! ( output. contains( "Test trace message" ) ) ;
444+ assert ! ( output. contains( "Test trace with value" ) ) ;
445+ assert ! ( output. contains( "field" ) && output. contains( "debug_info" ) ) ;
446+ }
447+
448+ #[ test]
449+ fn test_log_macro_with_explicit_level ( ) {
450+ let output = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
451+ let console_options = ConsoleOptions {
452+ target : Target :: Pipe ( output. clone ( ) ) ,
453+ ..ConsoleOptions :: default ( ) . with_min_log_level ( Level :: INFO )
454+ } ;
455+
456+ let handler = crate :: configure ( )
457+ . local ( )
458+ . send_to_logfire ( false )
459+ . with_console ( Some ( console_options) )
460+ . install_panic_handler ( )
461+ . with_default_level_filter ( tracing:: level_filters:: LevelFilter :: TRACE )
462+ . finish ( )
463+ . unwrap ( ) ;
464+
465+ let guard = crate :: set_local_logfire ( handler) ;
466+
467+ tracing:: subscriber:: with_default ( guard. subscriber ( ) . clone ( ) , || {
468+ crate :: log!( Level :: INFO , "Test log message" ) ;
469+ crate :: log!( Level :: INFO , "Test log with value" , field = "explicit" ) ;
470+ } ) ;
471+
472+ guard. shutdown_handler . shutdown ( ) . unwrap ( ) ;
473+
474+ let output = output. lock ( ) . unwrap ( ) ;
475+ let output = std:: str:: from_utf8 ( & output) . unwrap ( ) ;
476+
477+ assert ! ( output. contains( "Test log message" ) ) ;
478+ assert ! ( output. contains( "Test log with value" ) ) ;
479+ assert ! ( output. contains( "field" ) && output. contains( "explicit" ) ) ;
480+ }
481+
482+ #[ test]
483+ fn test_macros_with_parent_span ( ) {
484+ let output = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
485+ let console_options = ConsoleOptions {
486+ target : Target :: Pipe ( output. clone ( ) ) ,
487+ ..ConsoleOptions :: default ( ) . with_min_log_level ( Level :: INFO )
488+ } ;
489+
490+ let handler = crate :: configure ( )
491+ . local ( )
492+ . send_to_logfire ( false )
493+ . with_console ( Some ( console_options) )
494+ . install_panic_handler ( )
495+ . with_default_level_filter ( tracing:: level_filters:: LevelFilter :: TRACE )
496+ . finish ( )
497+ . unwrap ( ) ;
498+
499+ let guard = crate :: set_local_logfire ( handler) ;
500+
501+ tracing:: subscriber:: with_default ( guard. subscriber ( ) . clone ( ) , || {
502+ let parent_span = crate :: span!( "parent span" ) ;
503+ crate :: info!( parent: & parent_span, "Test info with parent" ) ;
504+ crate :: error!( parent: & parent_span, "Test error with parent" , field = "parent_test" ) ;
505+ } ) ;
506+
507+ guard. shutdown_handler . shutdown ( ) . unwrap ( ) ;
508+
509+ let output = output. lock ( ) . unwrap ( ) ;
510+ let output = std:: str:: from_utf8 ( & output) . unwrap ( ) ;
511+
512+ assert ! ( output. contains( "Test info with parent" ) ) ;
513+ assert ! ( output. contains( "Test error with parent" ) ) ;
514+ assert ! ( output. contains( "field" ) && output. contains( "parent_test" ) ) ;
515+ }
516+ }
0 commit comments