C++日志记录库spdlog介绍
spdlog简介
spdlog是基于C++11实现的一款纯头文件的日志管理库(git地址:https://github.com/gabime/spdlog),具有以下特点:
- 配置特别简单,仅包含头文件即可;
- 写日志方式简单明了;
- 可实现自动按日期创建日志文件/定时创建日志文件;
- 可自定义日志格式;
- 可以输出当前输出日志所在的文件及函数;
- 可自定义文档大小;
- 可将不同级别的信息输出到不同日志文件;
- 多平台等。
spdlog中各对象都分为多线程与单线程版本:
- *_st:单线程版本,不用加锁,效率更高。
- *_mt:多线程版本,用于多线程程序是线程安全的。
日志记录槽sink
spdlog定义了几种sinks用于不同场景(也可自定义)下的日志输出,sink中主要包含:
set_pattern(const std::string&)
:设置日志输出的内容格式。set_level(level_enum)
: 设置日志输出的最低等级。log(log_msg)
:由logger自动调用,外部不会主动调用。
日志记录器logger
一个logger对象中存储有多个sink,当调用logger的日志输出函数时,logger会调用自身存储的所有sink对象的log(log_msg)
函数进行输出。logger中主要包括:
set_pattern(const std::string&)
:设置logger包含的所有sink的日志输出内容格式。set_level(level_enum)
:设置logger日志输出最低等级,如果logger包含的sink没有设置日志等级的话,则会为其设置日志等级。log(level_enum level,log_msg content)
:按照level等级进行输出content,logger其中日志输出最低等级小于或等于level的sink会进行执行输出操作。trace(content,arg1,arg2…)
:按照trace等级进行输出,输出内容由content与后面的参数格式化而成。同类的函数还包括:debug/info/warn…。
输出格式pattern
通过set_pattern可设定日志格式,如set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l](%@): %v")
;
输出标记flag:
flag | meaning | example |
---|---|---|
%v | 日志内容 | “my log test content” |
%t | 线程ID | “123” |
%P | 进程ID | “234” |
%n | 记录器Logger名 | “basicLogger” |
%l | 日志级别 | “debug”, “info”, etc |
%L | 日志级别简称 | “D”, “I”, etc |
%a | 星期几(简称) | “Thu” |
%A | 星期几 | “Thursday” |
%b | 月份简称 | “Aug” |
%B | 月份 | “August” |
%c | 日期时间 | “Thu Aug 23 15:35:46 2014” |
%C | 年(两位) | “14” |
%Y | 年 | “2014” |
%D %x | 日期简写 | “08/23/14” |
%m | 月份(数字) | “11” |
%d | 日(数组) | “29” |
%H | 小时(24制) | “23” |
%I | 小时(12制) | “11” |
%M | 分钟 | “59” |
%S | 秒 | “58” |
%e | 毫秒 | “678” |
%f | 微秒 | “056789” |
%F | 纳秒 | “256789123” |
%p | AM/PM | “AM” |
%r | 时间(12制) | “02:55:02 pm” |
%R | 时分(24制) | “23:55” |
%T %X | 时间(24制) | “23:55:59” |
%z | 时区(偏移) | “+02:00” |
%E | epoch(秒) | “1528834770” |
%% | 百分号 | “%” |
%+ | 默认格式 | “[2014-10-31 23:46:59.678] [mylogger] [info] Some message” |
%^ | start color range (can be used only once) | “[mylogger] [info(green)] Some message” |
%$ | end color range (for example %^[+++]%$ %v) (can be used only once) | [+++] Some message |
%@ | 文件名与行数 | my_file.cpp:123 |
%s | 文件名 | my_file.cpp |
%g | 文件名(含路径) | /some/dir/my_file.cpp |
%# | 行数 | 123 |
%! | 函数名 | my_func |
%o | 相对上一条记录的时间间隔(毫秒) | 456 |
%i | 相对上一条记录的时间间隔(微秒) | 456 |
%u | 相对上一条记录的时间间隔(纳秒) | 11456 |
%O | 相对上一条记录的时间间隔(秒) | 4 |
日志输出中要携带文件名、行数或函数名时,必须使用SPDLOG_LOGGER_*宏,且要激活对应的级别(哪些级别以上的日志会被记录):
1 | // 记录INFO及以上级别日志 |
对齐方式
每个flag都可携带对齐方式(最多支持64字符),
align | meaning | example | result |
---|---|---|---|
% |
右对齐 | %8l | info |
%- |
左对齐 | %-8l | info |
%= |
居中 | %=8l | info |
截断
通过!可设定对应输出的最大长度:
align | meaning | example | result |
---|---|---|---|
% |
右对齐且截断 | %3!l | “inf” |
%- |
左对齐且截断 | %-2!l | “in” |
%= |
居中且截断 | %=1!l | “i” |
字符串格式化fmt
spdlog中字符串格式化使用fmt库。
格式化方式:{ [arg_id] [: (format_spec | chrono_format_spec)] }
- arg_id:参数标识;
- 忽略(为空时),依次对应每一个参数;
- 索引(数字,从0开始),引用第几个索引;
- 名称,命名参数;
- format_spec:参数格式化方式(类型、对齐、填充等);
Format Specification
格式化符说明:
1 | format_spec ::= [[fill]align][sign]["#"]["0"][width]["." precision]["L"][type] |
#不同的转换下有不同的意义:
- 整数时,表示前面添加进制前缀,如0x, 0b等;
- 浮点数时:总是有小数点(即使没有小数部分);
L
只对数字有效,根据本地设置来输出:如,
1 | auto s = fmt::format(std::locale("en_US.UTF-8"), "{:L}", 1234567890); |
格式化类型
格式化类型:
type | meaning |
---|---|
s | 字符串 |
c | 字符 |
b/B | 二进制 |
d | 数字(十进制) |
o | 八进制 |
x/X | 十六进制 |
a/A | 十六进制浮点数(p表示指数) |
e/E | 科学计数 |
f/F | 浮点数(包括NAN,INF),固定小数位数输出 |
g/G | 浮点数输出 |
p | 指针 |
示例:
1 | fmt::format("{:*^30}", "centered"); // use '*' as a fill char |
spdlog使用
spdlog默认日志输出级别是INFO。
默认情况下,日志是同步模式的,可通过以下方法开启异步模式:
1 | size_t q_size = 4096; //queue size must be power of 2 |
在异步模式下,日志先存入队列(队列占用的内存 = 设置的队列大小 * slot的大小, 64位系统下slot大小为104字节。),再由工作者线程从队列中取出并输出。当队列满时,会根据设定策略处理:
- 阻塞新来的日志,直到队列中有剩余空间(默认处理方式);
- 丢弃新来的日志,需要如下设定策略:
1 | spdlog::set_async_mode(q_size, spdlog::async_overflow_policy::discard_log_msg); |
异常处理
当输出日志时发生异常时,spdlog会向std::err 打印一条语句,为了避免输出的异常语句刷屏,打印频率被限制在每分钟一条。可通过set_error_handler来设定异常处理函数:
1 | //can be set globaly or per logger(logger->set_error_handler(..)) |
logger
默认情况下,spdlog的默认logger为输出到stdout:
1 |
|
在使用完logger后,要关闭掉以释放(否则无再建立同名logger)
1 | spdlog::drop_all(); // 关闭所有logger |
基础用法
spdlog中使用{}(里面可指定格式)作为格式化符
以下方式把日志输出到默认logger上:
1 | //#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG |
stdout日志
以彩色方式输出到标准输出设备上:
1 |
|
文件日志
基本文件
最简单的日志文件:
1 |
|
循环文件
日志文件超过指定大小后,自动生成一个新的;并且只保留最多指定数量的日志文件:
1 |
|
每日文件
每天指定时间生成一个新的日志文件:
1 |
|
示例
设定默认日志记录文件并在不同地方获取使用:
1 |
|
参考链接:https://zhuanlan.zhihu.com/p/649444681