日志系统使用指南
本页依据 文档基线与后续更新 中记录的 Zephyr main 快照更新。
Zephyr 日志系统提供模块/实例标识、严重等级、过滤、延后处理和多个后端。
公共头文件是 <zephyr/logging/log.h>,旧 <logging/log.h> 路径需要迁移。
模块日志
在 prj.conf 中配置:
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3
CONFIG_LOG_MODE_DEFERRED=y
然后在一个源文件中注册模块:
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(sensor_app, LOG_LEVEL_INF);
void log_measurement(int value)
{
LOG_INF("measurement=%d", value);
if (value < 0) {
LOG_WRN("unexpected value");
}
}
等级数值是:0 关闭,1 ERR,2 WRN,3 INF,4 DBG。
LOG_ERR/WRN/INF/DBG 使用对应等级,LOG_HEXDUMP_* 输出二进制数据。
格式与参数类型需匹配,例如 size_t 使用 %zu,指针使用 %p 并转换为 void *。
同一模块跨多个源文件时,只有一个文件 LOG_MODULE_REGISTER,其余文件使用
LOG_MODULE_DECLARE,并保持编译等级一致。
不要把注册宏放在会被多个源文件包含的普通头文件中。
配置模块等级
使用 Kconfig 模板创建应用自己的日志等级:
mainmenu "Sensor application"
source "Kconfig.zephyr"
module = SENSOR_APP
module-str = sensor application
source "subsys/logging/Kconfig.template.log_config"
随后以 CONFIG_SENSOR_APP_LOG_LEVEL 注册模块,并在 prj.conf 中选择模板生成的
等级选项,例如 CONFIG_SENSOR_APP_LOG_LEVEL_DBG=y。
全局 CONFIG_LOG_DEFAULT_LEVEL 本身是整数,不存在可通用套用的
CONFIG_LOG_DEFAULT_LEVEL_DBG=y 配置。
实例日志
同一模块有多个实例时,可使用 LOG_INSTANCE_* 按实例过滤:
#include <zephyr/logging/log.h>
#include <zephyr/logging/log_instance.h>
LOG_LEVEL_SET(LOG_LEVEL_INF);
struct sensor {
LOG_INSTANCE_PTR_DECLARE(log);
unsigned int id;
};
LOG_INSTANCE_REGISTER(sensor, first, LOG_LEVEL_INF);
static struct sensor first_sensor = {
LOG_INSTANCE_PTR_INIT(log, sensor, first)
.id = 1,
};
void report_sensor(void)
{
LOG_INST_INF(first_sensor.log, "id=%u", first_sensor.id);
}
相关宏处理日志禁用时的字段裁剪;不要绕过宏直接假设实例字段始终存在。
编译过滤与运行过滤
编译期过滤决定哪些语句进入镜像;运行时过滤不能恢复已经在编译期删除的日志。
CONFIG_LOG_MAX_LEVEL、CONFIG_LOG_OVERRIDE_LEVEL 和模块等级共同影响编译结果。
启用 CONFIG_LOG_RUNTIME_FILTERING=y 后,可通过日志控制接口对源和后端调整运行等级。
有多个后端时,每个后端可采用自己的过滤等级。
结合 Shell 的日志命令可查看状态和调整过滤,具体语法先查看设备上的 log --help。
处理模式与字符串
CONFIG_LOG_MODE_DEFERRED:前端打包,后续由处理线程或应用处理;常用于减少调用点耗时。CONFIG_LOG_MODE_IMMEDIATE:调用点同步处理,耗时包括格式化与输出。CONFIG_LOG_MODE_MINIMAL:以较少资源提供功能受限的日志。
延后模式需要有效的处理机制。若关闭内部日志处理线程,应按
<zephyr/logging/log_ctrl.h> 中的接口驱动处理,不能只写日志却从不消费。
CONFIG_LOG_BUFFER_SIZE、触发阈值、处理线程栈和输出速率共同影响是否丢日志。
当前日志实现内建对瞬态字符串参数的打包/复制机制,不应继续套用旧版日志系统的
log_strdup() 教程。自定义 cbprintf package、后端或前端时,仍应明确其格式字符串、
参数和载荷生命周期,见 cbprintf 与格式化打包。
后端、限流与 panic
UART、RTT、网络等后端需要对应设备和配置。CONFIG_LOG_PRINTK 可把 printk 导入日志,
延后模式下输出时间也会随之延后。
当前日志提供 LOG_*_RATELIMIT 及指定间隔的变体,适合重复错误或高频状态。
它们受 CONFIG_LOG_RATELIMIT 和关闭时 fallback 策略控制,
不能假设关闭限流功能后总会退化成普通日志。
log_panic() 切换到 panic 处理用于故障场景。正常应用仍应通过合理等级、缓冲区容量
和后端吞吐控制负载;输出日志会影响执行时间,不能仅凭“延后模式”认为没有实时性成本。