日志组件

优质
小牛编辑
137浏览
2023-12-01

日志组件接口

宏定义

#define LOG_E(...)   ulog_e(LOG_TAG, __VA_ARGS__)
 错误级别日志
 
#define LOG_W(...)   ulog_w(LOG_TAG, __VA_ARGS__)
 警告级别日志
 
#define LOG_I(...)   ulog_i(LOG_TAG, __VA_ARGS__)
 提示级别日志
 
#define LOG_D(...)   ulog_d(LOG_TAG, __VA_ARGS__)
 调试级别日志
 
#define LOG_RAW(...)   ulog_raw(__VA_ARGS__)
 输出 raw 日志
 

函数

int ulog_init (void)
 ULOG 初始化
 
void ulog_deinit (void)
 ULOG 去初始化
 
rt_err_t ulog_backend_register (ulog_backend_t backend, const char *name, rt_bool_t support_color)
 注册后端设备
 
rt_err_t ulog_backend_unregister (ulog_backend_t backend)
 注销后端设备
 
int ulog_tag_lvl_filter_set (const char *tag, rt_uint32_t level)
 按模块/标签的级别过滤日志
 
void ulog_global_filter_lvl_set (rt_uint32_t level)
 按级别过滤日志(全局)
 
void ulog_global_filter_tag_set (const char *tag)
 按标签过滤日志(全局)
 
void ulog_global_filter_kw_set (const char *keyword)
 按关键词过滤日志(全局)
 
void ulog_flush (void)
 输出缓冲区日志到后端
 
void ulog_hexdump (const char *tag, rt_size_t width, rt_uint8_t *buf, rt_size_t size)
 输出 HEX 格式日志
 
void ulog_raw (const char *format,...)
 输出 raw 日志
 

详细描述

日志组件接口

ulog 是一个非常简洁、易用的 C/C++ 日志组件,第一个字母 u 代表 μ,即微型的意思。它能做到最低 ROM<1K, RAM<0.2K 的资源占用。ulog 不仅有小巧体积,同样也有非常全面的功能,其设计理念参考的是另外一款 C/C++ 开源日志库:EasyLogger(简称 elog),并在功能和性能等方面做了非常多的改进。主要特性如下:

  • 日志输出的 后端多样化 ,可支持例如:串口、网络,文件、闪存等后端形式;
  • 日志输出被设计为 线程安全 的方式,并支持 异步输出 模式;
  • 日志系统 高可靠 ,在中断 ISR 、Hardfault 等复杂环境下依旧可用;
  • 支持 动态/静态 开关控制全局的日志输出级别;
  • 各模块的日志支持 动态/静态 设置输出级别;
  • 日志内容支持按 关键词及标签 方式进行全局过滤;
  • API 和日志格式可兼容 linux syslog
  • 支持以 hex 格式 dump 调试数据到日志中;
  • 兼容 rtdbg (RTT 早期的日志头文件)及 EasyLogger 的日志输出 API。
https://www.xnip.cn/wp-content/uploads/2021/docimg6/12-4bvjxhlufge.jpg ulog 框架总览

上图为 ulog 的内部框架图,由此可见:

  • 前端 :该层作为离应用最近的一层,给用户提供了 syslog 及 LOG_X 两类 API 接口,方便用户在不同的场景中使用;
  • 核心 :中间核心层的主要工作是将上层传递过来的日志,按照不同的配置要求进行格式化与过滤然后生成日志帧,最终通过不同的输出模块,输出到最底层的后端设备上;
  • 后端 :接收到核心层发来的日志帧后,将日志输出到已经注册的日志后端设备上,例如:文件、控制台、日志服务器等等。

在 ulog 中,每条日志都有自己的日志级别,日志级别代表了日志的重要性,在 ulog 中 由高到低 ,有如下几个日志级别:

级别名称对应宏描述
LOG_LVL_ASSERT断言ASSERT()发生无法处理、致命性的的错误,以至于系统无法继续运行的断言日志
LOG_LVL_ERROR错误LOG_E(...)发生严重的、 不可修复 的错误时输出的日志属于错误级别日志
LOG_LVL_WARNING警告LOG_W(...)出现一些不太重要的、具有 可修复性 的错误时,会输出这些警告日志
LOG_LVL_INFO信息LOG_I(...)给本模块上层使用人员查看的重要提示信息日志,例如:初始化成功,当前工作状态等。该级别日志一般在量产时依旧 保留
LOG_LVL_DBG调试LOG_D(...)给本模块开发人员查看的调试日志,该级别日志一般在量产时 关闭

相关应用笔记:

宏定义说明

#define LOG_E( ...)   ulog_e(LOG_TAG, __VA_ARGS__)

错误级别日志

'E'为LOG_LVL_ERROR的缩写,表示发生严重的、不可修复的错误时输出的日志属于错误级别日志 。

参数
...日志内容,格式与 printf 一致
#define LOG_W( ...)   ulog_w(LOG_TAG, __VA_ARGS__)

警告级别日志

'W'为 LOG_LVL_WARNING 的缩写,表示出现一些不太重要的、具有可修复性的错误时,会输出这些警告日志。

参数
...日志内容,格式与 printf 一致
#define LOG_I( ...)   ulog_i(LOG_TAG, __VA_ARGS__)

提示级别日志

'I'为 LOG_LVL_INFO 的缩写,表示给本模块上层使用人员查看的重要提示信息日志,例如:初始化成功,当前工作状态等。该级别日志一般在量产时依旧保留。

参数
...日志内容,格式与 printf 一致
#define LOG_D( ...)   ulog_d(LOG_TAG, __VA_ARGS__)

调试级别日志

'D'为 LOG_LVL_DBG 的缩写,表示给本模块开发人员查看的调试日志,该级别日志一般在量产时关闭。

参数
...日志内容,格式与 printf 一致
#define LOG_RAW( ...)   ulog_raw(__VA_ARGS__)

输出 raw 日志

LOG_Xulog_x 这类 API 输出都是带格式日志,有些时候需要输出不带任何格式的日志时,可以使用LOG_RAWvoid ulog_raw(const char *format, ...) 函数。

参数
...日志内容,格式与 printf 一致

函数说明

int ulog_init(void )

ULOG 初始化

在使用 ulog 前必须调用该函数完成 ulog 初始化。如果开启了组件自动初始化, API 也将被自动调用。

返回
返回描述
0成功
-RT_ENOMEM失败,内存不足
void ulog_deinit(void )

ULOG 去初始化

当 ulog 不再使用时,可以执行该函数释放资源。

rt_err_t ulog_backend_register(ulog_backend_t backend,
const char * name,
rt_bool_t support_color 
)

注册后端设备

将后端设备注册到 ulog 中,注册前确保后端设备控制块中的函数成员已设置。

参数
backend后端设备对象
name后端设备名称
support_color是否支持彩色日志
返回
RT_EOK 成功
rt_err_t ulog_backend_unregister(ulog_backend_t backend)

注销后端设备

将后端设备从 ulog 中移除。

参数
backend后端设备对象
返回
RT_EOK 成功
int ulog_tag_lvl_filter_set(const char * tag,
rt_uint32_t level 
)

按模块/标签的级别过滤日志

通过这个 API 可以按照标签的级别来过滤日志,常见功能对应的函数调用与命令示例如下:

功能函数调用执行命令
关闭 wifi 模块全部日志ulog_tag_lvl_filter_set("wifi", LOG_FILTER_LVL_SILENT);ulog_tag_lvl wifi 0
开启 wifi 模块全部日志ulog_tag_lvl_filter_set("wifi", LOG_FILTER_LVL_ALL);ulog_tag_lvl wifi 7
设置 wifi 模块日志级别为警告ulog_tag_lvl_filter_set("wifi", LOG_LVL_WARNING);ulog_tag_lvl wifi 4
参数
tag日志的标签
level设定的日志级别,详见 ulog_def.h
返回
>=0 成功;-5 失败,没有足够的内存。
void ulog_global_filter_lvl_set(rt_uint32_t level)

按级别过滤日志(全局)

设定全局的日志过滤器级别,低于这个级别的日志都将停止输出。 常见功能对应的函数调用与命令示例如下:

功能函数调用执行命令
关闭全部日志ulog_global_filter_lvl_set(LOG_FILTER_LVL_SILENT);ulog_lvl 0
开启全部日志ulog_global_filter_lvl_set(LOG_FILTER_LVL_ALL);ulog_lvl 7
设置日志级别为警告ulog_global_filter_lvl_set(LOG_LVL_WARNING);ulog_lvl 4
参数
level设定的级别,可设定的级别包括:
级别名称
LOG_LVL_ASSERT断言
LOG_LVL_ERROR错误
LOG_LVL_WARNING警告
LOG_LVL_INFO信息
LOG_LVL_DBG调试
LOG_FILTER_LVL_SILENT静默(停止输出)
LOG_FILTER_LVL_ALL全部
void ulog_global_filter_tag_set(const char * tag)

按标签过滤日志(全局)

设定全局的日志过滤器标签,该过滤方式可以对所有日志执行按标签过滤,只有 包含标签信息 的日志才允许输出。

例如:有 wifi.driverwifi.mgntaudio.driver 3 种标签的日志,当设定过滤标签为 wifi 时,只有标签为 wifi.driverwifi.mgnt 的日志会输出。同理,当设置过滤标签为 driver 时,只有标签为 wifi.driveraudio.driver 的日志会输出。常见功能对应的函数调用与命令示例如下:

功能函数调用执行命令
设置过滤标签为 wifiulog_global_filter_tag_set("wifi");ulog_tag wifi
设置过滤标签为 driverulog_global_filter_tag_set("driver");ulog_tag dirver
设置日志级别为警告ulog_global_filter_tag_set("");ulog_tag
参数
tag设定的过滤标签
void ulog_global_filter_kw_set(const char * keyword)

按关键词过滤日志(全局)

设定全局的日志过滤器关键词,只有内容中 包含关键词信息 的日志才允许输出。常见功能对应的函数调用与命令示例如下:

功能函数调用执行命令
设置过滤关键词为 wifiulog_global_filter_kw_set("wifi");ulog_kw wifi
清空过滤关键词ulog_global_filter_kw_set("");ulog_kw
参数
keyword设定的过滤关键词
void ulog_flush(void )

输出缓冲区日志到后端

由于 ulog 的异步模式具有缓存机制,注册进来的后端内部也可能具有缓存。 如果系统出现了 hardfault 、断言等错误情况,但缓存中还有日志没有输出出来, 这可能会导致日志丢失的问题,对于查找异常的原因会无从入手。 当出现异常时,输出异常信息日志时,同时再调用该函数,即可保证缓存中剩余的日志也能够输出到后端中去。

下面以 RT-Thread 的断言进行举例:

RT-Thread 的断言支持断言回调(hook),我们定义一个类似如下的断言 hook 函数,然后通过 rt_assert_set_hook(rtt_user_assert_hook); 函数将其设置到系统中即可。

static void rtt_user_assert_hook(const char* ex, const char* func, rt_size_t line){ rt_enter_critical(); ulog_output(LOG_LVL_ASSERT, "rtt", RT_TRUE, "(%s) has assert failed at %s:%ld.", ex, func, line); // flush all log ulog_flush(); while(1);}
void ulog_hexdump(const char * tag,
rt_size_t width,
rt_uint8_tbuf,
rt_size_t size 
)

输出 HEX 格式日志

以 16 进制 hex 格式 dump 数据到日志中。

参数
tag日志标签
width一行 hex 内容的宽度(数量)
buf待输出的数据内容
size数据大小

注意:

  • hexdump 日志为 DEBUG 级别,并支持运行期的级别过滤
  • hexdump 日志对应的 tag ,支持运行期的标签过滤
void ulog_raw(const char * format,
 ... 
)

输出 raw 日志

有些时候需要输出不带任何格式的日志时,可以使用LOG_RAWvoid ulog_raw(const char *format, ...) 函数。

参数
format格式化字符串的格式
...日志内容,格式与 printf 一致
参见
LOG_RAW(...)