spdlog 基本结构分析

代码取自 V1.5.0, 代码堪称美学。

spdlog 是一个只有头文件的C++日志库,速度非常快,扩展性很强,更重要的是 社区活跃,文档齐全

使用

  1. 参考官方的 example.
  2. {fmt} 的格式使用也需要熟悉一下,毕竟也进 C++20 了,什么垃圾流就快扫进历史的垃圾堆吧.

分析

这里选择了三个点来做分析:

  1. 提供的 日志格式 非常丰富,并且允许用户自定义需要的格式。
  2. 对日志文件的类型也做了充分扩展,支持控制台,普通文件,按大小滚动文件,按时间滚动文件,如果不能满足需要,可以自己扩展格式,见 spdlog/sinks/base_sink.h
  3. 支持单/多线程,异步/同步,阻塞非阻塞模式。

spdlog 的代码结构如下:

spdlog
├─example 用法代码
├─include 实现目录
│ └─spdlog
│ ├─details 功能函数目录
│ ├─fmt {fmt} 库目录
│ ├─sinks 落地文件格式实现
│ └─*.h 异步模式,日志库接口等实现
├─src .cpp 文件,组成编译模块生成静态库使用
├─test 测试代码

基本逻辑结构如下:

有几个比较重要的文件:

  • spdlog/spdlog.h 为日志库接口,提供日志宏的属性控制函数。
  • spdlog/logger.h 为日志管理器,为前后端连接的枢纽。
  • spdlog/async.h 为异步模式接口。
  • spdlog/sinks/base_sink.h 为日志文件格式父类,后面所有的日志文件格式都是继承该类来实现不同功能。
  • spdlog/sinks/registry.h 用于登记所有的logger,及一些默认的属性,如日志格式、日志写入等级。

spdlog 接口

spdlog 总体而言提供了日志接口

  1. spdlog::debug(), 默认的日志对象,使用默认的日志信息格式,输出至 stdout。
  2. logger->debug(), 指定日志对象进行日志记录,输出至该日志对象对应的文件中。
  3. SPDLOG_LOGGER_DEBUG(logger), SPDLOG_DEBUG(), 使用宏对以上两种接口进行包装,产生的日志格式包含 文件、函数、行。

提供的一些落地的文件类型:

  • 标准输出
  • 带颜色的标准输出(默认)
  • 基本文件
  • 可设定时间的滚动文件
  • 可设定大小的滚动文件
  • 过滤重复的日志
  • syslog 日志

这里简单提一下 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() 的代码完全不需要修改了,也提高了内聚性。

spdlog 默认使用同步模式,也可以设置异步模式,异步模式会创建一个线程池,线程池大小可以自行设置,默认为1,该线程池所有者为 details::registry::instance(). 后台的大小可以设置的 多生产者多消费者队列 默认为阻塞模式,也可以设置为非阻塞,不过这个非阻塞的处理非常简单粗暴,就是简单的丢弃最老的日志,推荐是不要这样设置滴,一般产生阻塞的情况大概是磁盘IO打满了,出现这个情况一般是别的地方出问题了。

details::registry 管理所有的日志对象

  1. 使用 <name, logger> 将日志对象和其名称对应起来,后面使用的时候可以直接通过名称获取对应的日志对象。
  2. 保存全部日志对象的默认属性,可使用提供的属性控制接口改变所有的日志对象属性。
  3. 提供定时flush,spdlog 的文件操作具有缓冲区属性,为试日志信息及时落地,后台新生成一个flush线程,设置一个时间(单位:秒)定时唤醒一次进行 flush。

参考

  1. {fmt}, A modern formatting library. 现代化的格式化库,速度快,使用简单,已经确定进入 C++20.

spdlog 基本结构分析的更多相关文章

  1. Facebook的体系结构分析---外文转载

    Facebook的体系结构分析---外文转载 From various readings and conversations I had, my understanding of Facebook's ...

  2. Android项目目录结构分析

    Android项目目录结构分析 1.HelloWorld项目的目录结构1.1.src文件夹1.2.gen文件夹1.3.Android 2.1文件夹1.4.assets 1.5.res文件夹1.6.An ...

  3. 【转载】nedmalloc结构分析

    原文:nedmalloc结构分析 nedmalloc是一个跨平台的高性能多线程内存分配库,很多库都使用它,例如:OGRE.现在我们来看看nedmalloc的实现 (以WIN32部分为例)    位操作 ...

  4. laravel5-目录结构分析

    laravel5-目录结构分析 (2016-01-21 11:24:03) 转载▼     一.环境配置: $ lsb_release -a No LSB modules are available. ...

  5. [Cocos2d-x for WP8学习笔记] HelloWorld结构分析

    先来看一下目录结构: Assets:游戏资源文件,图片音频等,Resource文件夹也有类似功能 include:用于放置游戏头文件 Shaders:渲染器着色器文件(大雾) cocos2dorig. ...

  6. Sde表结构分析

    原文 Sde表结构分析 今天开始想分析一下sde的表结构,希望能够弄明白sde一个要素类的每个Feature是如何存储的. 弄ArcSDE的人都知道,ArcSDE内一个要素类在关系数据库(以MS SQ ...

  7. Linux中断处理体系结构分析

    Linux中断处理体系结构分析(一) 异常,就是可以打断CPU正常运行流程的一些事情,比如外部中断.未定义指令.试图修改只读的数据.执行swi指令(Software Interrupt Instruc ...

  8. PNG文件结构分析 ---Png解析

    PNG文件结构分析 ---Png解析   为了实现更高级的应用,我们必须充分挖掘PNG的潜力. PNG的文件结构 根据PNG文件的定义来说,其文件头位置总是由位固定的字节来描述的:   十进制数 13 ...

  9. Android 虚拟机Dalvik、Android各种java包功能、Android相关文件类型、应用程序结构分析、ADB

    Android虚拟机Dalvik Dalvik冲击 随着Google 的AndroidSDK 的发布,关于它的API 以及在移动电话领域所带来的预期影响这些方面的讨论不胜枚举.不过,其中的一个话题在J ...

随机推荐

  1. 2019-10-23-WPF-使用-SharpDx-异步渲染

    title author date CreateTime categories WPF 使用 SharpDx 异步渲染 lindexi 2019-10-23 21:18:38 +0800 2018-0 ...

  2. Scheduler

    先看看文档对于Scheduler的作用介绍 https://code4craft.gitbooks.io/webmagic-in-action/content/zh/posts/ch1-overvie ...

  3. 如何读取redis中的key值中的结果

    redis的值有5种类型,不同的类型有不同的命令来获取: 字符直接 get key 队列 左端弹出一个元素  LPOP key 哈希 HGET key field 集合 SMEMBERS key 返回 ...

  4. 学习vue就是那么简单,一个简单的案例

    vue是前端兴起的一个javascript库,相信大家都使用过jQuery,虽然vue和jQuery没有可比性,但从熟悉的角度去理解新的东西或许会容易接受一些,有时候由于思想和模式的转变会带来阵痛,但 ...

  5. Canvas学习实践:一款简单的动画游戏

    最近学习了下Canvas绘图...突发奇想就有了下面这款简单的小游戏,纯属娱乐~ 废话不多说,直接上代码: <!DOCTYPE html> <html lang="zh&q ...

  6. Cannot destructure property `createHash` of 'undefined' or 'null'(next服务端渲染引入next-less错误).

    next中引入@zeit/next-less因next版本过低(webpack4之前的版本)无法执行next-less内置的mini-css-extract-plugin mini-css-extra ...

  7. CMD操纵Mysql命令大全

    连接:mysql -h主机地址 -u用户名 -p用户密码 (注:u与root可以不用加空格,其它也一样)断开:exit (回车) 创建授权:grant select on 数据库.* to 用户名@登 ...

  8. maxmind geoip2使用笔记

    客户需求如下,nginx的访问日志中ip,匹配出对应的国家,省份和城市,然后给我了一个maxmind的连接参考. 查找资料,有做成hive udf的使用方式, 我们项目中一直使用 waterdrop ...

  9. 【Git】git-filter-branch - Rewrite branches

    1.命令使用场景 ①Removing sensitive data from a repository(https://help.github.com/en/github/authenticating ...

  10. Struts2注解详解(转)

    一,引入支持Struts2支持注解开发jar包: struts2-convention-plugin-2.1.8.1.jar(支持Struts2框架注解开发的jar包) 二,Struts2使用注解开发 ...