@@ -335,57 +335,37 @@ pub unsafe fn impl_log(
335335 static FORMAT_STRING : OnceLock < CString > = OnceLock :: new ( ) ;
336336 let format_string = FORMAT_STRING . get_or_init ( || CString :: new ( "%s" ) . unwrap ( ) ) ;
337337
338- let severity = severity. as_native ( ) ;
338+ let severity = severity. as_native ( ) as i32 ;
339339
340340 let _lifecycle = ENTITY_LIFECYCLE_MUTEX . lock ( ) . unwrap ( ) ;
341341
342342 #[ cfg( test) ]
343- {
344- // If we are compiling for testing purposes, when the default log
345- // output handler is being used we need to use the format_string,
346- // but when our custom log output handler is being used we need to
347- // pass the raw message string so that it can be viewed by the
348- // custom log output handler, allowing us to use it for test assertions.
349- if log_handler:: is_using_custom_handler ( ) {
350- // We are using the custom log handler that is only used during
351- // logging tests, so pass the raw message as the format string.
352- unsafe {
353- // SAFETY: The global mutex is locked as _lifecycle
354- rcutils_log (
355- & location,
356- severity as i32 ,
357- logger_name. as_ptr ( ) ,
358- message. as_ptr ( ) ,
359- ) ;
360- }
361- } else {
362- // We are using the normal log handler so call rcutils_log the normal way.
363- unsafe {
364- // SAFETY: The global mutex is locked as _lifecycle
365- rcutils_log (
366- & location,
367- severity as i32 ,
368- logger_name. as_ptr ( ) ,
369- format_string. as_ptr ( ) ,
370- message. as_ptr ( ) ,
371- ) ;
372- }
373- }
374- }
375-
376- #[ cfg( not( test) ) ]
343+ if log_handler:: is_using_custom_handler ( )
344+ && unsafe { rcutils_logging_logger_is_enabled_for ( logger_name. as_ptr ( ) , severity) }
377345 {
378346 unsafe {
379- // SAFETY: The global mutex is locked as _lifecycle
380- rcutils_log (
347+ // SAFETY: The global mutex is locked as _lifecycle and the pointers are valid for
348+ // the duration of this call.
349+ log_handler:: dispatch_logging_output_handler (
381350 & location,
382- severity as i32 ,
351+ severity,
383352 logger_name. as_ptr ( ) ,
384- format_string . as_ptr ( ) ,
353+ log_handler :: null_timestamp ( ) ,
385354 message. as_ptr ( ) ,
386355 ) ;
387356 }
388357 }
358+
359+ unsafe {
360+ // SAFETY: The global mutex is locked as _lifecycle
361+ rcutils_log (
362+ & location,
363+ severity,
364+ logger_name. as_ptr ( ) ,
365+ format_string. as_ptr ( ) ,
366+ message. as_ptr ( ) ,
367+ ) ;
368+ }
389369 } ;
390370
391371 match logger_name {
@@ -473,14 +453,12 @@ macro_rules! function {
473453#[ cfg( test) ]
474454mod tests {
475455 use crate :: { log_handler:: * , test_helpers:: * , * } ;
476- use serial_test:: serial;
477456 use std:: {
478457 sync:: { Arc , Mutex } ,
479458 time:: Duration ,
480459 } ;
481460
482461 #[ test]
483- #[ serial]
484462 fn test_logging_macros ( ) -> Result < ( ) , RclrsError > {
485463 // This test ensures that strings which are being sent to the logger are
486464 // being sanitized correctly. Rust generally and our logging macro in
@@ -497,15 +475,32 @@ mod tests {
497475 log ! ( "please do not crash" , "%n" ) ;
498476
499477 let graph = construct_test_graph ( "test_logging_macros" ) ?;
478+ let node = graph. node1 ;
479+ let node_logger_name = node. logger ( ) . name ( ) . to_owned ( ) ;
480+
481+ let custom_logger_name = "test_logging_macros_custom" ;
482+ let once_logger_name = "test_logging_macros_once" ;
483+ let skip_logger_name = "test_logging_macros_skip" ;
484+ let throttle_logger_name = "test_logging_macros_throttle" ;
500485
501486 let log_collection: Arc < Mutex < Vec < LogEntry < ' static > > > > = Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ;
502487 let inner_log_collection = log_collection. clone ( ) ;
503488
504489 log_handler:: set_logging_output_handler ( move |log_entry : log_handler:: LogEntry | {
505- inner_log_collection
506- . lock ( )
507- . unwrap ( )
508- . push ( log_entry. into_owned ( ) ) ;
490+ if [
491+ node_logger_name. as_str ( ) ,
492+ custom_logger_name,
493+ once_logger_name,
494+ skip_logger_name,
495+ throttle_logger_name,
496+ ]
497+ . contains ( & log_entry. logger_name . as_ref ( ) )
498+ {
499+ inner_log_collection
500+ . lock ( )
501+ . unwrap ( )
502+ . push ( log_entry. into_owned ( ) ) ;
503+ }
509504 } )
510505 . unwrap ( ) ;
511506
@@ -551,8 +546,6 @@ mod tests {
551546 count
552547 } ;
553548
554- let node = graph. node1 ;
555-
556549 log ! ( & * node, "Logging with node dereference" ) ;
557550 assert_eq ! ( last_logger_name( ) , node. logger( ) . name( ) ) ;
558551 assert_eq ! ( last_message( ) , "Logging with node dereference" ) ;
@@ -621,27 +614,27 @@ mod tests {
621614 log_debug ! ( node. logger( ) , "This debug message does not appear" ) ;
622615 assert_ne ! ( last_message( ) , "This debug message does not appear" ) ;
623616
624- log ! ( "custom logger name" , "message for custom logger" ) ;
625- assert_eq ! ( last_logger_name( ) , "custom logger name" ) ;
617+ log ! ( custom_logger_name , "message for custom logger" ) ;
618+ assert_eq ! ( last_logger_name( ) , custom_logger_name ) ;
626619 assert_eq ! ( last_message( ) , "message for custom logger" ) ;
627620
628621 for _ in 0 ..3 {
629622 log ! (
630- "custom logger name once" . once( ) ,
623+ once_logger_name . once( ) ,
631624 "one-time message for custom logger" ,
632625 ) ;
633626 }
634- assert_eq ! ( last_logger_name( ) , "custom logger name once" ) ;
627+ assert_eq ! ( last_logger_name( ) , once_logger_name ) ;
635628 assert_eq ! ( last_severity( ) , LogSeverity :: Info ) ;
636629 assert_eq ! ( count_message( "one-time message for custom logger" ) , 1 ) ;
637630
638631 for _ in 0 ..3 {
639632 log ! (
640- "custom logger name skip" . error( ) . skip_first( ) ,
633+ skip_logger_name . error( ) . skip_first( ) ,
641634 "error for custom logger" ,
642635 ) ;
643636 }
644- assert_eq ! ( last_logger_name( ) , "custom logger name skip" ) ;
637+ assert_eq ! ( last_logger_name( ) , skip_logger_name ) ;
645638 assert_eq ! ( last_severity( ) , LogSeverity :: Error ) ;
646639 assert_eq ! ( count_message( "error for custom logger" ) , 2 ) ;
647640
@@ -651,7 +644,7 @@ mod tests {
651644
652645 for i in 0 ..15 {
653646 log ! (
654- "logger"
647+ throttle_logger_name
655648 . throttle( Duration :: from_nanos( 10 ) )
656649 . throttle_clock( ThrottleClock :: Clock ( & clock) ) ,
657650 "custom clock throttled message" ,
@@ -674,7 +667,6 @@ mod tests {
674667 }
675668
676669 #[ test]
677- #[ serial]
678670 fn test_rosout_publishing_default ( ) -> Result < ( ) , RclrsError > {
679671 use crate :: rcl_bindings:: rcl_logging_rosout_enabled;
680672 use ros_env:: rcl_interfaces:: msg:: rmw:: Log ;
@@ -687,8 +679,11 @@ mod tests {
687679 . unwrap ( ) ;
688680
689681 // Check if rosout is enabled at the rcl level
690- // SAFETY: This is a simple query function with no preconditions
691- let rosout_enabled = unsafe { rcl_logging_rosout_enabled ( ) } ;
682+ let rosout_enabled = {
683+ let _lifecycle_lock = ENTITY_LIFECYCLE_MUTEX . lock ( ) . unwrap ( ) ;
684+ // SAFETY: The entity lifecycle mutex is locked to protect logging's global state.
685+ unsafe { rcl_logging_rosout_enabled ( ) }
686+ } ;
692687 assert ! (
693688 rosout_enabled,
694689 "rcl_logging_rosout should be enabled for this test"
@@ -814,7 +809,6 @@ mod tests {
814809 }
815810
816811 #[ test]
817- #[ serial]
818812 fn test_rosout_disabled ( ) -> Result < ( ) , RclrsError > {
819813 use ros_env:: rcl_interfaces:: msg:: rmw:: Log ;
820814 use std:: sync:: {
0 commit comments