Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.
Package Dependencies
System Dependencies
Dependant Packages
Launch files
Messages
Services
Plugins
Recent questions tagged ros2_medkit_log_bridge at Robotics Stack Exchange
Package Summary
| Version | 0.5.0 |
| License | Apache-2.0 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/selfpatch/ros2_medkit.git |
| VCS Type | git |
| VCS Version | main |
| Last Updated | 2026-06-16 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Maintainers
- mfaferek93
Authors
ros2_medkit_log_bridge
Drop-in bridge that promotes ROS 2 /rosout log entries to structured medkit
faults, attributing each fault to the node that logged it. No changes to the
user’s nodes are required.
It is a compatibility adapter, the same category as
ros2_medkit_diagnostic_bridge. Native ros2_medkit_fault_reporter
instrumentation stays the canonical path for code you control; this bridge is
the fallback for nodes that only log.
What it does
Subscribes to /rosout (rcl_interfaces/msg/Log) and forwards entries at or
above a severity floor to the FaultManager:
| Log level | medkit severity |
|---|---|
| DEBUG (10) / INFO (20) | dropped |
| WARN (30) | SEVERITY_WARN |
| ERROR (40) | SEVERITY_ERROR |
| FATAL (50) | SEVERITY_CRITICAL |
-
source_idof each fault is the originating node’s fully-qualified name. It is derived fromLog.nameby taking the first dotted segment (aLog.namemay carry a sub-logger suffix, e.g.controller_manager.resource_manager, and node names cannot contain.) and prefixing/, giving e.g./controller_manager. The gateway discovers entities by node FQN, so this is the form that lets a fault (and its snapshots / rosbag) associate with the entity in the SOVD tree. Each node gets its own per-nodeFaultReporterand therefore its own client-side debounce. -
fault_codeis auto-generated as<PREFIX>_<NODE>_<HASH>.<HASH>is a fixed FNV-1a 32-bit digest (8 lowercase hex) of a normalized message template (numbers / hex / paths stripped, isolated single-letter tokens dropped) so the same logical message maps to the same code across occurrences.<NODE>is the upper-snake ofsource_id. The 8-hex hash is never truncated; if the 64-char cap is hit the node part is trimmed instead.
Namespaced-node limitation:
Log.nameencodes a node’s namespace with the same.separator as a sub-logger suffix, so the two are indistinguishable from the string alone.source_idtakes the first dotted segment, which is right for a non-namespaced node with a sub-logger but collapses a namespaced node (robot1.planner_server->/robot1) to its namespace, so same-named nodes in different namespaces share one code. Multi-robot fleets typically isolate robots byROS_DOMAIN_ID(one gateway per robot, federated by peer aggregation), which sidesteps this.
Forwarding, the LocalFilter, and confirmation
Two independent debounces sit between a log line and a confirmed fault:
- Per-node
FaultReporterLocalFilter(client-side). WARN is held untildefault_threshold(3) occurrences withindefault_window_sec(10s). ERROR/FATAL have severity>= bypass_severity(2) and bypass the filter, forwarding immediately. - Bridge
report_cooldown_seccooldown, applied only toERROR/FATAL(the levels that bypass the LocalFilter). It forwards the first occurrence of a(fault_code, severity)immediately and suppresses that same pair forreport_cooldown_sec(default 5s,0.0disables), bounding a flood.WARNis never cooled here (that would starve its LocalFilter threshold counting), and keying on severity means aWARNnever suppresses a same-messageERRORescalation.
Whether a forwarded fault then shows as PREFAILED (suspected) or CONFIRMED
is a separate, gateway-side decision driven by the FaultManager’s
confirmation_threshold - not by this bridge and not by the client-side
LocalFilter. For visible-but-quiet WARNs, launch the FaultManager with a low
confirmation_threshold (or an entity threshold for LOG_* codes).
Hard limitations (by construction)
- Only sees logs that reach
/rosoutvia rclcpp from a still-alive node. Console-only loggers (e.g. some Micro XRCE-DDS / non-rclcpp loggers) are invisible. - A node that crashes hard may not flush its final log to
/rosout, so the terminating ERROR can be missed. Process-death detection belongs to a separate liveliness bridge, not here.
Run it
# next to an existing stack + the medkit gateway/fault_manager
ros2 launch ros2_medkit_log_bridge log_bridge.launch.py
Configuration (config/log_bridge.yaml)
| Param | Default | Meaning |
|---|---|---|
rosout_topic |
/rosout |
log topic to subscribe |
severity_floor |
30 (WARN) |
minimum level promoted; raise to 40 on chatty / constrained targets. Clamped to [0, 50] at load (a value out of range is corrected with a warning) |
code_prefix |
LOG |
prefix for generated fault codes; normalized to [A-Z0-9_] at load |
exclude_nodes |
[] |
node-FQN substrings to skip |
include_only_nodes |
[] |
if set, only promote nodes whose FQN matches |
max_tracked_nodes |
512 |
cap on per-node reporters; least-recently-used nodes evicted past this |
report_cooldown_sec |
5.0 |
per-fault_code forward debounce; 0.0 disables |
exclude_nodes / include_only_nodes match as unanchored substrings
against the node FQN: planner matches /planner_server and
/robot1/planner_server. Use a longer, more specific substring (e.g.
File truncated at 100 lines see the full file
Changelog for package ros2_medkit_log_bridge
Forthcoming
- Initial release: promote
/rosoutlog entries (WARN/ERROR/FATAL) to FaultManager faults, attributed to the originating node via a per-source FaultReporter, with auto-generated stable fault codes.