日志能方便地诊断程序原因、统计程序运行数据,是大型软件系统必不可少的组件之一。本文将从设计上和功能上对比 C++ 语言常见的两款日志库: boost::log 和 google-glog 。

设计

boost::log 的设计主要有日志器( Logger )、日志核心( Logging core )、 Sink 前后端( frontend, backend )组成。日志文本以及日志环境由日志器( Logger )负责搜集,日志核心负责处理日志数据(例如全局过滤、将日志记录传递给 Sink ), Sink 前端分为同步、异步以及不考虑线程同步问题的版本,它们负责将日志记录传递给 Sink 后端处理。 Sink 后端负责把日志记录格式化并输出到不同的介质中(例如日志文件、报警以及统计源中)。

功能

严重性分级

boost::log 的默认分级包括 trace, debug, info, warning, error, fatal ,支持自定义分级。而 glog 仅仅支持 INFO, WARNING, ERROR, FATAL ,如果想要扩展严重性分级,需要使用 VLOG 宏,通过全局变量或者命令行来过滤。如果不使用自定义 Sink , glog 默认是以严重性等级将日志分散保存到不同文件中,如果需要将自定义等级( VLOG )输出到文件,需要修改库源码(参考 LogMessage::SendToLog )。如果给 glog 的日志级别设置为 FATAL , glog 在写完日志之后会自动终止程序。

日志过滤

glog 通过设置 stderrthreshold 全局变量或者命令行参数来实现大于等于某个级别的日志记录到 stderr 以及 log 文件中。而 boost::log 支持两层过滤,可以通过 core::set_filter 设置全局过滤器,也能通过 sink::set_filter 设置 sink 过滤器。配合 lambda 表达式 或者函数对象, boost::log 可以生成无论多么复杂的过滤器。(例如只把某个级别的日志写入文件,或者把统计日志、 trace 日志分别重定向到不同的 sink 中,然后输出到不同的介质)。

线程安全

glog 仅支持同步日志。它的写入代码可以参考 LogMessage::Flush ,在写入日志的时候使用了互斥锁,因此性能会受 I/O 速度影响。有两个支持异步日志的非官方 glog 库,他们分别是 g2log 和 g3log ,均采用 C++11 编写。 boost::log 支持 同步和异步 sink ,同步 sink 在将日志传递给 backend 时会加 互斥锁 。 boost::log 的同步异步 sink 切换起来非常方便,只需要修改类型名就可以了。

自定义 sink 功能

boost::log 和 glog 都支持自定义 sink ,可以实现一条日志信息复制分流到多个 sink 进行处理,也可以在 sink 中以不同的格式输出日志。但是 glog 的 sink 没有过滤器,能获取到的信息也有限。而 boost 将日志抽象成 record 对象,不仅仅包含了日志的文本,还可以包含更丰富的自定义属性。

自定义属性功能

有时程序需要记录的信息往往不仅仅包含一条消息,还需要包含执行环境的一些属性(例如网络对端的 IP 地址)。 boost::log 提供了 属性集 功能,属性集不仅仅包括常用的数据(例如计数器、时间、计时器、线程 ID 等信息)还支持自定义属性。用户可以将程序的任意上下文放入日志记录对象中,然后在 sink 中进行处理。而 glog 不支持此功能,它的 sink 能处理的数据都以函数参数的形式提供给回调函数。

自定义日志器( Logger )

glog 支持为不同严重级别的日志设定日志器,可以通过这点来将不同日志级别的日志分散到不同的文件中。 boost::log 也支持自定义日志源,但它不是用来过滤级别的(因为过滤功能用 sink 的 filtering 就够了),它的日志源可以包含 特定环境 的信息(例如在网络连接 network_connection 中的日志源可以携带远程 IP 地址这个属性,这样从那个日志源发出的每一条日志信息都包含此属性)。

滚动日志

glog 通过设置 FLAGS_max_log_size 这个全局变量来实现日志尺寸大小。 boost::log 则支持不同的 sink 按照文件大小、时间等参数来 旋转 。如果想要 glog 支持按照时间旋转日志,需要 改动 源代码。

宽字符支持

boost::log 支持 宽字符 日志, sink 可以通过设置 locale 进行必要的编码转换。而 glog 仅仅支持 const char* 类型的日志消息。

参数配置

glog 的参数配置(例如缓冲日志时间、最大日志大小、日志文件夹)大多以全局变量或者命令行参数的形式,并且它们控制的是全局范围的参数。 boost::log 可以针对不同 sink 设置不同参数。

格式化

除非自定义 sink ,默认情况下 glog 写入文件的格式是固定的(参考 LogFileObject::Write ),而 boost::log 如果想要设置不同的格式,只需要传递一个 formatter 对象给 sink 即可。

调试支持

glog 提供 DLOG 等宏,这些宏在没有定义 NDEBUG 时有效。 boost::log 则需要程序员自己条件输出。通过不同的 sink/filter 可以实现 glog 同样的功能。

条件日志

glog 支持 LOG_IF , LOG_EVERY_N 等条件日志宏。 boost::log 没有提供类似的宏,但是可以通过 filter 实现。

失败信号处理器

在 Linux 操作系统中, glog 提供 google::InstallFailureSignalHandler() 函数,当程序收到诸如 SIGSEGV 等会导致进程终止的信号时, glog 的信号处理器可以输出 stack trace 信息,方便调试。 glog 原生是为 Linux 操作系统准备的,因此对 Windows 的支持很有限,这个功能也不支持。 boost::log 没有实现这个功能。

文档

boost::log 的文档很全面,例程也很丰富, Google 上的资料也很多。 glog 官方只有 一篇 简介,细节问题则分散在开源社区的 issue 中(例如 Rolling File Log ),搜索引擎上的资料也少。

其他

  • boost::log 提供很多使用小工具,例如支持日志排序、输出操作、 binary dump 操作( logging::dump(packet.data(), packet.size() 对于输出内存块很方便)。

  • boost::log 支持从 配置文件 中读取日志配置信息,可以通过修改配置文件来修改日志过滤器、格式等配置。

  • 对于不同的输出方式, boost::log 提供了一些现成的 sink backend ,例如输出到 Windows 事件日志、调试器、 Linux syslog 接口、文本文件等。

  • glog 提供了一些类似单元测试的宏,例如 CHECK_EQ, CHECK_NE 等,可以有条件地终止程序, glog 还提供了类似 static_assert 的 GOOGLE_GLOG_COMPILE_ASSERT 。

总结

glog :小巧精简,源代码简洁易懂,便于学习。缺点是不太灵活,扩充功能需要修改库源码。文档资料少。

C++ 日志库 boost::log 以及 glog 的对比的更多相关文章

  1. 谷歌日志库GLog 使用说明

    1 引用头文件 加载库 #include <glog/include/logging.h> #pragma comment(lib,"libglog.lib") 2 初 ...

  2. glog日志库使用笔记

    日志能方便地诊断程序原因.统计程序运行数据,是大型软件系统必不可少的组件之一.glog 是google的开源日志系统,相比较log4系列的日志系统,它更加轻巧灵活. 在Github上下载glog,解压 ...

  3. golang的日志系统log和glog

    go语言有一个标准库,log,提供了最基本的日志功能,但是没有什么高级的功能,如果需要高级的特性,可以选择glog或log4go. 参考:https://cloud.tencent.com/devel ...

  4. C/C++log日志库比较

    事实上,在C的世界里面没有特别好的日志函数库(就像Java里面的的log4j,或者C++的log4cxx).C程序员都喜欢用自己的轮子.printf就是个挺好的轮子,但没办法通过配置改变日志的格式或者 ...

  5. C++的开源跨平台日志库glog学习研究(二)--宏的使用

    上一篇从整个工程上简单分析了glog,请看C++的开源跨平台日志库glog学习研究(一),这一篇对glog的实现代码入手,比如在其源码中以宏的使用最为广泛,接下来就先对各种宏的使用做一简单分析. 1. ...

  6. ubutun16.04 安装编译glog日志库

    glog 是一个 C++ 日志库,它提供 C++ 流式风格的 API.在安装 glog 之前需要先安装 gflags,这样 glog 就可以使用 gflags 去解析命令行参数(可以参见gflags ...

  7. C++的开源跨平台日志库glog学习研究(三)--杂项

    在前面对glog分别做了两次学习,请看C++的开源跨平台日志库glog学习研究(一).C++的开源跨平台日志库glog学习研究(二)--宏的使用,这篇再做个扫尾工作,算是基本完成了. 编译期断言 动态 ...

  8. C++的开源跨平台日志库glog学习研究(一)

    作为C++领域中为数不多的好用.高效的.跨平台的日志工具,Google的开源日志库glog也算是凤毛麟角了.glog 是一个C++实现的应用级日志记录框架,提供了C++风格的流操作. 恰巧趁着五一我也 ...

  9. [译]如何禁止Requests库的log日志信息呢?

    原文来源: https://stackoverflow.com/questions/11029717/how-do-i-disable-log-messages-from-the-requests-l ...

随机推荐

  1. properties的编码问题

    1.在eclipse中,如果不专门设置,properties文件的编码是ISO-8859-1,最好将其改为UTF-8 2.当properties文件的编码改为UTF-8还不够,Spring的conte ...

  2. mysql my.cnf文件

    一.mysqld组值设置: 1.user = mysql #启动mysql的用户.2.pid-file = /var/run/mysqld/mysqld.pid #指定pid文件.3.socket = ...

  3. 关于Linux安装中NAT模式和桥接模式的区别详解

    1.一般我们在创建一个Linux虚拟机时候,会面临三个网络配置选择: 桥接模式.nat模式.host-only模式(主机模式,这个模式用得少,就不介绍了) 2.NAT模式: 所谓nat模式,就是虚拟系 ...

  4. bash常用的快捷键

    bash常用快捷键 快捷键 作用 CTRL+A 把光标移动到命令行开头.如果我们输入的命令过长,则在想要把光标移动到命令行开头时使用 CTRL+E 光标移动到命令行行尾 CTRL+C 强制中止当前命令 ...

  5. idea备忘

    1.idea 最近打开的文件个数 File->Settings->Editor->General->Editor Tabs->Tab Closing Policy-> ...

  6. Discretized Streams: A Fault-Tolerant Model for Scalable Stream Processing

    https://www2.eecs.berkeley.edu/Pubs/TechRpts/2012/EECS-2012-259.pdf Discretized Streams: A Fault-Tol ...

  7. [webpack]解决报错 CleanWebpackPlugin is not a constructor

    错误写法 const CleanWebpackPlugin = require("clean-webpack-plugin"); 正确写法: let {CleanWebpackPl ...

  8. js实现文本框支持加减运算的方法

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/T ...

  9. 123457123456#0#-----com.twoapp.HuaXueGame01--前拼后广--儿童滑雪大冒险游戏jiemei

    com.twoapp.HuaXueGame01--前拼后广--儿童滑雪大冒险游戏jiemei

  10. python中的列表推导式——轻量级循环

    列表推导式(list comprehension)是利用其他列表创建新列表(类似于数学术语中的集合推导式)的一种方法.它的工作方式类似于for循环,也很简单. 列表推导式书写形式: [表达式 for ...