代码取自 V1.5.0, 代码堪称美学。git
spdlog 是一个只有头文件的C++日志库,速度很是快,扩展性很强,更重要的是 社区活跃,文档齐全。github
这里选择了三个点来作分析:后端
spdlog 的代码结构以下:多线程
spdlog ├─example 用法代码 ├─include 实现目录 │ └─spdlog │ ├─details 功能函数目录 │ ├─fmt {fmt} 库目录 │ ├─sinks 落地文件格式实现 │ └─*.h 异步模式,日志库接口等实现 ├─src .cpp 文件,组成编译模块生成静态库使用 ├─test 测试代码
基本逻辑结构以下:
异步
有几个比较重要的文件:async
spdlog 整体而言提供了日志接口函数
spdlog::debug()
, 默认的日志对象,使用默认的日志信息格式,输出至 stdout。logger->debug()
, 指定日志对象进行日志记录,输出至该日志对象对应的文件中。SPDLOG_LOGGER_DEBUG(logger), SPDLOG_DEBUG()
, 使用宏对以上两种接口进行包装,产生的日志格式包含 文件、函数、行。提供的一些落地的文件类型:测试
这里简单提一下 sinks 的实现,全部落地文件的类型都是从 base_sink
(忽略sink) 继承而来,提供了两个纯虚函数 sink_it_()
和 flush_()
,这样一来,须要扩展的类型文件只须要实现两个函数,很大的简化了扩展的流程。而单/多线程经过模板来肯定是否须要使用互斥量来保持同步,也算是比较有意思的一个实现了:线程
// 例子使用 base_file_sink using basic_file_sink_mt = basic_file_sink<std::mutex>; using basic_file_sink_st = basic_file_sink<details::null_mutex>; struct null_mutex { void lock() const {} void unlock() const {} bool try_lock() const { return true; } }; template<typename Mutex> void SPDLOG_INLINE spdlog::sinks::base_sink<Mutex>::log(const details::log_msg &msg) { std::lock_guard<Mutex> lock(mutex_); sink_it_(msg); }
若是须要使用多线程模式,就使用 std::mutex
,若是是单线程,咱们就不须要互斥来同步,这里实现一个空的互斥量类,就使得 log() 的代码彻底不须要修改了,也提升了内聚性。debug
spdlog 默认使用同步模式,也能够设置异步模式,异步模式会建立一个线程池,线程池大小能够自行设置,默认为1,该线程池全部者为 details::registry::instance()
. 后台的大小能够设置的 多生产者多消费者队列 默认为阻塞模式,也能够设置为非阻塞,不过这个非阻塞的处理很是简单粗暴,就是简单的丢弃最老的日志,推荐是不要这样设置滴,通常产生阻塞的状况大概是磁盘IO打满了,出现这个状况通常是别的地方出问题了。
details::registry
管理全部的日志对象
<name, logger>
将日志对象和其名称对应起来,后面使用的时候能够直接经过名称获取对应的日志对象。