spdlog源码阅读(一):简介
spdlog是一个跨平台、快速和轻量的C++日志库,其完全header-only实现和基于C++11实现的特性使其可以很好的集成到任何项目中。项目地址:https://github.com/gabime/spdlog
spdlog短小精悍,代码行数在2w左右,且代码风格优秀,符合现代C++编程规范,有许多值得学习的实践,遂开坑对该源码开始阅读和理解。
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 |
注意:
- 后缀 “_mt” 表示多线程(thread-safe)版本,”_st” 表示单线程版本。
- spdlog 还支持自定义 sink,允许用户根据需求实现自己的 sink。
Sink类通过继承将接口和实现进行解耦,并实现了多种日志输出方式,具有较好的灵活性和拓展性。
Formatter 类
日志的格式化器,可以格式化出不同类型的时间,支持文本的空白填充和对齐。此外,也支持自定义flag_formatter以实现自定义的格式化。
Registry 类
全局单例,管理所有Logger实例,提供创建和检索Logger的接口。
异步支持
spdlog实现了异步日志,通过异步日志类async_logger实现,允许日志记录操作在后台线程中进行,减少对主程序执行的影响。异步日志不直接输出,而是存在一个无锁环形队列circular_q中,通过实现一个多生产者-多消费者模式来实现日志的高效写入。
然而使用异步日志会引入一些复杂性,当队列满时,spdlog默认使用覆盖的策略,会导致一部分的异步日志的丢失。
相关阅读
在此之前已有诸多优秀的spdlog库的源码解读,例如
spdlog源码阅读(一):简介