日志能方便地诊断程序原因、统计程序运行数据,是大型软件系统必不可少的组件之一。本文将从设计上和功能上对比 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. java 标准日期格式

    public static void main(String[] argv) { // 使用默认时区和语言环境获得一个日历 Calendar cale = Calendar.getInstance() ...

  2. linux redhat 安装了jdk检查版本不是自己安装的版本的解决办法

    Linux下安装jdk java -version 不是自己所需要的版本 设置环境变量,这是最重要的 在etc/profile文件下添加 export JAVA_HOME=/usr/java/jdk1 ...

  3. radio回显的

    JS回显 var jksp=document.getElementsByName("spjdcyModel.jksp"); // alert(jksp[0].value); //a ...

  4. 走进JavaWeb技术世界7:Tomcat中的设计模式

    . 门面设计模式 门面设计模式在 Tomcat 中有多处使用,在 Request 和 Response 对象封装中.Standard Wrapper 到 ServletConfig 封装中.Appli ...

  5. golang ssh 远程执行命令(有一些命令会报command not found)

    func sshSession(user, password, host string, port int) (sshSession *ssh.Session, err error) { //参数: ...

  6. ST Debug (printf) Viewer for Jlink

    Debug (printf) Viewer http://www.keil.com/support/man/docs/uv4/uv4_db_dbg_serialwin.htm Serial Windo ...

  7. pecl和pear 的区别和联系

    Pear:是PHP的扩展代码包,所有的扩展均以PHP代码的形式出现,功能强大,安装简单,甚至可以改改就用.使用的时候,要在代码中进行Include才能够使用. Pecl:是PHP的标准扩展,可以补充实 ...

  8. linux nand flash常用命令

    使用命令前用cat /proc/mtd 查看一下mtdchar字符设备:或者用ls -l /dev/mtd*#cat /proc/mtddev:    size   erasesize  namemt ...

  9. angular中的动态路由

    1.配置动态路由 const routes: Routes = [ {path: 'home', component: HomeComponent}, {path: 'news', component ...

  10. nmealib-0.5.3 问题 Build Error: undefined reference to `ceil'

    When building on Ubuntu 12.x the build fails with the following error… gcc samples/generate/main.o - ...