当前位置: 首页 > backend >正文

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操作阻塞业务线程
  • 要求日志执行器是线程安全的
使用
产生日志
写入
console后端
log_executor
work_executor
LoggerModule

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)
http://www.xdnf.cn/news/2985.html

相关文章:

  • 信创产业贡献︱悬镜安全深度参编《2024网信自主创新调研报告》
  • 监控易一体化运维:解锁业务系统管理,助力企业运维升级
  • SOLIDWORKS广东东莞地区代理商哪个服务好?都有哪些代理商?
  • docker 部署前、后端分离项目详细步骤(从打包到部署)
  • 嵌入式学习笔记 - 关于STM32 SPI控制器读取以及写入时,标志位TXE, RXNE的变化
  • 文献阅读(二)植被恢复力变化对不同干旱类型的空间异质性|《Earth‘s Future》
  • 第八章 磁盘管理未完待续
  • 关闭正点原子atk-qtapp-start.service
  • 使用C# ASP.NET创建一个可以由服务端推送信息至客户端的WEB应用(一)
  • 解决vue3 路由query传参刷新后数据丢失的问题
  • [MySQL数据库] InnoDB存储引擎(四): InnoDB磁盘文件
  • 基于Spring Boot+Vue 网上书城管理系统设计与实现(源码+文档+部署讲解)
  • C# 中重启程序通常意味着关闭当前运行的应用程序实例
  • 【语法】C++的继承
  • 云钥科技红外短波工业相机
  • 【开源项目】基于sherpa-onnx的实时语音识别系统 - LiveASR
  • 实习技能记录【4】-----消息分发中的观察者模型
  • 聚焦智能体未来,领驭科技在微软创想未来峰会大放异彩
  • 每日一道leetcode(不会做学习版,多学一题)
  • SpringBoot+Mybatis通过自定义注解实现字段加密存储
  • Astro大屏中关于数据流转的数据接入与数据中心之间的逻辑关系梳理
  • 笔试专题(十二)
  • 字符串(格式化字符串字面值)进行输出
  • Rust 的 Web 世界:actix_web 轻松接收 JSON 请求体
  • 打造美观 API 文档:Spring Boot + Swagger 实战指南
  • C++23 std::byteswap:反转字节 (P1272R4)
  • C#里创建一个TCP客户端连接类
  • 【LeetCode】彩灯装饰记录 III
  • 【运维】使用 DataX 实现 MySQL 到 PostgreSQL 的数据同步
  • 苍穹外卖心得体会