easylogging++的那些事(三)总体设计

上一篇文章我们介绍了 easylogging++的 ,今天我们开始介绍 easylogging++的总体设计。

一、日志框架的需求分析

    谈 easylogging++的总体设计之前,我们先假设现在需要开发一个日志框架,按照软件开发的流程,我们首进行需求分析。需求分为功能性需求和非功能性需求,日志框架的功能性需求就是日志框架要实现的功能,即规范应用程序日志记录过程,将处理日志记录这件事情的过程标准化。当想要捕获程序的运行时信息时,日志框架首先要发出要记录的信息,然后格式化这些信息,最后决定将它出到哪里。一般情况下,会输出到文件中,但是也可以将其输出到控制台、数据库,或者任何能够接收数据地方。
    通过上面的描述,我们可以得出 日志框架的功能性需求:

  • 日志内容:多种日志类型的支持
  • 日志格式的管理:日志格式的配置
  • 日志输出地的管理

    再说说 日志框架的非功能性需求:

  • 易用性
    日志框架否易集成、易插拔、跟业务代码是否松耦合、提供的接口是否够灵活等等有的时候,文档写得好坏甚至都有可能决定一个框架是否受欢迎。

  • 性能
    由于日志记录是很频繁的,我们不希望日志框架本身的代码执行效率,对业务系统有太多性能上的影响。

  • 扩展性
    可以在不修改框架源码,甚至不拿到框架源码的情况下,为框架扩展新的功能。这就有点类似给框架开发插件。

  • 容错性
    日志记录异常不能对正常的业务逻辑造成影响。

二、easylogging++的需求分析

功能性需求

1、日志内容: 多种日志类型的支持

    easylogging++将日志分为两种:用户日志和 syslog 日志,而用户日志又可分为普通日志和 verbose 日志。其中普通日志又可以细分为 带 errno 错误信息的和 不带 errno 错误信息。

2、日志格式的管理: 日志格式的配置

    easylogging++可以通过三种方式来配置:

  1. 命令行参数
  2. 通过相应的 API 以字符串形式来配置
  3. 通过加载配置文件

3、日志输出地的管理

    默认 easylogging++提供了对于控制台和文件输出这两种输出地的管理,其他方式可以通过注册相应的 LogDispatchCallback 回调来实现。github 上提供了通过 boost 实现的网络发送日志的 demo

非功能性需求

1、易用性

  • 官方文档很清晰。
  • 目前仅仅包含一个头文件和一个 cc 文件,很容易集成。
  • 接口易于使用,提供了流式接口和类似 printf 的接口以及大量相关的日志记录宏。

2、性能

    目前网上没有看到相关的性能评测数据,这里就不做过多说明,从源码上面能看的到的有四点:

  • 流式输出
  • 复用文件流
  • 支持日志缓存
  • 异步日志支持(实验性功能,由同步日志改为异步日志会出现崩溃问题)

3、扩展性

  • 提供了不同类型的回调注册机制
        1) 注册相应的 LogDispatchCallback 回调来实现日志输出事件的跟踪
        2) 注册相应的 PerformanceTrackingCallback 回调实现自定义的性能跟踪
        3) 注册相应的 LoggerRegistrationCallback 回调实现日志记录器注册事件的跟踪
        4) 支持日志旋转功能(源码当中这里实现的日志旋转后会截断日志文件的动作确实在实际项目中一般不这么用)
        5) 注册自定义的崩溃处理器以及堆栈跟踪
  • 灵活的日志格式配置方式,同时还支持自定义日志格式解析器,通过 CustomFormatSpecifier 类实现
  • STL, QT, BOOST, wxWidgets 相关数据类型直接输出到日志的支持以及兼容第三方类型直接日志输出支持

4、容错性

  • easylogging++支持线程安全。
  • 记录日志时,内部已经捕获了所有的异常,不让异常对正常的业务逻辑造成影响。

三、easylogging++的框架设计

easylogging++的所有与日志输出相关的信息都保存在 Storage 类中,日志库的入口类或者总的管理类,其中保存了这些信息:

  • RegisteredHitCounters 指定文件指定行的用于是否记录日志的计数器
  • RegisteredLoggers 注册的日志记录器的管理类
  • LoggingFlag 写日志时会用到的一些标志
  • VRegistry 详细日志相关配置的管理类(保存详细日志级别以及 vModule 相关信息)
  • AsyncLogQueue 异步日志队列(暂时保存日志)
  • IWorker 异步日志调度器(处理 AsyncLogQueue 中的日志)
  • CommandLineArgs 命令行参数解析器
  • PreRollOutCallback 日志回旋回调函数
  • LogDispatchCallback 所有注册的日志派发回调函数
  • PerformanceTrackingCallback 所有注册的性能跟踪回调函数
  • 线程信息容器(线程 ID 字符串 线程名称)
  • CustomFormatSpecifier 自定义日志格式指示器
  • Level 普通日志记录时的基准日志级别,大于这个级别才会记录普通日志

其中 RegisteredLoggers 管理的日志记录器类为 Logger,每个 Logger 实例保存了以下信息:

  • id: Logger 标识符,唯一标识一个 logger 实例
  • stringstream_t 每个 Logger 实例的字符串流,每条日志的信息会先写入这个字符串流
  • 应用程序名称
  • Configurations Logger 实例对应各个日志级别的配置项的字符串形式的值 Logger 实例对应的字符串形式的日志格式信息,比如是否启用配置项是字符串形式的 "true" 或者 "false"
  • TypedConfigurations Logger 实例对应各个日志级别的配置项的类型是程序运行时的实际类型,比如是否启用配置项是 bool
  • Logger 实例对应各个日志级别的写日志时未刷新累计的次数
  • LogStreamsReferenceMapPtr 文件名和对应文件流的映射关系容器(key-> 文件名,value-> 文件流)

easylogging++的总体设计就介绍到这里,下一篇我们开始分析主流程。

posted @ 2022-11-23 21:34  节奏自由  阅读(291)  评论(0编辑  收藏  举报