如何使用Google日志库(glog)

    工作有一段时间了,总是在忙碌和无所事事中矛盾着,今天据说台风17级,正好休息,于是整理一下glog。

    在公司管理日志用glog比较多,因为它开源,而且确实方便。官方文档在这里:http://google-glog.googlecode.com/svn/trunk/doc/glog.html 。按照个人理解翻译一下,翻译中可能会有个人理解,所以不保证原汁原味(不过尽量保持),也因水平有限,欢迎拍砖。


简介(Introduction)

    Google glog是一个实现应用级别日志的开源库,这个库提供了基于C++流风格的日志接口和许多有用的宏。要打出一个日志信息,只要和C++流类似的把信息输出到LOG()就可以了,哈哈,很容易吧?就和C++中使用cout一样!例如:

   #include 

   int main(int argc, char* argv[]) {
     // Initialize Google's logging library.
     google::InitGoogleLogging(argv[0]);

     // ...
     LOG(INFO) << "Found " << num_cookies << " cookies";
   }

    为了简化许多普遍的日志工作,glog定义了一系列宏。我们可以根据严重性等级打出日志,可以在命令行控制日志行为,可以按条件打出日志,也可以在期望的条件没有达到时退出程序,还可以引进自己的日志等级,等等。本文档介绍glog支持的功能。但是注意本文档并未介绍该库中所有的功能,仅介绍大多数有用功能。如果想了解更多常用功能的话,可以查看src/glog目录下的头文件。(补充一句:对于大多数开源工具,查看头文件虽然不能了解底层实现,但却是掌握接口使用和库中提供的功能的快捷通道。)


严重性等级(Severity Level)

    我们可以指定INFO、WARNING、ERROR、FATAL中的一种等级打出日志(严重性依次递增),以FATAL打出日志会在信息输出后终止程序。需要注意的是,高级别的日志不仅会输出在对应级别的日志文件中,也会输出在低级别的日志文件中。例如:一个ERROR级别的日志会同时输出在ERROR、WARNING、INFO对应的日志文件中。

    DFATAL级别的日志会在debug模式下打出一个FATAL级别的错误,在产品中,它通过自动降级为ERROR从而避免程序中断。

    除非特别指定,否则glog会把日志信息输出到"/tmp/...log...


设置参数(Setting Flags)

    有几个参数会影响glog的输出行为。如果你的电脑上安装了Google gflags library,那么配置脚本(可以查看包中的安装文件获取更多关于该脚本的详细信息)会发现和适用它,从而允许你在命令行传入参数。例如,如果你想开启参数--logtostderr,那么你可以按如下命令行启动自己的应用:

./your_application --logtostderr=1
    如果你没有安装Google gflags library,那么你可以通过设置环境变量设置这些参数,在参数名前加上 "GLOG_"就可以了。例如:

GLOG_logtostderr=1 ./your_application

    以下是常见的参数:

logtostderr (bool, default=false) 把信息输出到标准错误而非文件,默认值为false。
Note: 可以通过设置值为1,true,yes(大小写不敏感)把二进制参数设置为true,类似的,也可以通过设置值为0,false,no(大小写不敏感)把二进制参数设置为false。
stderrthreshold (int, default=2, which is ERROR) 严重性级别在该值以上的日志信息同时写入文件和标准错误。 严重性等级对应关系:INFO、WARNING、ERROR、FATAL一次为0、1、2、3。 log_dir (string, default="") 日志信息记录文件,默认为空。 v (int, default=0) 对于所有用VLOG(m)打出的日志,仅在m的值小于该参数的值时才进行输出,该值可能被vmodule覆盖,默认为0。 vmodule (string, default="") 分模块儿设置VLOG(m)日志的输出。参数格式为以逗号分隔的 =列表组成。其中module name支持通配符,忽略后缀名。log level覆盖--v设置的所有值。     在logging.cc中还有定义的别的参数,可以通过在源码中过滤“DEFINE_”查看所有参数。

    你还可以通过在程序中设置全局变量“FLAGS_*”调整参数。除了和目标文件有关的设置外,多数设置会在修改完FLAGS_*后立即生效。例如,你可能试图在调用google::InitGoogleLogging前设置FLAGS_log_dir ,这里是个例子:

   LOG(INFO) << "file";
   // Most flags work immediately after updating values.
   FLAGS_logtostderr = 1;
   LOG(INFO) << "stderr";
   FLAGS_logtostderr = 0;
   // This won't change the log destination. If you want to set this
   // value, you should do this before google::InitGoogleLogging .
   FLAGS_log_dir = "/some/log/directory";
   LOG(INFO) << "the same file";


条件日志(Conditional/Occasional Logging)

    有时,你可能想仅在某些条件满足的情况下才记录日志信息,可以使用如下宏完成条件日志:

LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
    只有当num_cookies > 10,该日志才会输出。如果某一行会被执行多次,在某些区间内输出信息可能非常有用。

LOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
    上面这条语句在该命令第1,11,21……次被执行时输出日志。google::COUNTER记录当前执行的次数。

    以上两类情况可以通过以下宏合并在一起使用:

LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << google::COUNTER
                                        << "th big cookie";
    除了在每第n次时输出日志,也可以限制前n次出现时输出日志:

LOG_FIRST_N(INFO, 20) << "Got the " << google::COUNTER << "th cookie";

    该命令在前20次执行时输出日志信息。


支持debug模式(Debug Mode Support)

    debug模式的特定的宏只在debug模式下生效,在非debug模式下编译中不生成任何信息。使用该宏可以避免因过多日志导致应用速度减慢。

DLOG(INFO) << "Found cookies";

DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";

DLOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";


CHECK宏(Check Macros)

    在程序中周期性地检查期望出现的情况,从而尽早的发现错误是一种非常好的习惯和方法。CHECK宏提供了一种在某种条件不满足时退出程序的机制,和标准C库中定义的assert类似。

    CHECK宏在条件非真时退出程序,和assert不同的是,CHECK不受NDEBUG的约束,因此,下例中的fp->Write(x)总是会被执行:

CHECK(fp->Write(x) == 4) << "Write failed!";
    有很多进行比较的宏:CHECK_EQCHECK_NECHECK_LECHECK_LTCHECK_GE, 和CHECK_GT(宏的意义根据字面意思应该很好理解,比如EQ是equal,GT是greater than等)。这些宏比较两个值,当结果和期望值不同时,输出一个FATAL级别的日志,该日志内容包含这两个值,因此,对比较的类型,必须定义了operator << (ostream, ...)。

    举例:

CHECK_NE(1, 2) << ": The world must be ending!";
CHECK_EQ(string("abc")[1], 'b');
    如果出现类型不一样的情况,可以用static_cast进行类型转换:

CHECK_EQ(some_ptr, static_cast(NULL));
    该例子中比较some_ptr是否为NULL。

    然后更好的比较方法是使用宏CHECK_NOTNULL:

CHECK_NOTNULL(some_ptr);
some_ptr->DoSomething();
    由于该宏返回该指针,所以在构造函数的初始化列表中非常有用:

   struct S {
     S(Something* ptr) : ptr_(CHECK_NOTNULL(ptr)) {}
     Something* ptr_;
   };

    果要比较两个C类型的字符串是否相等,可以使CHECK_STREQCHECK_STRNECHECK_STRCASEEQ,CHECK_STRCASENE,其中,带有CASE的表示大小写不敏感。像这些宏传入参数时,可以传入NULL,比较时,NULL和任何非NULL的字符串不相等,任意两个NULL相等。

    CHECK_DOUBLE_EQ检查两个浮点数是否相等,允许一个小范围的误差。CHECK_NEAR接受第三个浮点数作为参数,以指定误差允许的范围。

你可能感兴趣的:(学习笔记,C++)