spdlog是一个只有头文件的轻量级C++11日志库,速度非常快,扩展性很强,更重要的是社区活跃,文档齐全。原来项目中使用的是log4cplus,感觉稍微有点笨重。
github地址:https://github.com/gabime/spdlog
它支持的平台包括Windows、Linux、Mac、Android。特点如下:
1.一个字,快;三个字,非常快
2.仅包括头文件
3.日志格式丰富,格式化处理使用开源的fmt库(https://github.com/fmtlib/fmt )
4.可选的异步模式
这里的同步/异步指日志信息是否直接输出/写入文件,直接写就是同步,稍后写就是异步。spdlog默认的状态就是同步了,同步也没什么好说的。这里介绍下异步的逻辑实现:
异步状态下,日志会先存入队列,然后由线程从队列中取数据,当队列满的时候会有淘汰策略。如果工作线程中抛出了异常,向队列写入下一条日志时异常会再次抛出,可以在写入队列时捕捉工作者线程的异常,淘汰策略一般两种:
①阻塞新来的的日志,直到队列有剩余空间(默认处理方式)
②把新的日志丢掉(需要设定:spdlog::set_async_mode(队列大小,spdlog::async_overflow_policy::discard_log_msg))
5.自定义格式
一般情况下,希望输出的日志信息中带有各类基本信息。但具体情况要具体分析,spdlog中提供了个性化的输出方式,可以自己指定模式进行输出。基本上就是各类“%参数”的组合。具体内容可以参考:https://github.com/gabime/spdlog/wiki/3.-Custom-formatting
6.单线程/多线程日志
spdlog中提供了单线程和多线程模式,由使用者在对象创建中自己指定。
st:单线程版本,不用加锁,效率高,但不保证线程安全
mt:多线程版本,保证多线程并发情况线程安全,但效率稍低
7.多种日志输出方式:控制台输出(stdout)——默认输出方式,日志文件,数据库或其他外部实体
①当天日志(spdlog::daliy_logger):记录当天的所有日志,但在指定时间点会把日志清空
②循环日志(spdlog::rotating_logger):日志创建成功后,如果写入的日志大小超过限制就会写入到新日志文件中去。不过同时存在的日志总数是有上限的,达到上限后按指定策略淘汰。需要特别注意的是日志更迭的规则:当日志A存满时,将日志A名称更改为B,再新建一个日志命名为A,依次类推,直到达到上限数字
③单个日志(spdlog::basic_logger):只有一个日志文件,所有日志都会在该文件中累加
④输出终端(spdlog::stdout_color):日志打印至终端,不同等级日志颜色不同
8.日志过滤——日志等级能在编译时修改也能在运行时修改
9.支持从argv参数和环境变量加载日志等级
10.回溯支持——将调试消息存储在环形缓冲区中,稍后根据需要显示。
一.spdlog的结构
spdlog可以分成三级结构,从上而下是logger registry、logger、sink,其各自功能如下:
logger registry(日志管理器):负责管理所有的logger,用户建立的所有logger都会在registry处进行登记然后统一管理。使用 <name, logger> 将日志对象和其名称对应起来,后面使用的时候可以直接通过名称获取对应的日志对象。
logger(日志记录器):是用户直接操作的对象,通过操作logger进行日志逻辑的生成
sink(日志记录槽):受logger控制,执行具体的动作(动作包括写入日志文件/输出到控制台)
简单来说,就是一个logger registry管多个logger,一个logger管多个sink。
说到底,日志库的目的就是把日志信息写到指定地方。从上面对于结构的功能描述,sink才是真正操作日志进行写操作的结构,那sink可以把日志信息写到哪里呢?主要有三个去向:
1.控制台输出(stdout)——默认输出方式
2.日志文件
3.数据库或其他外部实体
通过刷新方式可以控制日志何时写入文件中,spdlog提供了两种刷新方式:
1.程序正常退出时写入(默认)
2.程序运行中,在指定位置进行写入(实时刷新日志,便于锁定错误所在位置)
要想使用实时刷新日志,spdlog提供了两种方法:
1.logger对象->flush_on(设定等级),flush_on是一次性刷新,执行到此时按照设定等级进行日志刷新。
2.logger对象->flush_every(周期时间),flush_every是设置刷新周期,定时进行刷新。刷新的级别采取默认了。
二.一个例子
#include <iostream>
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h" // support for basic file logging
#include "spdlog/sinks/rotating_file_sink.h" // support for rotating file logging
int main(int, char* [])
{
try
{
// Create basic file logger (not rotated)
auto my_logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt");
// create a file rotating logger with 5mb size max and 3 rotated files
auto file_logger = spdlog::rotating_logger_mt("file_logger", "myfilename", 1024 * 1024 * 5, 3);
}
catch (const spdlog::spdlog_ex& ex)
{
std::cout << "Log initialization failed: " << ex.what() << std::endl;
}
}
这个例子是最基础的用法
更多例子参考官方example
如果想循序渐进学习spdlog,从QuickStart开始
三.压测
下面是同步和异步模式下的压测数据,环境是Ubuntu 64 bit, Intel i7-4770 CPU @ 3.40GHz
Synchronous mode
[info] **************************************************************
[info] Single thread, 1,000,000 iterations
[info] **************************************************************
[info] basic_st Elapsed: 0.17 secs 5,777,626/sec
[info] rotating_st Elapsed: 0.18 secs 5,475,894/sec
[info] daily_st Elapsed: 0.20 secs 5,062,659/sec
[info] empty_logger Elapsed: 0.07 secs 14,127,300/sec
[info] **************************************************************
[info] C-string (400 bytes). Single thread, 1,000,000 iterations
[info] **************************************************************
[info] basic_st Elapsed: 0.41 secs 2,412,483/sec
[info] rotating_st Elapsed: 0.72 secs 1,389,196/sec
[info] daily_st Elapsed: 0.42 secs 2,393,298/sec
[info] null_st Elapsed: 0.04 secs 27,446,957/sec
[info] **************************************************************
[info] 10 threads, competing over the same logger object, 1,000,000 iterations
[info] **************************************************************
[info] basic_mt Elapsed: 0.60 secs 1,659,613/sec
[info] rotating_mt Elapsed: 0.62 secs 1,612,493/sec
[info] daily_mt Elapsed: 0.61 secs 1,638,305/sec
[info] null_mt Elapsed: 0.16 secs 6,272,758/sec
Asynchronous mode
[info] -------------------------------------------------
[info] Messages : 1,000,000
[info] Threads : 10
[info] Queue : 8,192 slots
[info] Queue memory : 8,192 x 272 = 2,176 KB
[info] -------------------------------------------------
[info]
[info] *********************************
[info] Queue Overflow Policy: block
[info] *********************************
[info] Elapsed: 1.70784 secs 585,535/sec
[info] Elapsed: 1.69805 secs 588,910/sec
[info] Elapsed: 1.7026 secs 587,337/sec
[info]
[info] *********************************
[info] Queue Overflow Policy: overrun
[info] *********************************
[info] Elapsed: 0.372816 secs 2,682,285/sec
[info] Elapsed: 0.379758 secs 2,633,255/sec
[info] Elapsed: 0.373532 secs 2,677,147/sec
参考链接:http://t.zoukankan.com/shuqin-p-12214439.html
原文链接:https://blog.csdn.net/caoshangpa/article/details/79476025