spdlog源码阅读(一):简介

spdlog是一个跨平台、快速和轻量的C++日志库,其完全header-only实现和基于C++11实现的特性使其可以很好的集成到任何项目中。项目地址:https://github.com/gabime/spdlog

spdlog短小精悍,代码行数在2w左右,且代码风格优秀,符合现代C++编程规范,有许多值得学习的实践,遂开坑对该源码开始阅读和理解。

spdlog整体架构

组成部分

spdlog结构

Logger 类

logger是spdlog日志库的核心类,提供日志输出的接口,具有以下功能:

  • 支持trace,debug,info,warn,error和critical等级的日志输出接口,具有日志等级过滤的功能。
  • 日志接口使用友好,提供了格式化字符串模板接口,使用fmt库作为底层驱动。
  • 通过设置Sink对象来实现日志消息的单一输出或多个输出,每个输出可以单独设置日志过滤等级和日志格式化模板。
  • 提供线程安全性,允许多个线程修改logger对象的日志过滤等级和日志刷新等级。
  • 提供宽字符的支持。

Sink 类

Sink包含了一系列输出类,来负责日志不同的输出形式。Sink是日志输出的抽象基类,只提供接口不提供实现。file_sink, console_sink等类通过继承拓展Sink类,负责实现日志的输出。

以下是 spdlog 主要实现的 sink 类型:

Sink 类型 描述 头文件
stdout_sink_mt / stdout_sink_st 输出到标准输出的 sink spdlog/sinks/stdout_sinks.h
stderr_sink_mt / stderr_sink_st 输出到标准错误的 sink spdlog/sinks/stdout_sinks.h
basic_file_sink_mt / basic_file_sink_st 基本的文件输出 sink spdlog/sinks/basic_file_sink.h
rotating_file_sink_mt / rotating_file_sink_st 循环文件 sink spdlog/sinks/rotating_file_sink.h
daily_file_sink_mt / daily_file_sink_st 每日文件 sink spdlog/sinks/daily_file_sink.h
null_sink_mt / null_sink_st 空 sink,不输出任何内容 spdlog/sinks/null_sink.h
syslog_sink 系统日志 sink(仅 UNIX 系统) spdlog/sinks/syslog_sink.h
android_sink Android 日志 sink spdlog/sinks/android_sink.h
wincolor_sink_mt / wincolor_sink_st Windows 控制台彩色输出 sink spdlog/sinks/wincolor_sink.h
ansicolor_sink_mt / ansicolor_sink_st ANSI 终端彩色输出 sink spdlog/sinks/ansicolor_sink.h
ostream_sink_mt / ostream_sink_st 输出到 C++ ostream 的 sink spdlog/sinks/ostream_sink.h
dist_sink_mt / dist_sink_st 分发 sink spdlog/sinks/dist_sink.h
msvc_sink_mt / msvc_sink_st Visual Studio 输出窗口 sink spdlog/sinks/msvc_sink.h
tcp_sink_mt / tcp_sink_st TCP 网络 sink spdlog/sinks/tcp_sink.h
callback_sink_mt / callback_sink_st 回调函数 sink spdlog/sinks/callback_sink.h
dup_filter_sink_mt / dup_filter_sink_st 重复消息过滤 sink spdlog/sinks/dup_filter_sink.h
hourly_file_sink_mt / hourly_file_sink_st 每小时文件 sink spdlog/sinks/hourly_file_sink.h
kafka_sink_mt / kafka_sink_st Kafka 消息队列 sink spdlog/sinks/kafka_sink.h
mongo_sink_mt / mongo_sink_st MongoDB sink spdlog/sinks/mongo_sink.h
qt_sinks_mt / qt_sinks_st Qt GUI 应用程序 sink spdlog/sinks/qt_sinks.h
ringbuffer_sink_mt / ringbuffer_sink_st 环形缓冲区 sink spdlog/sinks/ringbuffer_sink.h
systemd_sink_mt / systemd_sink_st Systemd Journal sink spdlog/sinks/systemd_sink.h
win_eventlog_sink_mt / win_eventlog_sink_st Windows 事件日志 sink spdlog/sinks/win_eventlog_sink.h

注意:

  1. 后缀 “_mt” 表示多线程(thread-safe)版本,”_st” 表示单线程版本。
  2. spdlog 还支持自定义 sink,允许用户根据需求实现自己的 sink。
    Sink类通过继承将接口和实现进行解耦,并实现了多种日志输出方式,具有较好的灵活性和拓展性。

Formatter 类

日志的格式化器,可以格式化出不同类型的时间,支持文本的空白填充和对齐。此外,也支持自定义flag_formatter以实现自定义的格式化。

Registry 类

全局单例,管理所有Logger实例,提供创建和检索Logger的接口。

异步支持

spdlog实现了异步日志,通过异步日志类async_logger实现,允许日志记录操作在后台线程中进行,减少对主程序执行的影响。异步日志不直接输出,而是存在一个无锁环形队列circular_q中,通过实现一个多生产者-多消费者模式来实现日志的高效写入。

然而使用异步日志会引入一些复杂性,当队列满时,spdlog默认使用覆盖的策略,会导致一部分的异步日志的丢失。

相关阅读

在此之前已有诸多优秀的spdlog库的源码解读,例如

spdlog库笔记汇总

作者

echo

发布于

2024-09-23

更新于

2024-11-24

许可协议

评论