AimRT 从零到一:官方示例精讲 —— 四、logger示例.md
logger示例
官方仓库:logger
配置文件(configuration_logger.yaml
)
依据官方示例项目结构自行编写YAML配置文件:
# 基础信息
base_info:project_name: Logger # 项目名称build_mode_tags: ["EXAMPLE", "SIMULATION", "TEST_CAMERA"] # 构建模式标签aimrt_import_options: # AimRT框架的构建选项AIMRT_BUILD_TESTS: "OFF" # 是否构建测试代码AIMRT_BUILD_EXAMPLES: "ON" # 是否构建示例代码AIMRT_BUILD_DOCUMENT: "OFF" # 是否构建文档AIMRT_BUILD_RUNTIME: "ON" # 是否构建运行时核心AIMRT_BUILD_CLI_TOOLS: "OFF" # 是否构建命令行工具AIMRT_BUILD_WITH_PROTOBUF: "ON" # 是否启用Protobuf支持AIMRT_USE_LOCAL_PROTOC_COMPILER: "OFF" # 是否使用本地protoc编译器AIMRT_BUILD_WITH_ROS2: "OFF" # 是否集成ROS2支持AIMRT_BUILD_NET_PLUGIN: "OFF" # 是否构建网络插件AIMRT_BUILD_ROS2_PLUGIN: "OFF" # 是否构建ROS2插件# 模块
modules:- name: logger_module- name: logger_bench_module# pkg
pkgs:- name: logger_pkg # 包名modules:- name: logger_module- name: logger_bench_module# 部署
deploy_modes:- name: local_deploy # 部署模式名称deploy_ins: # 部署实例- name: local_ins_logger # 实例名称pkgs:- name: logger_pkg # 实例加载的包
module目录
logger
一个最基本的 cpp logger 示例,演示内容包括:
- 如何在 AimRT 中打印 Log 到控制台;
- 如何使用不同的日志级别;
模块定义(logger_module.h
)
#pragma once
#include <atomic>
#include <future>#include "aimrt_module_cpp_interface/module_base.h"namespace Logger::logger_module {
using namespace aimrt;// 日志模块类,继承自AIMRT模块基类
class LoggerModule : public aimrt::ModuleBase {public:LoggerModule() = default;~LoggerModule() override = default;// 获取模块信息ModuleInfo Info() const override {return ModuleInfo{.name = "LoggerModule"};}// 初始化模块bool Initialize(aimrt::CoreRef aimrt_ptr) override;// 启动模块bool Start() override;// 关闭模块void Shutdown() override;private:aimrt::CoreRef core_; // AIMRT核心引用aimrt::executor::ExecutorRef executor_; // 执行器引用std::atomic_bool run_flag_ = false; // 运行标志位std::promise<void> stop_sig_; // 停止信号
};} // namespace Logger::logger_module
模块实现(logger_module.cc
)
#include "logger_module/logger_module.h"#include "yaml-cpp/yaml.h"namespace Logger::logger_module {using namespace aimrt::logger;bool LoggerModule::Initialize(aimrt::CoreRef core) {// 保存AIMRT框架句柄core_ = core;// 获取执行器句柄executor_ = core_.GetExecutorManager().GetExecutor("work_executor");AIMRT_HL_CHECK_ERROR_THROW(core_.GetLogger(), executor_,"获取执行器'work_thread_pool'失败");AIMRT_HL_INFO(core_.GetLogger(), "初始化成功");return true;
}bool LoggerModule::Start() {run_flag_ = true;executor_.Execute([this]() {// 为当前作用域创建日志句柄auto GetLogger = [this]() { return core_.GetLogger(); };std::string s = "abc";int n = 0;while (run_flag_.load()) {++n;// 输出各级别日志AIMRT_TRACE("测试跟踪日志, 字符串 = {}, 计数器 = {}", s, n);AIMRT_DEBUG("测试调试日志, 字符串 = {}, 计数器 = {}", s, n);AIMRT_INFO("测试信息日志, 字符串 = {}, 计数器 = {}", s, n);AIMRT_WARN("测试警告日志, 字符串 = {}, 计数器 = {}", s, n);AIMRT_ERROR("测试错误日志, 字符串 = {}, 计数器 = {}", s, n);AIMRT_FATAL("测试致命日志, 字符串 = {}, 计数器 = {}", s, n);std::this_thread::sleep_for(std::chrono::seconds(1));}stop_sig_.set_value();});AIMRT_HL_INFO(core_.GetLogger(), "启动成功");return true;
}void LoggerModule::Shutdown() {if (run_flag_) {run_flag_ = false;stop_sig_.get_future().wait();}AIMRT_HL_INFO(core_.GetLogger(), "关闭成功");
}} // namespace Logger::logger_module
- 注意,提供的日志宏基于 C++20 Format 语法
实现内容很简单,不在此做具体分析,只需要关注配置文件的部分
对应的启动配置文件
# AIMRT框架主配置
aimrt:# 日志系统配置log:# 核心日志级别,可选值:Trace/Debug/Info/Warn/Error/Fatal/Off# 设置INFO表示只记录INFO及以上级别的日志core_lvl: INFO# 日志后端配置backends:# 使用控制台作为日志输出- type: console# 执行器配置executor:# 执行器列表executors:# 定义一个名为work_executor的执行器- name: work_executor# 执行器类型为简单线程type: simple_thread# 模块配置module:# 模块包配置pkgs:# 指定模块包路径- path: ./liblogger_pkg.so# 启用该包中的LoggerModule模块enable_modules: [LoggerModule]# 模块详细配置modules:# LoggerModule模块的配置- name: LoggerModule# 该模块的日志级别设置为TRACE(最详细)log_lvl: TRACE
-
core_lvl
设置的是AimRT核心的日志等级;modules
中的log_lvl
控制的是本模块的日志等级 -
backends
:日志输出后端,支持console
(控制台)、rotate_file
(滚动文件)等多种类型
logger rotate file
一个最基本的 cpp logger 示例,演示内容包括:
-
如何使用 rotate_file 类型 Log 后端并了解其配置项;
-
代码与上一个
logger
示例完全相同
对应的启动配置文件
aimrt: # AIMRT框架根配置节点# 日志系统配置部分log:# 核心日志级别配置(框架自身日志输出级别)# 可选值(区分大小写):# TRACE - 最详细跟踪信息(开发调试用)# DEBUG - 调试信息# INFO - 常规运行信息(推荐生产环境使用)# WARN - 警告信息# ERROR - 错误信息# FATAL - 致命错误# OFF - 关闭所有日志core_lvl: INFO # 当前设置为INFO级别# 日志输出后端配置(支持同时配置多个输出目标)backends:# 控制台输出配置(必选)- type: console # 输出到标准控制台# 滚动文件输出配置(可选)- type: rotate_file # 滚动文件类型options: # 文件输出专属配置path: ./log # 日志文件存储目录(相对路径)filename: examples_cpp_logger_rotate_file.log # 日志文件名max_file_size_m: 4 # 单个文件最大大小(单位MB)max_file_num: 10 # 最大保留文件数(达到后自动删除最旧文件)# 执行器(线程池)配置部分executor:# 执行器列表(可配置多个执行器)executors:# 工作执行器配置- name: work_executor # 执行器名称(需与代码中引用名称一致)type: simple_thread # 执行器类型:简单线程模式# 模块系统配置部分module:# 动态模块包配置(可配置多个模块包)pkgs:# 第一个模块包配置- path: ./liblogger_pkg.so # 模块动态库路径(相对/绝对路径)enable_modules: [LoggerModule] # 需要启用的模块列表(数组格式)# 模块详细参数配置(可覆盖模块默认参数)modules:# Logger模块配置- name: LoggerModule # 必须与代码中模块类名完全一致log_lvl: TRACE # 模块专用日志级别(可独立于core_lvl设置)
logger specify executor
一个最基本的 cpp logger 示例,演示内容包括:
- 如何使用指定的执行器作为日志后端的执行线程;
- 代码与示例
logger
相同
对应的启动配置文件
aimrt: # AIMRT框架根配置节点# 日志系统配置log:# 核心日志级别(框架自身日志输出级别)# 可选值(区分大小写):# TRACE - 最详细跟踪信息# DEBUG - 调试信息# INFO - 常规信息(推荐生产环境使用)# WARN - 警告信息# ERROR - 错误信息# FATAL - 致命错误# OFF - 关闭日志core_lvl: INFO # 当前设置为INFO级别# 日志输出后端配置backends:# 控制台日志输出配置- type: console # 控制台输出类型options:log_executor_name: log_executor # 指定专用的日志执行器# 执行器(线程池)配置executor:# 执行器列表(可配置多个)executors:# 工作执行器(用于业务逻辑)- name: work_executor # 执行器名称type: simple_thread # 简单线程模式# 专用日志执行器(确保日志输出不阻塞业务线程)- name: log_executor # 执行器名称需与日志配置一致type: simple_thread # 简单线程模式# 模块系统配置module:# 动态模块包配置pkgs:# 日志模块包配置- path: ./liblogger_pkg.so # 模块动态库路径enable_modules: [LoggerModule] # 启用的模块列表# 模块参数配置modules:# 日志模块配置- name: LoggerModule # 必须与代码中模块名一致log_lvl: TRACE # 模块日志级别(开发时可用TRACE)
- 这里创建了一个单独的日志执行器,避免日志I/O操作阻塞业务线程
- 要求日志执行器是线程安全的
logger format
一个最基本的 cpp logger 示例,演示内容包括:
- 如何使用自定义的 format 格式输出日志;
- 代码与示例
logger
相同
对应的启动配置文件
aimrt: # AIMRT框架根配置节点# 日志系统配置log:# 核心日志级别(框架自身日志输出级别)# 可选值(区分大小写):# TRACE - 最详细跟踪信息# DEBUG - 调试信息# INFO - 常规信息(推荐生产环境使用)# WARN - 警告信息# ERROR - 错误信息# FATAL - 致命错误# OFF - 关闭日志core_lvl: INFO # 当前设置为INFO级别# 日志输出后端配置backends:# 控制台日志输出配置- type: console # 控制台输出类型options:# 日志格式模板(支持自定义格式)# 可用占位符说明:# %c - 日志器名称# %f - 文件名(短格式)# %A - 完整文件名# %l - 行号# %t - 线程ID# %n - 模块名称# %G - 日志分组# %v - 实际日志内容# %L - 日志级别# %D - 日期时间(可带格式修饰,如%D{%Y-%m-%d %H:%M:%S})pattern: "[%c.%f][%A][%l][%t][%n][%G] %v"# 执行器(线程池)配置executor:# 执行器列表(可配置多个)executors:# 工作执行器配置- name: work_executor # 执行器名称type: simple_thread # 简单线程模式# 模块系统配置module:# 动态模块包配置pkgs:# 日志模块包配置- path: ./liblogger_pkg.so # 模块动态库路径enable_modules: [LoggerModule] # 启用的模块列表# 模块参数配置modules:# 日志模块配置- name: LoggerModule # 必须与代码中模块名一致log_lvl: TRACE # 模块日志级别(开发时可用TRACE)
- 配置了日志打印格式为[%c.%f][%A][%l][%t][%n][%G] %v,日志输出示例如下:
[2024-10-31 20:35:28.378443][Thursday][Info][126632][LoggerModule][logger_module.cc] Test info log
logger rotate file with sync(0.8.x版本不支持,最新main分支开始支持)
一个最基本的 cpp logger 示例,演示内容包括:
- 如何使用 rotate_file 类型 Log 后端并了解其配置项;
- 如何配置相关配置选项以开启定期落盘机制,保证数据完整性;
对应的启动配置文件
aimrt: # AIMRT框架根配置节点# 日志系统配置log:# 核心日志级别(框架自身日志输出级别)# 可选值(区分大小写):# TRACE - 最详细跟踪信息(开发调试用)# DEBUG - 调试信息# INFO - 常规运行信息(推荐生产环境使用)# WARN - 警告信息# ERROR - 错误信息# FATAL - 致命错误# OFF - 关闭所有日志core_lvl: INFO # 当前设置为INFO级别# 日志输出后端配置(支持多后端同时输出)backends:# 控制台输出配置(实时输出)- type: console # 标准控制台输出# 轮转文件输出配置(持久化存储)- type: rotate_file # 支持日志文件轮转options:path: ./log # 日志存储目录(相对路径)filename: examples_cpp_logger_rotate_file.log # 日志文件名max_file_size_m: 4 # 单个文件最大4MBmax_file_num: 10 # 最多保留10个历史文件# 日志同步配置(确保日志完整性)enable_sync: true # 启用定期同步sync_interval_ms: 5000 # 每5秒同步到磁盘sync_executor_name: sync_timer_executor # 使用专用执行器# 执行器(线程池)配置executor:executors:# 工作执行器(处理业务逻辑)- name: work_executortype: simple_thread # 简单线程模式# 日志同步定时器执行器- name: sync_timer_executortype: asio_thread# 模块系统配置module:# 动态模块包配置pkgs:- path: ./liblogger_pkg.so # 模块动态库路径enable_modules: [LoggerModule] # 启用的模块列表# 模块参数配置modules:- name: LoggerModule # 模块名称(需与代码一致)log_lvl: TRACE # 模块日志级别(开发调试用TRACE)