记录日志
目录
有关可用功能的详细信息,请参阅 日志页面。
在代码中使用日志语句
基本日志记录
下面的代码将在``DEBUG``级别从ROS 2节点输出日志消息:
// printf style
RCLCPP_DEBUG(node->get_logger(), "My log message %d", 4);
// C++ stream style
RCLCPP_DEBUG_STREAM(node->get_logger(), "My log message " << 4);
node.get_logger().debug('My log message %d' % (4))
请注意,在两种情况下都不会添加尾随换行符,因为日志记录基础设施将自动添加一个。
仅记录第一次
下面的代码将在``INFO``级别从ROS 2节点输出日志消息,但仅在第一次调用时:
// printf style
RCLCPP_INFO_ONCE(node->get_logger(), "My log message %d", 4);
// C++ stream style
RCLCPP_INFO_STREAM_ONCE(node->get_logger(), "My log message " << 4);
num = 4
node.get_logger().info(f'My log message {num}', once=True)
记录除第一次之外的所有日志
以下代码将从一个ROS 2节点以``WARN``严重程度输出日志消息,但在第一次触发时不输出:
// printf style
RCLCPP_WARN_SKIPFIRST(node->get_logger(), "My log message %d", 4);
// C++ stream style
RCLCPP_WARN_STREAM_SKIPFIRST(node->get_logger(), "My log message " << 4);
num = 4
node.get_logger().warning('My log message {0}'.format(num), skip_first=True)
记录被节流
以下代码将从一个ROS 2节点以``ERROR``严重程度输出日志消息,但每秒钟不超过一次。
间隔参数指定消息之间的毫秒数应具有整数数据类型,以便可以将其转换为 rcutils_duration_value_t``(即 ``int64_t
):
// printf style
RCLCPP_ERROR_THROTTLE(node->get_logger(), *node->get_clock(), 1000, "My log message %d", 4);
// C++ stream style
RCLCPP_ERROR_STREAM_THROTTLE(node->get_logger(), *node->get_lock(), 1000, "My log message " << 4);
// For now, use the nanoseconds() method to use an existing rclcpp::Duration value, see https://github.com/ros2/rclcpp/issues/1929
RCLCPP_ERROR_STREAM_THROTTLE(node->get_logger(), *node->get_clock(), msg_interval.nanoseconds()/1000000, "My log message " << 4);
num = 4
node.get_logger().error(f'My log message {num}', throttle_duration_sec=1)
除第一次外,日志被限制了频率
以下代码将在 ROS 2 节点中以 DEBUG
严重性输出日志消息,每秒最多一次,并跳过第一次命中:
// printf style
RCLCPP_DEBUG_SKIPFIRST_THROTTLE(node->get_logger(), *node->get_clock(), 1000, "My log message %d", 4);
RCLCPP_DEBUG_SKIPFIRST_THROTTLE(node->get_logger(), *node->get_clock(), 1000, "My log message " << 4);
num = 4
node.get_logger().debug(f'My log message {num}', skip_first=True, throttle_duration_sec=1.0)
日志演示
在这个 演示 中,展示了不同类型的日志调用,并配置了不同日志记录器的严重级别,可以在本地和外部进行配置。
使用以下命令启动演示:
ros2 run logging_demo logging_demo_main
随着时间的推移,您将看到具有不同属性的各种日志调用的输出。首先,您只会看到具有严重级别为 INFO
及以上(WARN
、ERROR
、FATAL
)的日志调用的输出。请注意,尽管在每次迭代中都会到达该行,但第一条消息只会被记录一次,因为它是用于该消息的日志调用的属性之一。
日志目录配置
日志目录可以通过两个环境变量进行配置:ROS_LOG_DIR
和 ROS_HOME
。逻辑如下:
如果``ROS_LOG_DIR``已设置且非空,则使用``$ROS_LOG_DIR``。
否则,使用``$ROS_HOME/log``,如果未设置或为空,则使用``~/.ros``作为``ROS_HOME``。
例如,要将日志目录设置为 ~/my_logs
:
export ROS_LOG_DIR=~/my_logs
ros2 run logging_demo logging_demo_main
export ROS_LOG_DIR=~/my_logs
ros2 run logging_demo logging_demo_main
set "ROS_LOG_DIR=~/my_logs"
ros2 run logging_demo logging_demo_main
然后您将在 ~/my_logs/
下找到日志文件。
另外,您可以设置 ROS_HOME
,日志目录将相对于它而定($ROS_HOME/log
)。ROS_HOME
旨在用于需要基础目录的任何内容。请注意,ROS_LOG_DIR
必须未设置或为空。例如,当将 ROS_HOME
设置为 ~/my_ros_home
时:
export ROS_HOME=~/my_ros_home
ros2 run logging_demo logging_demo_main
export ROS_HOME=~/my_ros_home
ros2 run logging_demo logging_demo_main
set "ROS_HOME=~/my_ros_home"
ros2 run logging_demo logging_demo_main
然后您将在 ~/my_ros_home/log/
下找到日志文件。
日志记录器级别配置:编程方式
经过10次迭代,日志记录器的级别将被设置为``DEBUG``,这将导致额外的消息被记录。
其中一些调试消息会导致评估额外的函数/表达式,这些函数/表达式在未启用``DEBUG``日志调用时以前被跳过。有关使用的调用的进一步解释,请参阅演示的`源代码 <https://github.com/ros2/demos/blob/humble/logging_demo/src/logger_usage_component.cpp>`__,并参阅 rclcpp 日志记录文档以获得支持的日志记录调用的完整列表。
日志记录器级别配置:外部
将来将会有一种通用方法来在运行时外部配置日志记录器(类似于 ROS 1 中通过远程过程调用允许日志记录器配置的方式,如 rqt_logger_level)。**目前,ROS 2 尚未正式支持这个概念。**与此同时,此演示提供了一个**示例**服务,可用于外部调用以请求配置进程中已知日志记录器的级别。
之前启动的演示已经在运行这个示例服务。要将演示的日志记录器级别设置回``INFO``,请使用以下命令调用该服务:
ros2 service call /config_logger logging_demo/srv/ConfigLogger "{logger_name: 'logger_usage_demo', level: INFO}"
只要您知道日志记录器的名称,此服务调用将适用于正在运行的任何日志记录器,包括ROS 2核心中的日志记录器,如``rcl``(常见的客户端库包)。要为``rcl``启用调试日志记录,请执行以下命令:
ros2 service call /config_logger logging_demo/srv/ConfigLogger "{logger_name: 'rcl', level: DEBUG}"
您应该会看到``rcl``的调试输出开始显示。
使用日志记录器配置组件
响应记录器配置请求的服务器已被开发为一个组件,以便可以将其添加到现有的基于组合的系统中。例如,如果您正在使用`容器运行您的节点<../Intermediate/Composition>`,为了能够配置您的记录器,您只需要请求将``logging_demo::LoggerConfig``组件额外加载到容器中。
例如,如果您想调试``composition::Talker``演示程序,您可以正常启动Talker,如下所示:
Shell 1:
ros2 run rclcpp_components component_container
Shell 2:
ros2 component load /ComponentManager composition composition::Talker
当您想要启用调试日志记录时,使用以下命令加载“LoggerConfig”组件:
Shell 2
ros2 component load /ComponentManager logging_demo logging_demo::LoggerConfig
最后,通过处理空命名的日志记录器,将所有未设置的日志记录器配置为调试严重性。请注意,已经特别配置为使用特定严重性的日志记录器不会受到此调用的影响。
Shell 2:
ros2 service call /config_logger logging_demo/srv/ConfigLogger "{logger_name: '', level: DEBUG}"
您应该看到进程中以前未设置的日志记录器开始显示调试输出,包括来自ROS 2核心的输出。
日志级别配置:命令行
自 Bouncy ROS 2 版本开始,未显式设置严重性级别的日志记录器的级别可以从命令行进行配置。重新启动演示,包括以下命令行参数:
ros2 run logging_demo logging_demo_main --ros-args --log-level debug
这将将任何未设置级别的记录器的默认级别配置为调试级别。您应该能够从演示本身和 ROS 2 核心的记录器看到调试输出。
自 Galactic ROS 2 版本开始,可以从命令行配置单个记录器的严重性级别。重新启动演示,包括以下命令行参数:
ros2 run logging_demo logging_demo_main --ros-args --log-level logger_usage_demo:=debug
控制台输出格式化
如果您希望获得更详细或更简洁的格式化输出,您可以使用RCUTILS_CONSOLE_OUTPUT_FORMAT环境变量。例如,要在日志调用中额外获取时间戳和位置,请停止演示并使用设置了该环境变量的方式重新启动它:
export RCUTILS_CONSOLE_OUTPUT_FORMAT="[{severity} {time}] [{name}]: {message} ({function_name}() at {file_name}:{line_number})"
ros2 run logging_demo logging_demo_main
export RCUTILS_CONSOLE_OUTPUT_FORMAT="[{severity} {time}] [{name}]: {message} ({function_name}() at {file_name}:{line_number})"
ros2 run logging_demo logging_demo_main
set "RCUTILS_CONSOLE_OUTPUT_FORMAT=[{severity} {time}] [{name}]: {message} ({function_name}() at {file_name}:{line_number})"
ros2 run logging_demo logging_demo_main
您应该看到每条消息中额外打印的以秒为单位的时间戳、函数名称、文件名和行号。“time”选项仅在ROS 2 Bouncy版本及以后的版本中受支持。
控制台输出着色
默认情况下,当输出定向到终端时会进行着色。如果您想强制启用或禁用着色,可以使用``RCUTILS_COLORIZED_OUTPUT``环境变量。例如:
export RCUTILS_COLORIZED_OUTPUT=0 # 1 for forcing it
ros2 run logging_demo logging_demo_main
export RCUTILS_COLORIZED_OUTPUT=0 # 1 for forcing it
ros2 run logging_demo logging_demo_main
set "RCUTILS_COLORIZED_OUTPUT=0" :: 1 for forcing it
ros2 run logging_demo logging_demo_main
您应该看到现在调试、警告、错误和致命错误日志没有进行着色。
注解
在Linux和MacOS中,强制着色输出意味着如果您将输出重定向到文件中,将会出现ANSI转义颜色代码。在Windows中,着色方法依赖于控制台API。如果强制启用,您将收到一条新的警告,表示着色失败。默认行为已经检查输出是否为控制台,因此不建议强制着色。