Zephyr日志使用指南-编译时日志过滤

Creative Commons
本作品采用知识共享署名

本文说明如何进行编译时日志消息过滤。

Zephyr中存在大量的模块日志,在系统编译或运行时均可进行日志过滤,编译时的过滤是指定日志最小的等级,一旦设定运行时无法改变。运行时过滤的等级只能大于或者等于编译时指定的过滤等级。例如编译时指定了过滤等级为WARNING,那么运行时只允许设置*_WRN*_ERR输出的消息,无法通过运行时设置让*_INF*_DBG的日志显示出来。对应的关系如下。

编译时过滤等级 LOG_ERR/LOG_HEXDUMP_ERR LOG_WRN/LOG_HEXDUMP_WRN LOG_INF/LOG_HEXDUMP_INF LOG_DBG/LOG_HEXDUMP_DBG
LOG_LEVEL_NONE 0 OFF OFF OFF OFF
LOG_LEVEL_ERR 1U ON OFF OFF OFF
LOG_LEVEL_WRN 2U ON ON OFF OFF
LOG_LEVEL_INF 3U ON ON ON OFF
LOG_LEVEL_DBG 4U ON ON ON ON

现有模块的编译时过滤等级

Zephyr的代码内有大量的日志输出,默认情况下这些日志都被限制在INFO等级,其DEBUG等级的日志不会输出到后端,在开发调试过程中遇到问题时希望查看模块DEBUG等级的日志进行诊断。另外就是在产品发布时会通过提高日志过滤等级只让ERROR等级输出甚至不输出。为达到这些目标就需要通过配置修改模块日志的默认过滤等级来开启日志。这里以I2C的为例说明如何指定模块的默认过滤等级:

  1. 找到模块代码,I2C的在drivers/i2c/目录下

  2. 打开任意有使用LOG_MODULE_REGISTER的源文件,例如i2c_esp32.c查看其配置项为CONFIG_I2C_LOG_LEVEL

    1
    LOG_MODULE_REGISTER(i2c_esp32, CONFIG_I2C_LOG_LEVEL);
  1. 使用配置项_等级模式在prj.conf中进行配置,可用配置项如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 不显示任何LOG
    CONFIG_I2C_LOG_LEVEL_OFF=y
    # 显示ERROR等级LOG
    CONFIG_I2C_LOG_LEVEL_ERR=y
    # 显示WARNING及以上等级LOG
    CONFIG_I2C_LOG_LEVEL_WRN=y
    # 显示INFO及以上等级LOG
    CONFIG_I2C_LOG_LEVEL_INF=y
    # 显示DEBUG及以上等级LOG
    CONFIG_I2C_LOG_LEVEL_DBG=y

注意:只能5选1,例如想要显示所有的I2C日志,就在prj.conf中添加

1
CONFIG_I2C_LOG_LEVEL_DBG=y

对于其它的模块也是一样的模式,例如想要关闭FLASH中日志,就在prj.conf中添加

1
CONFIG_FLASH_LOG_LEVEL_OFF=y

自定义模块的编译时过滤等级

Zephyr日志使用指南-模块日志一文中已经演示过编译时指定的过滤等级由LOG_MODULE_REGISTER的最后一个参数指定,例如

1
LOG_MODULE_REGISTER(module_name, 3)

LOG_MODULE_REGISTER是变参宏,当没有显式的指定过滤等级时,使用CONFIG_LOG_DEFAULT_LEVEL配置的过滤等级,默认情况下该配置项为3,也就是INFO等级。
例如

1
LOG_MODULE_REGISTER(module_name)

改变默认等级
prj.conf中添加下面配置5选一对默认过滤等级进行配置:

1
2
3
4
5
6
7
8
9
10
# 不显示任何LOG
CONFIG_LOG_DEFAULT_LEVEL_OFF=y
# 显示ERROR等级LOG
CONFIG_LOG_DEFAULT_LEVEL_ERR=y
# 显示WARNING及以上等级LOG
CONFIG_LOG_DEFAULT_LEVEL_WRN=y
# 显示INFO及以上等级LOG
CONFIG_LOG_DEFAULT_LEVEL_INF=y
# 显示DEBUG及以上等级LOG
CONFIG_LOG_DEFAULT_LEVEL_DBG=y

自定义模块过滤等级
前面的内容可以看到,在自定义的模块中我们是使用的数字直接指定编译时的过滤等级,当我们需要修改时,需要到源文件内进行修改,这样做并不方便。我们可以通过导入日志Kconfig模板的方式让自定义的模块也能通过配置项进行编译时默认过滤等级配置。方法如下:

  • 为自定义模块添加Kconfig文件,示例代码Kconfig.logging内容如下

    1
    2
    3
    4
    5
    6
    7
    8
    # 指定模块
    module = LOGGING_SAMPLE

    # 指定在menuconfig中配置项显示的字符串
    module-str = logging_sample

    # 导入日志配置模板
    source "subsys/logging/Kconfig.template.log_config"
  • 在自定义模块内应用配置项,示例代码内容如下

    1
    2
    #include <logging/log.h>
    LOG_MODULE_REGISTER(logging_sample, CONFIG_LOGGING_SAMPLE_LOG_LEVEL);
  • prj.conf中进行配置

    1
    CONFIG_LOGGING_SAMPLE_LOG_LEVEL_ERR=y

如果不进行配置,将默认为INFO等级。

可选配置项为

1
2
3
4
5
6
7
8
9
10
# 不显示任何LOG
CONFIG_LOGGING_SAMPLE_LOG_LEVEL_OFF=y
# 显示ERROR等级LOG
CONFIG_LOGGING_SAMPLE_LOG_LEVEL_ERR=y
# 显示WARNING及以上等级LOG
CONFIG_LOGGING_SAMPLE_LOG_LEVEL_WRN=y
# 显示INFO及以上等级LOG
CONFIG_LOGGING_SAMPLE_LOG_LEVEL_INF=y
# 显示DEBUG及以上等级LOG
CONFIG_LOGGING_SAMPLE_LOG_LEVEL_DBG=y

参考

https://docs.zephyrproject.org/latest/services/logging/index.html