spdlog日志库的核心组件分析-sink
Sink负责将日志输出到不同的目标。Spdlog提供了多种Sink,包括stdout_sink(输出到控制台)、basic_file_sink(输出到文件)、syslog_sink(输出到syslog)等。
Sink组件的实现采用继承抽象类的方法,提供了灵活的扩展能力。
最基础的sink基类定义如下:
1 | class sink |
sink 是最基础的抽象类,提供了 level_ 日志等级设置。并且提供了下面四个抽象方法:
- log:用于接收
spdlog::details::log_msg类型的日志消息,实现将消息输出到指定目标的功能。 - flush:用于将缓冲区中的日志消息输出到目标。
- set_pattern:用于设置日志格式。该方法接收一个字符串参数,包含格式说明符和文本内容。
- set_formatter:用于设置日志的格式化器。该方法接收一个
std::unique_ptr<spdlog::formatter>类型的参数,表示要使用的格式化器的指针。
base_sink
1 | class base_sink : public sink |
base_sink 继承自 sink,在次基础上提供了锁和格式化器,其中 mutex_ 用于保证多线程环境下的数据安全,formatter_ 表示该 sink 所使用的 formatter。sink_it_() 方法用于实现将日志输出到目标的具体逻辑,flush_() 用于实现将缓冲区中的日志消息输出到目标,set_pattern_() 用于设置日志格式,set_formatter_() 用于设置日志的格式化器。由于 base_sink 是一个抽象类,所以这些方法都是纯虚函数,需要在子类中实现。
自定义锁
mutex_ 的类型通过模板传递,也就是说我们可以自定义锁。那么自定义锁需要满足哪些条件呢?在 log 写日志函数里可以找到调用:
1 | template<typename Mutex> |
std::lock_guard 使用了自定义的锁,查看 lock_guard的实现,是个模板函数,会调用到 Mutex的 lock 和 unlock 方法。
1 | template<typename _Mutex> |
也就是说我们自定义的 Mutex 只要实现 lock 与 unlock 方法就可以了。spdlog 也给我们提供了默认的无锁Mutex,来提供单线程不加锁的日志实现。
1 | struct null_mutex |
实现自定义日志输出
继承 base_sink 后我们可以定义自己的输出实现,只需要实现下面两个接口:
1 | virtual void sink_it_(const details::log_msg &msg) = 0; |
sink_it_:用于写日志
flush_:用于刷新缓冲区到输出
目前 spdlog 已经提供了多种 Sink 的实现,包括:stdout_sink(输出到控制台)
basic_file_sink(输出到文件)
daily_file_sink(每天输出到不同的日志文件)
rotating_file_sink(按文件大小或时间自动切分日志文件)
null_sink(无输出)
syslog_sink(输出到系统日志)
udp_sink(输出到udp)
tcp_sink(输出到tcp)
kafka_sink(输出到kafka)
…
如果需要自定义输出实现,只需要继承base_sink并实现sink_it_和flush_两个接口即可。同时,也可以自定义锁,只需要实现lock和unlock两个方法,并在继承base_sink时将锁作为模板参数传入即可。
参考链接:https://zhuanlan.zhihu.com/p/617954521
💡 准备购买云服务器 / 域名来搭建或部署站点?
通过下面的链接下单,通常能领到新用户专属优惠,也能小额支持本站持续更新:
阿里云(返现) | 腾讯云 2核2G 99元/年 | 腾讯云 云产品特惠













