一、spdlog 介绍
- 日志作用:追踪程序运行状态、出现问题提供现场运行信息、分析性能瓶颈和潜在系统故障。
- spdlog 是一款高效的 C++ 日志库,它以其极高的性能和零成本的抽象而著称。
- spdlog 支持异步和同步日志记录,提供多种日志级别,并允许用户将日志输出到控制台、文件或自定义的接收器。
git clone https://github.com/gabime/spdlog.git
cd spdlog
mkdir build
cd build
cmake ..
make -j
sudo make install
sudo apt-get install libspdlog-dev
二、spdlog 为何高效
- 零成本抽象:spdlog 通过模板和内联函数来实现零成本抽象,确保只有在真正需要时才进行日志记录。
- 异步日志记录:spdlog 支持异步日志记录,这意味着它可以将日志消息发送到线程池进行处理,从而减少对主线程性能的影响。
- 如果要严格按照日志的到达顺序输出到日志文件中,消费者线程的个数只能为 1。
- 高效地格式化:spdlog 使用 fmt 库进行高效的字符串格式化,减少了格式化日志消息所需的时间。
三、spdlog 特征
- 极高的日志记录速度:spdlog 每秒能够记录数百万条日志消息,这对于需要处理大量日志数据的应用来说是非常重要的。
- 低内存占用:spdlog 的设计确保了即使在高负载下,它也能保持低内存占用。
- 灵活的配置:用户可以根据需要配置 spdlog,选择异步或同步日志记录,以及选择不同的日志级别和输出目标。
四、spdlog 输出控制
- 多种日志级别:spdlog 支持多种日志级别,包括 trace、debug、info、warn、error 和 critical,用户可以根据需要选择合适的日志级别。
- 多种输出目标:用户可以将日志输出到控制台、文件或通过网络发送到远程服务器。
- 格式化输出:spdlog 支持格式化输出,允许用户以结构化的方式输出日志消息。
五、spdlog 处理流程
- registry:用于管理多个日志,是单例模式,提供一个全局访问点。
- logger:同步日志。
- async logger:异步日志。
- sink:决定了日志消息的输出位置。
- formatter:负责将日志消息转换为特定格式。
- thread pool:异步日志使用的线程池。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/4853ea8793c4c8b968bf6255ecf8c694.png)
六、接口使用
- 如何创建 logger。
- spdlog 工厂方法创建 → 屏蔽复杂的创建对象流程,但是只能携带一个 sink。
- 手动创建 → 方便携带多个 sink。
- 如何创建 sink。
- 如何自定义格式化。
- set_pattern。
- 扩展标识(flags)。
- 创建一个 formatter。
- logger 设置 formatter 或 sink 设置 formatter。
- 源文件定位。
SPDLOG_INFO(msg)
。
SPDLOG_LOGGER_INFO(logger, msg)
;
- 如何创建异步日志。
- 使用
spdlog::async_factory
、 spdlog::create_async<Sink>
、 spdlog::create_async_nb<Sink>
。
- 屏蔽复杂的创建对象流程,但是只能携带一个 sink。
- 构建
spdlog::async_logger
。
spdlog::init_thread_pool(queue_size, thread_count)
创建线程池。
- 默认线程池只有一个线程,队列大小为 8192。
- 多线程线程池,日志输出无法保证有序。
- 处理队列满的策略:
async_overflow_policy::block
→ 队列满时阻塞。
async_overflow_policy::overrun_oldest
→ 队列满时丢弃最老的。
async_overflow_policy::discard_new
→ 队列满时丢弃最新的。
- 刷新策略(刷到内核态缓冲区中(page cache))。
- 手动 flush,
logger->flush
,如果是异步的,将发出一个 flush 的消息。
- 条件 flush,
logger->flush_on(spdlog::level::err)
,设置最小日志等级触发自动 flush。
- 间隔 flush,
spdlog::flush_every(std::chrono::seconds(5))
,需要线程安全的 logger。
七、代码实现
#include <iostream>
#include <spdlog/async.h>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
int main() {
spdlog::info("hello spdlog");
auto logger_sync = spdlog::stdout_color_mt("sync console");
logger_sync->info("hello spdlog too !");
spdlog::get("sync console")->info("hello spdlog too !");
auto logger_async = spdlog::stdout_color_mt<spdlog::async_factory>("async console");
logger_async->info("hello spdlog too !");
return 0;
}