日志记录和日志记录器配置
概述
ROS 2 中的日志记录子系统旨在将日志消息传递到各种目标,包括:
输出到控制台(如果有连接的话)
输出到磁盘上的日志文件(如果有本地存储可用)
输出到ROS 2网络上的``/rosout``主题
默认情况下,ROS 2节点中的日志消息将输出到控制台(stderr)、输出到磁盘上的日志文件以及输出到ROS 2网络上的``/rosout``主题。所有这些目标都可以在每个节点上独立启用或禁用。
本文档的其余部分将介绍日志子系统背后的一些概念。
严重程度级别
日志消息与严重级别关联:``DEBUG``(调试)、``INFO``(信息)、``WARN``(警告)、``ERROR``(错误)或 ``FATAL``(致命),按升序排列。
记录器仅处理具有不低于记录器指定级别的严重级别的日志消息。
每个节点都有一个与之关联的记录器,自动包含节点的名称和命名空间。如果节点的名称在外部重映射为源代码中定义的其他内容,则会反映在记录器名称中。还可以创建使用特定名称的非节点记录器。
记录器名称表示层次结构。如果名称为“abc.def”的记录器的级别未设置,它将推迟到其父级名称为“abc”的级别,如果该级别也未设置,则使用默认记录器级别。更改记录器“abc”的级别时,除非明确设置了它们的级别,否则会影响其所有后代(例如“abc.def”、“abc.ghi.jkl”)的级别。
API
这些是ROS 2日志记录基础设施的终端用户应使用的API,按客户端库进行划分。
RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}
- 每次执行到这行时输出给定的 printf 样式的消息RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_ONCE
- 仅在第一次执行到这行时输出给定的 printf 样式的消息RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_EXPRESSION
- 仅在给定表达式为真时输出给定的 printf 样式的消息RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_FUNCTION
- 仅在给定函数返回 true 时输出给定的 printf 样式的消息RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_SKIPFIRST
- 第一次执行到这行时除外,输出给定的 printf 样式的消息RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_THROTTLE
- 以整数毫秒为单位,输出不超过给定速率的 printf 样式的消息RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_SKIPFIRST_THROTTLE
- 按照给定的整数毫秒速率输出printf风格的消息,但跳过第一次RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM
- 每次执行到此行时,输出给定的C++流式消息RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM_ONCE
- 仅在第一次执行到此行时,输出给定的C++流式消息RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM_EXPRESSION
- 仅在给定表达式为真时,输出给定的C++流式消息RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM_FUNCTION
- 仅在给定函数返回真时,输出给定的C++流式消息RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM_SKIPFIRST
- 第一次执行到此行时以外的其他时间,输出给定的C++流式消息RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM_THROTTLE
- 以整数毫秒的速率输出给定的C++流式消息,不超过指定的速率RCLCPP_{DEBUG,INFO,WARN,ERROR,FATAL}_STREAM_SKIPFIRST_THROTTLE
- 以整数毫秒的速率输出给定的C++流式消息,不超过指定的速率,但跳过第一个消息
上述每个API的第一个参数都需要传递一个``rclcpp::Logger``对象。可以通过调用``node->get_logger()``(推荐)从节点API中获取该对象,或者构建一个独立的``rclcpp::Logger``对象。
rcutils_logging_set_logger_level
- 将特定记录器名称的日志级别设置为给定的严重级别rcutils_logging_get_logger_effective_level
- 给定记录器名称,返回记录器的级别(可能未设置)
logger.{debug,info,warning,error,fatal}
- 将给定的Python字符串输出到日志记录基础设施。这些调用接受以下关键字参数来控制行为:throttle_duration_sec
- 如果不是 None,则为浮点数秒数的节流间隔持续时间skip_first
- 如果为 True,则在第一次命中此行之外的所有时间输出消息once
- 如果为 True,则仅在第一次命中此行时输出消息
rclpy.logging.set_logger_level
- 将特定日志记录器名称的日志记录级别设置为给定的严重级别rclpy.logging.get_logger_effective_level
- 给定日志记录器名称,返回日志记录级别(可能未设置)
配置
由于``rclcpp``和``rclpy``使用相同的底层日志记录基础设施,配置选项是相同的。
环境变量
以下环境变量控制ROS 2日志记录器的某些方面。对于每个环境设置,请注意这是一个进程级的设置,因此适用于该进程中的所有节点。
ROS_LOG_DIR
- 控制用于将日志消息写入磁盘的日志目录(如果启用)。如果非空,则使用此变量中指定的确切目录。如果为空,则使用``ROS_HOME``环境变量的内容构建路径,形式为``$ROS_HOME/.log``。在所有情况下,``~``字符会扩展为用户的主目录。ROS_HOME
- 控制用于各种ROS文件(包括日志和配置文件)的主目录。在日志记录的上下文中,此变量用于构建用于日志文件的目录路径。如果非空,则使用此变量的内容作为ROS_HOME路径。在所有情况下,``~``字符会扩展为用户的主目录。RCUTILS_LOGGING_USE_STDOUT
- 控制输出消息流的目标。如果未设置或为0,则使用stderr。如果为1,则使用stdout。RCUTILS_LOGGING_BUFFERED_STREAM
- 控制日志流(如在RCUTILS_LOGGING_USE_STDOUT
中配置)是否应该是行缓冲或无缓冲的。如果未设置此项,则使用流的默认设置(通常为标准输出的行缓冲,标准错误输出的无缓冲)。如果设置为 0,则强制将流设置为无缓冲。如果设置为 1,则强制将流设置为行缓冲。RCUTILS_COLORIZED_OUTPUT
- 控制是否在输出消息时使用颜色。如果未设置此项,则根据平台和控制台是否为 TTY 自动确定。如果设置为 0,则强制禁用输出时使用颜色。如果设置为 1,则强制启用输出时使用颜色。RCUTILS_CONSOLE_OUTPUT_FORMAT
- 控制每条日志消息输出的字段。可用字段有:{severity}
- 严重级别。{name}
- 日志记录器的名称(可能为空)。{message}
- 日志消息(可能为空)。{function_name}
- 调用此函数的函数名称(可能为空)。{file_name}
- 调用此函数的文件名(可能为空)。{time}
- 自纪元以来的秒数。{time_as_nanoseconds}
- 自纪元以来的纳秒数。{line_number}
- 调用此函数的行号(可能为空)。
如果未提供格式,则使用默认格式
[{severity}] [{time}] [{name}]: {message}
。
节点创建
当初始化ROS 2节点时,可以通过节点选项来控制一些行为方面的细节。由于这些是每个节点的选项,即使将节点组合到单个进程中,也可以为不同的节点设置不同的选项。
log_levels
- 在此特定节点内使用的组件的日志级别。可以使用以下命令设置:ros2 run demo_nodes_cpp talker --ros-args --log-level talker:=DEBUG
external_log_config_file
- 用于配置后端日志记录器的外部文件。如果为NULL,则将使用默认配置。请注意,此文件的格式是特定于后端的(当前未实现默认后端记录器spdlog的配置)。可以使用以下命令设置:ros2 run demo_nodes_cpp talker --ros-args --log-config-file log-config.txt
log_stdout_disabled
- 是否禁止将日志消息写入控制台。可以使用以下命令执行:ros2 run demo_nodes_cpp talker --ros-args --disable-stdout-logs
log_rosout_disabled
- 是否禁止将日志消息写入``/rosout``。这可以大大节省网络带宽,但外部观察者将无法监视日志记录。可以使用以下命令执行:ros2 run demo_nodes_cpp talker --ros-args --disable-rosout-logs
log_ext_lib_disabled
- 是否完全禁用外部日志记录器的使用。在某些情况下,这可能更快,但意味着日志不会写入磁盘。可以使用以下命令来实现:ros2 run demo_nodes_cpp talker --ros-args --disable-external-lib-logs
日志子系统设计
下图显示了日志子系统的五个主要组件及其交互方式。
rcutils
rcutils``具有一个日志实现,可以根据特定格式(参见上面的``配置
)格式化日志消息,并将这些日志消息输出到控制台。``rcutils``实现了一个完整的日志解决方案,但允许较高级别的组件以依赖注入模型插入到日志基础设施中。当我们谈到下面的``rcl``层时,这将变得更加明显。
请注意,这是一种*每个进程*的日志记录实现,因此在此级别配置的任何内容都将影响整个进程,而不仅仅是单个节点。
rcl_logging_spdlog
rcl_logging_spdlog
实现了 rcl_logging_interface
API,因此为 rcl
层提供外部日志记录服务。特别是,rcl_logging_spdlog
实现接受格式化的日志消息,并使用 spdlog
库将它们写入磁盘上的日志文件,通常位于 ~/.ros/log``(尽管此处可配置;请参阅上述 ``Configuration
)。
rcl
rcl
中的日志记录子系统使用 rcutils
和 rcl_logging_spdlog
来提供大部分 ROS 2 日志记录服务。当日志消息到达时,rcl
决定将其发送到何处。有三个主要位置可以传送日志消息;单个节点可以启用其中任意组合:
通过
rcutils
层发送到控制台通过``rcl_logging_spdlog``层将日志写入磁盘
通过RMW层将日志发送到ROS 2网络上的``/rosout``主题