Skip to content

Conversation

nnarain
Copy link

@nnarain nnarain commented Jun 28, 2025

Description

This PR adds a new log verb to the ros2cli node commands, enable a user to set the log level of a node.

Is this user-facing behavior change?

New log verb.

ros2 node log /my_node DEBUG

Did you use Generative AI?

Portions of the call_log_level_set function were generated using GitHub Copilot, GPT-4.1 auto-completion. It was edited manually to fix issues and tested.

Additional Information

Copy link
Contributor

@ahcorde ahcorde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linters are failing https://build.ros2.org/job/Rpr__ros2cli__ubuntu_noble_amd64/207/#showFailuresLink

Do you mind to add some tests too ?

Copy link
Collaborator

@fujitatomoya fujitatomoya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • This command requires that Node has to enable enable_logger_service (default off), otherwise it only shows that Service <node name>/set_logger_levels not ready. actually the service will never be ready, unless the user application explicitly enables the service programmatically.
  • when the enable_logger_service is enabled, user knows how this works as service from https://docs.ros.org/en/rolling/Tutorials/Demos/Logging-and-logger-configuration.html#logger-level-configuration-externally. so that user can use ros2 service xxx command to get/set logger level of the node. why do we need to have the duplicated method? ros2 service command is also 1st class command line interface, i do not see the necessary reason to remap the same operation to ros2 node xxx command.

with above reasons, i am not sure that having this subcommand is a right thing to do. any thoughts?

@nnarain
Copy link
Author

nnarain commented Jul 1, 2025

@fujitatomoya

This command requires that Node has to enable enable_logger_service (default off), otherwise it only shows that Service /set_logger_levels not ready. actually the service will never be ready, unless the user application explicitly enables the service programmatically.

I don't think there's any harm in command existing if the logger services are disabled by default. Maybe it could be logged more clearly like: "Service not available. Are the logging services enabled?"

when the enable_logger_service is enabled, user knows how this works as service from https://docs.ros.org/en/rolling/Tutorials/Demos/Logging-and-logger-configuration.html#logger-level-configuration-externally. so that user can use ros2 service xxx command to get/set logger level of the node. why do we need to have the duplicated method? ros2 service command is also 1st class command line interface, i do not see the necessary reason to remap the same operation to ros2 node xxx command.

I think this argument could be applied to any ros2 <subcommand> that calls a service? For example ros2 lifecycle xxx calls services under the hood https://github.com/ros2/ros2cli/blob/rolling/ros2lifecycle/ros2lifecycle/api/__init__.py

I personally don't find

ros2 service call /NodeWithLoggerService/set_logger_levels rcl_interfaces/srv/SetLoggerLevels '{levels: [{name: "NodeWithLoggerService", level: 20}, {name: "rcl", level: 10}]}'

to be the most convenient thing to write. Which was the motivation for the PR.

@fujitatomoya
Copy link
Collaborator

@nnarain thanks for sharing ideas!

to be the most convenient thing to write. Which was the motivation for the PR.

it is opposite for me. enable_logger_service is the service endpoint, so that i will try to use ros2 service xxx command to list/set/get. if the ros2 service command is hidden and internal command line, this makes sense. i would keep this operation with primitive interface for the maintainability.

let's keep this open to get more feedback from other maintainers and developers 👂

@christophebedard
Copy link
Member

🧇 I added this to the agenda for next week's ROS PMC meeting (2025-07-15).

Comment on lines 167 to 172
# Prepare the service name for the target node
service_name = f'{node_name}/set_logger_levels'
client = node.create_client(SetLoggerLevels, service_name)

if not client.service_is_ready():
raise RuntimeError(f'Service {service_name} not ready')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a comment about this part specifically:

As Tomoya said, the node will not have this service if its enable_logger_service node option isn't set to true: https://docs.ros.org/en/rolling/Tutorials/Demos/Logging-and-logger-configuration.html#logger-level-configuration-externally. It is false by default: https://github.com/ros2/rclcpp/blob/84c6fb1cfc945521680a0e1fccf5b32237acbcc3/rclcpp/include/rclcpp/node_options.hpp#L452

Instead of just throwing an error with a generic f'Service {service_name} not ready' message, it should let the user know that the service may not exist if the node doesn't have the enable_logger_service option enabled. This way the user knows exactly what to change in their code. Something like:

Suggested change
# Prepare the service name for the target node
service_name = f'{node_name}/set_logger_levels'
client = node.create_client(SetLoggerLevels, service_name)
if not client.service_is_ready():
raise RuntimeError(f'Service {service_name} not ready')
# Prepare the service name for the target node
service_name = f'{node_name}/set_logger_levels'
client = node.create_client(SetLoggerLevels, service_name)
if not client.service_is_ready():
raise RuntimeError(
f"Service '{service_name}' is not available. This service is only available if the "
f"'enable_logger_service' node option is enabled for node '{node_name}'."
)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah! I missed this from your earlier comment:

Maybe it could be logged more clearly like: "Service not available. Are the logging services enabled?"

Then yes, definitely!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated log line

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should explicitly mention the "'enable_logger_service' node option" not just "Are the logging services enabled?"

Users probably have no idea how to enable logging services. It's much more useful to tell them exactly what needs to change: enable the enable_logger_service node option

@nnarain
Copy link
Author

nnarain commented Jul 16, 2025

Added a unit test, but all tests are failing for me locally.

Seeing the following

Exception: Launch stopped before the active tests finished.

Seems like there's a known issue: #1073
though not entirely sure if this one is the same.

with self.launch_node_command(arguments=['log', '/complex_node', 'DEBUG']) as node_command:
assert node_command.wait_for_shutdown(timeout=10)
assert node_command.exit_code == launch_testing.asserts.EXIT_OK
assert node_command.output == 'Successfully set log level "/complex_node" to DEBUG.\n'
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests primarily revolve around checking the output of the command, which makes sense. Though in this case it's changing the state of complex node. I suppose the log service should be tested somewhere so just testing if the cli command was successful is sufficient.

@fujitatomoya
Copy link
Collaborator

IMO, setting log level with ros2 node log xxx and getting the log level with ros2 service xxx is inconsistent user experience that makes confusion. if we have ros2 node log xxx to set the log level to the node, it is probably nice to have getter subcommand with ros2 node log xxx?

besides that, we have a possible proposal for ros2 log xxx command to manage the logger of the node. @nnarain how do you think about this ros2 log xxx command introduction instead of ros2 node log xxx?

we need to take some time for more basic design, but off the top of my head (could be more useful subcommands)

  • ros2 log get <nodename>: get the log level of the node
  • ros2 log set <nodename> <log level>: set the log level of the node
  • ros2 log levels: show available log levels.
  • ros2 log list: list all nodes with runtime logger configuration support.
  • ros2 log watch <nodename>: Continuously watch log via rosout for the specified node to print the console.

if you want to go with current PR, that is fine. but i think ros2 log makes more sense for user interface for log dedicated command.

@nnarain
Copy link
Author

nnarain commented Jul 17, 2025

Ya I think that's a reasonable approach

@nnarain
Copy link
Author

nnarain commented Jul 18, 2025

@fujitatomoya @christophebedard

Regarding ros2 log watch ...

A rosout cli was proposed here: #850

Would that functionality be desired? I also work at Clearpath, and honestly I forgot the rosout subcommand we use was not upstream.

@fujitatomoya
Copy link
Collaborator

@nnarain thanks for the information.

actually as implementation detail for ros2 log watch command, i was considering to take advantage of Content Filtered Topic if rmw supports it to filter out the unrelated message from rosout topic. unfortunately at this moment, i just cannot allocate time for this design development, but i will come up with basic design once my moving (from US to Japan) is completed. Or if someone else is taking over this feature to discuss more details with proposals, that would be really appreciated.

@nnarain
Copy link
Author

nnarain commented Jul 18, 2025

Was there a written proposal for ros2 log somewhere? I just saw a line mentioning this from the ROS PMC meeting minutes. Sounds like you already have a plan.

I don't mean to step on any planned work here. I don't mind getting a PR going for ros2log, if that's the desired approach and no one else is actively working on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants