基于C++的仿Log4j的日志库
- 本项目使用C++语言编写,实现了一个仿Log4j的日志库。
- 日志格式化输出到指定输出地(控制台、文件)
- 日志配置读取
- chx目录:项目的代码部分
- bin目录:包含生成的可执行文件,以及存储配置文件的conf目录
- tests目录:测试文件,测试了日志库的主要功能,以及写日志的性能
cmake .
make
bin/test or bin/test_config
- 每个日志器都包含一个存储日志输出器的list,日志器会将事件交给自己的日志输出器来进行输出,输出地有两类:控制台、文件。如果日志器的日志输出器列表为空,则会使用根日志器root进行输出。
- 每个日志输出器都有一个日志格式器,因此日志输出器再将事件委托给格式器进行格式化。
- 日志格式器会根据指定的格式字符串,生成一个存储格式项的vector。每个格式项会对传入的事件传出不同的属性,例如线程号格式项会输出事件的线程号。
日志格式器支持的格式字符串:
%m -- 消息体
%p -- level
%r -- 启动后的时间
%c -- 日志名称
%t -- 线程id
%n -- 回车换行
%d -- 时间戳
%f -- 文件名
%l -- 行号
%T -- TAB
- 当事件来临的时候,会将它交给一个日志器,然后日志器将事件交给它的日志输出器进行输出。
- 日志配置使用yaml文件,并使用yaml-cpp库读取yaml文件中的信息。
- 对于需要用到的配置项,创建一个ConfigVar来表示它,并在创建时将它放入配置的map中。
- 当程序加载配置文件时,会对配置文件中所有的键值对进行遍历,如果配置的map中有这个配置项,则将这个配置项修改成配置文件中的配置项。
- 修改配置项这部分,需要将从yaml文件中读取到的配置项的字符串,转换成配置项对应的类型(常规类型如int、float、string等,容器类型如vector、list、set、map等)。
因此,这部分实现了一个string和常见类型互相转换的模板类。其中,常规类型直接使用boost库中的lexical_cast函数进行转换,容器类型就需要根据不同容器的特点进行相应的转换。 - ConfigVar可以设置监听器,针对每次配置项的改变,改变程序中的某些值。例如,logs配置项存储的是日志器列表,在程序加载配置文件时,logs对应的ConfigVar监听到值的改变,对程序中的日志器做出相应的改变(新建、修改、删除)。
- 自旋锁保障日志格式化输出部分的线程安全,例如写文件、输出到控制台、设置日志格式、设置日志级别等。
选择自旋锁的原因:日志格式化输出部分进行的操作快,使用自旋锁的效率高。 - 读写锁保障日志配置读取部分的线程安全,例如写入配置项、从配置项读值等。
选择读写锁的原因:配置部分读多写少,因此使用读者优先的读写锁。