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

日志系统(log4cpp)

日志系统的设计

日志系统的设计,一般而言要抓住最核心的一条,就是日志从产生到到达最终目的地期间的处理流程。一般而言,为了设计一个灵活可扩展,可配置的日志库,主要将日志库分为4个部分去设计,分别是:记录器、过滤器、格式化器、输出器四部分。

记录器(日志来源):负责产生日志记录的原始信息,比如(原始信息,日志优先级,时间,记录的位置)等等信息。

过滤器(日志系统优先级):负责按指定的过滤条件过滤掉我们不需要的日志。

格式化器(日志布局):负责对原始日志信息按照我们想要的格式去格式化。

输出器(日志目的地):负责将将要进行记录的日志(一般经过过滤器及格式化器的处理后)记录到日志目的地(例如:输出到文件中)。

下面以一条日志的生命周期为例说明日志库是怎么工作的。

一条日志的生命周期:

  1. 产生:info(“log information.”);

  2. 经过记录器,记录器去获取日志发生的时间、位置、线程信息等等信息;

  3. 经过过滤器,决定是否记录;

  4. 经过格式化器处理成设定格式后传递给输出器。例如输出“2018-3-22 10:00:00 [info] log information.”这样格式的日志到文件中。日志的输出格式由格式化器实现,输出目的地则由输出器决定;

     5.  这条日志信息生命结束。 编辑 

日志目的地(Appender)

https://log4cpp.sourceforge.net/

通过log4cpp官网查看常用类的信息

我们关注这三个目的地类,点开后查看它们的构造函数

OstreamAppender C++通用输出流(如 cout)

核心功能:将日志输出到 C++ 标准输出流(std::ostream),最常用的场景是输出到控制台(std::cout 或 std::cerr)。

特点

灵活适配任何 std::ostream 类型的流对象(如控制台、自定义缓冲流等)。

无文件大小或滚动逻辑,日志会持续输出到指定流中(控制台会实时显示,若重定向到文件则类似普通文件输出)

// 输出到控制台(std::cout)
log4cpp::Appender* consoleAppender = new log4cpp::OstreamAppender("console", &std::cout);
// 输出到标准错误流(std::cerr)
log4cpp::Appender* errorAppender = new log4cpp::OstreamAppender("error", &std::cerr);

FileAppender 写到本地文件中

核心功能:将日志直接写入本地磁盘文件,是最基础的文件日志输出组件。

特点

日志会持续追加到指定文件中,文件大小会随着日志增多而无限增长。

无自动滚动或切割机制,若不手动处理,文件可能变得过大(如几十 GB),影响存储和读取。

// 输出到 "app.log" 文件,若文件不存在则创建,存在则追加内容
log4cpp::Appender* fileAppender = new log4cpp::FileAppender("file", "app.log");

RollingFileAppender 写到回卷文件中

核心功能:日志写入文件时,会根据文件大小阈值自动切割(回卷)文件,避免单个文件过大。

特点

可设置单个文件的最大容量(如 100MB),当文件达到该大小后,会自动重命名当前文件(如 app.log.1),并创建新的 app.log 继续写入。

可设置保留的历史文件数量(如最多保留 5 个历史文件),超过数量后会自动删除最旧的文件,节省磁盘空间。

// 参数:日志名、目标文件、单个文件最大字节数(100MB)、保留历史文件数(5个)
log4cpp::Appender* rollingAppender = new log4cpp::RollingFileAppender("rolling",       // Appender 名称"app.log",       // 基础文件名1024 * 1024 * 100,  // 单个文件最大大小(100MB)5,               // 最多保留 5 个历史文件false            // 是否追加到现有文件(false 表示新建时覆盖)
);

日志文件会按如下规律生成:

初始文件:app.log

达到阈值后:app.log 重命名为 app.log.1,新建 app.log

再次达到阈值:app.log 重命名为 app.log.2app.log.1 变为 app.log.1(序号递增)

超过 5 个文件后,最旧的 app.log.5 会被删除。

适用场景:日志量较大、需要长期记录的场景(如生产环境服务),避免单个日志文件过大导致的存储和读取问题。

特性OstreamAppenderFileAppenderRollingFileAppender
输出目标标准输出流(如控制台)本地文件(单一文件)本地文件(自动切割为多个文件)
文件大小管理无(依赖输出流本身)无(无限增长)有(按大小阈值切割,保留历史)
典型用途开发调试、控制台输出小规模日志、临时记录生产环境、大规模长期日志
核心优势灵活适配各类输出流简单直接,无需配置切割自动管理文件大小,节省存储空间

日志布局(Layout)

示例代码中使用的是BasicLayout,也就是默认的日志布局,这样一条日志最开始的信息就是日志产生时距离1970.1.1的秒数,不方便观察。

实际使用时可以用PatrrenLayout对象来定制化格式,类似于printf的格式化输出

%d 日期;日期可以进一步的设置格式,用花括号包围,例如%d{%H:%M:%S,%l}或者%d{%d/%m-%Y %H:%M:%S,%l}。如果不设置具体日期格式,则按如下默认格式被使用"1970-01-01 12:30:50,097"。

%c category信息;

%m 消息内容;

%n 换行符;

%p 优先级priority;

%r 自从layout被创建之后的毫秒数;

%R 自从1970年1月1日0时开始到目前为止的秒数;

%u 进程开始到目前为止的时钟周期数;

如果不设置,则默认是%m%n

使用new语句创建日志布局对象,通过指针调用setConversionPattern函数来设置日志布局

日志记录器(Category)

创建Category对象时,可以用getRoot先创建root模块对象,对root模块对象设置优先级和目的地;

再用getInstance创建叶模块对象,叶模块对象会继承root模块对象的优先级和目的地,可以再去修改优先级、目的地

补充:如果没有创建根对象,直接使用getInstance创建叶对象,会先隐式地创建一个Root对象。

子Category可以继承父Category的信息:优先级、目的地  

思考:为什么要创建叶模块对象呢??

如上图所示,叶模块对象可以继承根模块root对象的配置信息,只需要在root模块中进行配置,那么便可以实现全局的管理。另外也可以针对每个子模块分配做不同的配置以实现精细化管理。

日志优先级(Priority)

对于 log4cpp 而言,有两个优先级需要注意,一个是日志记录器的优先级,另一个就是某一条日志的优先级。Category对象就是日志记录器,在使用时须设置好其优先级;某一行日志的优先级,就是Category对象在调用某一个日志记录函数时指定的级别,如 logger.debug("this is a debug message") ,这一条日志的优先级就是DEBUG级别的。简言之:

日志系统有一个优先级A,日志信息有一个优先级B

只有B高于或等于A的时候,这条日志才会被输出(或保存),当B低于A的时候,这条日志会被过滤;

class LOG4CPP_EXPORT Priority {
public:typedef enum {EMERG = 0,FATAL = 0,ALERT = 100,CRIT = 200,ERROR = 300,WARN = 400,NOTICE = 500,INFO = 600,DEBUG = 700,NOTSET = 800 //这个不代表可以使用的优先级} PriorityLevel;//......
};  //数值越小,优先级越高;数值越大,优先级越低

http://www.dtcms.com/a/331819.html

相关文章:

  • 主进程如何将客户端连接分配到房间进程
  • Android UI(一)登录注册 - Compose
  • 基于Python和Dify的成本对账系统开发
  • OpenCV Canny 边缘检测
  • 软考中级【网络工程师】第6版教材 第3章 局域网 (上)
  • Linux中tty与8250-uart的虐恋(包括双中断发送接收机制)
  • Linux中Samba服务配置与使用指南
  • YouBallin正式上线:用Web3重塑创作者经济
  • 会议通信系统核心流程详解(底稿1)
  • JVM的逃逸分析深入学习
  • 17.2 修改购物车商品
  • RLVR(可验证奖励的强化学习):大模型后训练的客观评估策略
  • 负载因子(Load Factor) :哈希表(Hash Table)中的一个关键性能指标
  • AI大模型+Meta分析:助力发表高水平SCI论文
  • 多任务并发:进程管理的核心奥秘
  • 【记录】Apache SeaTunnel 系统监控信息
  • 使用ETL工具同步Oracle的表到Doris
  • 使用load data或insert导入10w条数据
  • 51单片机-GPIO介绍
  • 网络组播技术详解
  • 深入理解 `std::any`:C++ 中的万能容器
  • 俄罗斯加强互联网管控,限制 WhatsApp 和 Telegram 通话
  • P5663 [CSP-J2019] 加工零件
  • 腾讯K8S环境【TKE】中,如何驱逐指定pod重新部署?
  • Kafka下载和安装
  • Python:如何处理WRF投影(LCC, 兰伯特投影)?
  • 深度学习 --- ResNet神经网络
  • 【递归完全搜索】CCC 2008 - 24点游戏Twenty-four
  • 【完整源码+数据集+部署教程】膝关节屈伸运动检测系统源码和数据集:改进yolo11-RFAConv
  • pip和dnf只下载不安装离线包