日志库

[English]

概述

日志库提供了三种设置日志级别的方式:

  • 编译时:在 menuconfig 中,使用选项 CONFIG_LOG_DEFAULT_LEVEL 来设置日志级别。

  • 另外,还可以选择在 menuconfig 中使用选项 CONFIG_LOG_MAXIMUM_LEVEL 设置最高日志级别。这个选项默认被配置为默认级别,但这个选项也可以被配置为更高级别,将更多的可选日志编译到固件中。

  • 运行时:默认启用所有级别低于 CONFIG_LOG_DEFAULT_LEVEL 的日志。esp_log_level_set() 函数可以为各个模块分别设置不同的日志级别,可通过人类可读的 ASCII 零终止字符串标签来识别不同的模块。注意,在运行时是否可以更改日志级别由 CONFIG_LOG_DYNAMIC_LEVEL_CONTROL 决定。

  • 运行时:启用 CONFIG_LOG_MASTER_LEVEL 时,可以使用 esp_log_set_level_master() 函数设置 主日志级别 (Master logging level)。该选项会为所有已编译的日志添加额外的日志级别检查。注意,使用此选项会增加应用程序大小。如果希望在运行时编译大量可选日志,同时避免在不需要日志输出时查找标签及其级别带来的性能损耗,此功能会非常有用。

以下是不同的日志级别:

  • 错误(Error,最低级别)

  • 警告 (Warning)

  • 普通 (Info)

  • 调试 (Debug)

  • 冗余(Verbose,最高级别)

备注

注意,函数 esp_log_level_set() 无法将日志级别设置为高于 CONFIG_LOG_MAXIMUM_LEVEL 指定的级别。如需在编译时将特定文件的日志级别提高到此最高级别以上,请使用 LOG_LOCAL_LEVEL 宏(详细信息见下文)。

如何使用日志库

在使用日志功能的所有 C 文件中,将 TAG 变量定义如下:

static const char* TAG = "MyModule";

然后使用一个日志宏进行输出,例如:

ESP_LOGW(TAG, "Baud rate error %.1f%%. Requested: %d baud, actual: %d baud", error * 100, baud_req, baud_real);

可使用下列宏来定义不同的日志级别:

  • ESP_LOGE - 错误(最低级别)

  • ESP_LOGW - 警告

  • ESP_LOGI - 普通

  • ESP_LOGD - 调试

  • ESP_LOGV - 冗余(最高级别)

此外,上述宏还有对应的 ESP_EARLY_LOGx 版本,如 ESP_EARLY_LOGE。这些版本的宏必须在堆分配器和系统调用初始化之前,在早期启动代码中显式使用。通常情况下,编译引导加载程序时也可以使用普通的 ESP_LOGx 宏,但其最终实现与 ESP_EARLY_LOGx 宏相同。

上述宏还有对应的 ESP_DRAM_LOGx 版本,如 ESP_DRAM_LOGE。在禁用中断或无法访问 flash cache 的情况下需要输出日志时,可以使用这些版本的宏。但是,应尽量避免使用这些宏版本,因为在上述情况下输出日志可能会影响性能。

备注

在关键部分中断被禁用,因此只能使用 ESP_DRAM_LOGx (首选)或 ESP_EARLY_LOGx 宏。尽管这样可以输出日志,但最好可以调整程序使其不用输出日志。

如需在文件或组件范围内覆盖默认的日志级别,请定义 LOG_LOCAL_LEVEL 宏。

在文件中,该宏应在包含 esp_log.h 文件前进行定义,例如:

#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include "esp_log.h"

在组件中,该宏应在组件的 CMakeList 中进行定义:

target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DLOG_LOCAL_LEVEL=ESP_LOG_VERBOSE")

动态控制日志级别

如需在运行时按模块配置日志输出,请按如下方式调用 esp_log_level_set() 函数:

esp_log_level_set("*", ESP_LOG_ERROR);        // 将所有组件的日志级别设置为错误 (ERROR) 级别
esp_log_level_set("wifi", ESP_LOG_WARN);      // 启用来自 WiFi 堆栈的警告 (WARN) 日志
esp_log_level_set("dhcpc", ESP_LOG_INFO);     // 启用来自 DHCP 客户端的普通 (INFO) 日志

备注

上文介绍的 "DRAM" 和 "EARLY" 日志宏变型不支持按照模块设置日志级别。这些宏始终以“默认”级别记录日志,且只能在运行时调用 esp_log_level("*", level) 对日志级别进行更改。

即使已通过标签名称禁用日志输出,每个条目仍需约 10.9 微秒的处理时间。

日志组件提供多种选项,可以更好地调整系统以满足需求,从而减少内存使用并提高操作速度。CONFIG_LOG_TAG_LEVEL_IMPL 可配置检查标签级别:

  • None:选择此选项,则会禁用为每个标签设置日志级别的功能。在运行时是否可以更改日志级别取决于 CONFIG_LOG_DYNAMIC_LEVEL_CONTROL。如果禁用,则无法在运行时使用 esp_log_level_set() 更改日志级别。该选项适用于高度受限的环境。

  • Linked list (no cache):选择此选项,则会启用为每个标签设置日志级别的功能。此方法在链表中搜索所有标签的日志级别。如果标签数量比较多,这种方法可能会比较慢,但内存要求可能低于下面的 cache 方式。

  • Cache + Linked List (默认选项):选择此选项,则会启用为每个标签设置日志级别的功能。这种混合方法在速度和内存使用之间实现了平衡。cache 中存储最近访问的日志标签及其相应的日志级别,从而更快地查找常用标签。

启用 CONFIG_LOG_DYNAMIC_LEVEL_CONTROL 选项后,则可在运行时通过 esp_log_level_set() 更改日志级别。动态更改日志级别提高了灵活性,但也会产生额外的代码开销。 如果应用程序不需要动态更改日志级别,并且不需要使用标签来控制每个模块的日志,建议禁用 CONFIG_LOG_DYNAMIC_LEVEL_CONTROL。与默认选项相比,这可以节约大概 260 字节的 IRAM、264 字节的 DRAM、以及 1 KB 的 flash。这不仅可以简化日志,提高内存效率,还可以将应用程序中的日志操作速度提高约 10 倍。

备注

Linked listCache + Linked List 选项将自动启用 CONFIG_LOG_DYNAMIC_LEVEL_CONTROL

主日志级别

要启用主日志级别功能,须启用 CONFIG_LOG_MASTER_LEVEL 选项。该功能在调用 esp_log_write() 之前为 ESP_LOGx 宏添加了额外的级别检查。这样就可以设置更高的 CONFIG_LOG_MAXIMUM_LEVEL,并且不会在正常操作期间对性能造成影响(仅在有指示时)。应用程序可以全局设置主日志级别(esp_log_set_level_master())以强制执行最高日志级别。高于此级别的 ESP_LOGx 宏将直接跳过,不会调用 esp_log_write() 并进行标签查找。建议只在顶层应用程序中使用此功能,不要在共享组件中使用,因为这将覆盖所有使用该组件的用户的全局日志级别。默认情况下,启动时主日志级别是 CONFIG_LOG_DEFAULT_LEVEL

注意,由于此功能为所有 ESP_LOGx 宏添加了额外的检查,会导致应用程序的大小增加。

以下代码片段展示了主日志级别的运行方式。将主日志级别设置为 ESP_LOG_NONE 将在全局范围内禁用所有日志记录。esp_log_level_set() 目前不会影响日志记录。但在主日志级别释放后,日志将按照 esp_log_level_set() 中的设置打印输出。

// 在启动时,主日志级别为 CONFIG_LOG_DEFAULT_LEVEL,并等于ESP_LOG_INFO
ESP_LOGI("lib_name", "用于打印的消息");          // 打印普通 (INFO) 级别消息
esp_log_level_set("lib_name", ESP_LOG_WARN);        // 启用 lib_name 的警告 (WARN) 日志

esp_log_set_level_master(ESP_LOG_NONE);             // 全局禁用所有日志。esp_log_level_set 目前没有生效

ESP_LOGW("lib_name", "用于打印的消息");          // 主日志级别阻止了打印
esp_log_level_set("lib_name", ESP_LOG_INFO);        // 启用 lib_name 的 INFO 日志
ESP_LOGI("lib_name", "用于打印的消息");          // 主日志级别阻止了打印

esp_log_set_level_master(ESP_LOG_INFO);             // 全局启用所有 INFO 日志

ESP_LOGI("lib_name", "用于打印的消息");          // 打印一条 INFO 消息

通过 JTAG 将日志记录到主机

默认情况下,日志库使用类似 vprintf 的函数将格式化输出写入专用 UART。通过调用一个简单的 API,即可将所有日志通过 JTAG 输出,将日志输出速度提高数倍。如需了解详情,请参阅 记录日志到主机

线程安全

日志字符串首先被写入内存 buffer,然后发送到 UART 打印。日志调用是线程安全的,即不同线程的日志不会互相冲突。

应用示例

大多数 ESP-IDF 组件和示例都会使用日志库。如需查看有关日志功能的应用示例,请前往 ESP-IDF 的 examples 目录。与日志最相关的示例如下:

API 参考

Header File

Functions

vprintf_like_t esp_log_set_vprintf(vprintf_like_t func)

Set function used to output log entries.

By default, log output goes to UART0. This function can be used to redirect log output to some other destination, such as file or network. Returns the original log handler, which may be necessary to return output to the previous destination.

备注

Please note that function callback here must be re-entrant as it can be invoked in parallel from multiple thread context.

参数

func -- new Function used for output. Must have same signature as vprintf.

返回

func old Function used for output.

void esp_log_write(esp_log_level_t level, const char *tag, const char *format, ...)

Write message into the log.

This function is not intended to be used directly. Instead, use one of ESP_LOGE, ESP_LOGW, ESP_LOGI, ESP_LOGD, ESP_LOGV macros.

This function or these macros should not be used from an interrupt.

void esp_log_writev(esp_log_level_t level, const char *tag, const char *format, va_list args)

Write message into the log, va_list variant.

This function is provided to ease integration toward other logging framework, so that esp_log can be used as a log sink.

参见

esp_log_write()

Macros

ESP_EARLY_LOGE(tag, format, ...)

macro to output logs in startup code, before heap allocator and syscalls have been initialized. Log at ESP_LOG_ERROR level.

参见

printf,ESP_LOGE,ESP_DRAM_LOGE In the future, we want to become compatible with clang. Hence, we provide two versions of the following macros which are using variadic arguments. The first one is using the GNU extension ##__VA_ARGS__. The second one is using the C++20 feature VA_OPT(,). This allows users to compile their code with standard C++20 enabled instead of the GNU extension. Below C++20, we haven't found any good alternative to using ##__VA_ARGS__.

ESP_EARLY_LOGW(tag, format, ...)

macro to output logs in startup code at ESP_LOG_WARN level.

参见

ESP_EARLY_LOGE,ESP_LOGE, printf

ESP_EARLY_LOGI(tag, format, ...)

macro to output logs in startup code at ESP_LOG_INFO level.

参见

ESP_EARLY_LOGE,ESP_LOGE, printf

ESP_EARLY_LOGD(tag, format, ...)

macro to output logs in startup code at ESP_LOG_DEBUG level.

参见

ESP_EARLY_LOGE,ESP_LOGE, printf

ESP_EARLY_LOGV(tag, format, ...)

macro to output logs in startup code at ESP_LOG_VERBOSE level.

参见

ESP_EARLY_LOGE,ESP_LOGE, printf

ESP_LOG_EARLY_IMPL(tag, format, log_level, log_tag_letter, ...)
ESP_LOGE(tag, format, ...)
ESP_LOGW(tag, format, ...)
ESP_LOGI(tag, format, ...)
ESP_LOGD(tag, format, ...)
ESP_LOGV(tag, format, ...)
ESP_LOG_LEVEL(level, tag, format, ...)

runtime macro to output logs at a specified level.

参见

printf

参数
  • tag -- tag of the log, which can be used to change the log level by esp_log_level_set at runtime.

  • level -- level of the output log.

  • format -- format of the output log. See printf

  • ... -- variables to be replaced into the log. See printf

ESP_LOG_LEVEL_LOCAL(level, tag, format, ...)

runtime macro to output logs at a specified level. Also check the level with LOG_LOCAL_LEVEL. If CONFIG_LOG_MASTER_LEVEL set, also check first against esp_log_get_level_master().

参见

printf, ESP_LOG_LEVEL

ESP_DRAM_LOGE(tag, format, ...)

Macro to output logs when the cache is disabled. Log at ESP_LOG_ERROR level.

Similar to

Usage:

ESP_DRAM_LOGE(DRAM_STR("my_tag"), "format", orESP_DRAM_LOGE(TAG, "format", ...)`, where TAG is a char* that points to a str in the DRAM.

参见

ESP_EARLY_LOGE, the log level cannot be changed per-tag, however esp_log_level_set("*", level) will set the default level which controls these log lines also.

参见

esp_rom_printf,ESP_LOGE

备注

Unlike normal logging macros, it's possible to use this macro when interrupts are disabled or inside an ISR.

备注

Placing log strings in DRAM reduces available DRAM, so only use when absolutely essential.

ESP_DRAM_LOGW(tag, format, ...)

macro to output logs when the cache is disabled at ESP_LOG_WARN level.

参见

ESP_DRAM_LOGW,ESP_LOGW, esp_rom_printf

ESP_DRAM_LOGI(tag, format, ...)

macro to output logs when the cache is disabled at ESP_LOG_INFO level.

参见

ESP_DRAM_LOGI,ESP_LOGI, esp_rom_printf

ESP_DRAM_LOGD(tag, format, ...)

macro to output logs when the cache is disabled at ESP_LOG_DEBUG level.

参见

ESP_DRAM_LOGD,ESP_LOGD, esp_rom_printf

ESP_DRAM_LOGV(tag, format, ...)

macro to output logs when the cache is disabled at ESP_LOG_VERBOSE level.

参见

ESP_DRAM_LOGV,ESP_LOGV, esp_rom_printf

Type Definitions

typedef int (*vprintf_like_t)(const char*, va_list)

Header File

Functions

static inline esp_log_level_t esp_log_get_default_level(void)

Get the default log level.

This function returns the default log level. The default log level is used by the definition of ESP_LOGx macros and can be overridden for specific tags using esp_log_level_set("*", level). If CONFIG_LOG_DYNAMIC_LEVEL_CONTROL=n, changing the default log level is not possible.

返回

The default log level.

void esp_log_set_level_master(esp_log_level_t level)

Master log level.

Optional master log level to check against for ESP_LOGx macros before calling esp_log_write. Allows one to set a higher CONFIG_LOG_MAXIMUM_LEVEL but not impose a performance hit during normal operation (only when instructed). An application may set esp_log_set_level_master(level) to globally enforce a maximum log level. ESP_LOGx macros above this level will be skipped immediately, rather than calling esp_log or esp_log_write and doing a cache hit.

备注

The tradeoff is increased application size.

参数

level -- Master log level

esp_log_level_t esp_log_get_level_master(void)

Returns master log level.

返回

Master log level

void esp_log_level_set(const char *tag, esp_log_level_t level)

Set log level for given tag.

If logging for given component has already been enabled, changes previous setting.

To raise log level above the default one for a given file, define LOG_LOCAL_LEVEL to one of the ESP_LOG_* values, before including esp_log.h in this file.

If CONFIG_LOG_DYNAMIC_LEVEL_CONTROL is not selected the static (no-op) implementation of log level is used. Changing the log level is not possible, esp_log_level_set does not work.

备注

Note that this function can not raise log level above the level set using CONFIG_LOG_MAXIMUM_LEVEL setting in menuconfig.

参数
  • tag -- Tag of the log entries to enable. Must be a non-NULL zero terminated string. Value "*" resets log level for all tags to the given value. If the tag is NULL then a silent return happens.

  • level -- Selects log level to enable. Only logs at this and lower verbosity levels will be shown.

esp_log_level_t esp_log_level_get(const char *tag)

Get log level for a given tag, can be used to avoid expensive log statements.

If CONFIG_LOG_DYNAMIC_LEVEL_CONTROL is not selected the static (no-op) implementation of log level is used. Changing the log level is not possible, esp_log_level_set does not work. This function returns the default log level.

参数

tag -- Tag of the log to query current level. Must be a zero terminated string. If tag is NULL then the default log level is returned (see esp_log_get_default_level()).

返回

The current log level for the given tag.

Enumerations

enum esp_log_level_t

Log level.

Values:

enumerator ESP_LOG_NONE

No log output

enumerator ESP_LOG_ERROR

Critical errors, software module can not recover on its own

enumerator ESP_LOG_WARN

Error conditions from which recovery measures have been taken

enumerator ESP_LOG_INFO

Information messages which describe normal flow of events

enumerator ESP_LOG_DEBUG

Extra information which is not necessary for normal use (values, pointers, sizes, etc).

enumerator ESP_LOG_VERBOSE

Bigger chunks of debugging information, or frequent messages which can potentially flood the output.

enumerator ESP_LOG_MAX

Number of levels supported

Header File

Functions

void esp_log_buffer_hex_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level)

Logs a buffer of hexadecimal bytes at the specified log level.

This function logs a buffer of hexadecimal bytes with 16 bytes per line. The log level determines the severity of the log message.

备注

This function does not check the log level against the ESP_LOCAL_LEVEL. The log level comparison should be done in esp_log.h.

参数
  • tag -- Description tag to identify the log.

  • buffer -- Pointer to the buffer array containing the data to be logged.

  • buff_len -- Length of the buffer in bytes.

  • level -- Log level indicating the severity of the log message.

void esp_log_buffer_char_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t level)

This function logs a buffer of characters with 16 characters per line. The buffer should contain only printable characters. The log level determines the severity of the log message.

备注

This function does not check the log level against the ESP_LOCAL_LEVEL. The log level comparison should be done in esp_log.h.

参数
  • tag -- Description tag to identify the log.

  • buffer -- Pointer to the buffer array containing the data to be logged.

  • buff_len -- Length of the buffer in bytes.

  • level -- Log level indicating the severity of the log message.

void esp_log_buffer_hexdump_internal(const char *tag, const void *buffer, uint16_t buff_len, esp_log_level_t log_level)

This function dumps a buffer to the log in a formatted hex dump style, displaying both the memory address and the corresponding hex and ASCII values of the bytes. The log level determines the severity of the log message.

备注

This function does not check the log level against the ESP_LOCAL_LEVEL. The log level comparison should be done in esp_log.h.

备注

It is recommended to use terminals with a width of at least 102 characters to display the log dump properly.

参数
  • tag -- Description tag to identify the log.

  • buffer -- Pointer to the buffer array containing the data to be logged.

  • buff_len -- Length of the buffer in bytes.

  • log_level -- Log level indicating the severity of the log message.

Macros

ESP_LOG_BUFFER_HEX_LEVEL(tag, buffer, buff_len, level)

Log a buffer of hex bytes at specified level, separated into 16 bytes each line.

The hex log shows just like the one below:

 I (954) log_example: 54 68 65 20 77 61 79 20 74 6f 20 67 65 74 20 73
 I (962) log_example: 74 61 72 74 65 64 20 69 73 20 74 6f 20 71 75 69
 I (969) log_example: 74 20 74 61 6c 6b 69 6e 67 20 61 6e 64 20 62 65
 I (977) log_example: 67 69 6e 20 64 6f 69 6e 67 2e 20 2d 20 57 61 6c
 I (984) log_example: 74 20 44 69 73 6e 65 79 00

参数
  • tag -- Description tag to identify the log.

  • buffer -- Pointer to the buffer array containing the data to be logged.

  • buff_len -- Length of the buffer in bytes.

  • level -- Log level

ESP_LOG_BUFFER_CHAR_LEVEL(tag, buffer, buff_len, level)

Log a buffer of characters at specified level, separated into 16 bytes each line. Buffer should contain only printable characters.

The char log shows just like the one below:

 I (980) log_example: The way to get s
 I (985) log_example: tarted is to qui
 I (989) log_example: t talking and be
 I (994) log_example: gin doing. - Wal
 I (999) log_example: t Disney

参数
  • tag -- Description tag to identify the log.

  • buffer -- Pointer to the buffer array containing the data to be logged.

  • buff_len -- Length of the buffer in bytes.

  • level -- Log level.

ESP_LOG_BUFFER_HEXDUMP(tag, buffer, buff_len, level)

Dump a buffer to the log at specified level.

The dump log shows just like the one below:

 I (1013) log_example: 0x3ffb5bc0   54 68 65 20 77 61 79 20  74 6f 20 67 65 74 20 73  |The way to get s|
 I (1024) log_example: 0x3ffb5bd0   74 61 72 74 65 64 20 69  73 20 74 6f 20 71 75 69  |tarted is to qui|
 I (1034) log_example: 0x3ffb5be0   74 20 74 61 6c 6b 69 6e  67 20 61 6e 64 20 62 65  |t talking and be|
 I (1044) log_example: 0x3ffb5bf0   67 69 6e 20 64 6f 69 6e  67 2e 20 2d 20 57 61 6c  |gin doing. - Wal|
 I (1054) log_example: 0x3ffb5c00   74 20 44 69 73 6e 65 79  00                       |t Disney.|

备注

It is highly recommended to use terminals with over 102 text width.

参数
  • tag -- Description tag to identify the log.

  • buffer -- Pointer to the buffer array containing the data to be logged.

  • buff_len -- Length of the buffer in bytes.

  • level -- Log level.

ESP_LOG_BUFFER_HEX(tag, buffer, buff_len)

Log a buffer of hex bytes at Info level.

参见

ESP_LOG_BUFFER_HEX_LEVEL

参数
  • tag -- Description tag to identify the log.

  • buffer -- Pointer to the buffer array containing the data to be logged.

  • buff_len -- Length of the buffer in bytes.

ESP_LOG_BUFFER_CHAR(tag, buffer, buff_len)

Log a buffer of characters at Info level. Buffer should contain only printable characters.

参见

ESP_LOG_BUFFER_CHAR_LEVEL

参数
  • tag -- Description tag to identify the log.

  • buffer -- Pointer to the buffer array containing the data to be logged.

  • buff_len -- Length of the buffer in bytes.

Header File

Functions

uint32_t esp_log_timestamp(void)

Function which returns timestamp to be used in log output.

This function is used in expansion of ESP_LOGx macros. In the 2nd stage bootloader, and at early application startup stage this function uses CPU cycle counter as time source. Later when FreeRTOS scheduler start running, it switches to FreeRTOS tick count.

For now, we ignore millisecond counter overflow.

返回

timestamp, in milliseconds

char *esp_log_system_timestamp(void)

Function which returns system timestamp to be used in log output.

This function is used in expansion of ESP_LOGx macros to print the system time as "HH:MM:SS.sss". The system time is initialized to 0 on startup, this can be set to the correct time with an SNTP sync, or manually with standard POSIX time functions.

Currently, this will not get used in logging from binary blobs (i.e. Wi-Fi & Bluetooth libraries), these will still print the RTOS tick time.

返回

timestamp, in "HH:MM:SS.sss"

uint32_t esp_log_early_timestamp(void)

Function which returns timestamp to be used in log output.

This function uses HW cycle counter and does not depend on OS, so it can be safely used after application crash.

返回

timestamp, in milliseconds

Header File


此文档对您有帮助吗?