glog功能介绍


http://blog.51cto.com/mengjh/546766

本文是根据自己的理解翻译组织了glog的manual,鉴于自身的理解能力和英语水平,可能存在谬误,欢迎大家指出!英文原文见 http://google-glog.googlecode.com/svn/trunk/doc/glog.html
 
1.   概述
      Google glog是一个基于程序级记录日志信息的c++库,编程使用方式与c++的stream操作类似,例:
       LOG(INFO) << "Found " << num_cookies << " cookies";
“LOG”宏为日志输出关键字,“INFO”为严重性程度。
主要支持功能:
1, 参数设置,以命令行参数的方式设置标志参数来控制日志记录行为;
2, 严重性分级,根据日志严重性分级记录日志;
3, 可有条件地记录日志信息;
4, 条件中止程序。丰富的条件判定宏,可预设程序终止条件;
5, 异常信号处理。程序异常情况,可自定义异常处理过程;
6, 支持debug功能。可只用于debug模式;
7, 自定义日志信息;
8, 线程安全日志记录方式;
9, 系统级日志记录;
10, google perror风格日志信息;
11, 精简日志字符串信息。
 
2.   功能使用
1.1  参数设置
       可通过命令行方式设置glog的标志参数,用来控制日志记录行为。
命令格式如下:
      标志名1 =  标志值  标志名2= 标志值  ……  标志值n= 标志值        ./ 程序名
所有标志名需添加统一前缀—“ GLOG_”,不同标志语句之间以空格相隔;
例如:
-- GLOG_vmodule=mapreduce=2,file=1,gfs*=3  -- GLOG_v=0 ./application.exe
 
常用标志参数类型及其作用说明:
标志参数
类型
作用
logtostderr
bool
值为true的时候,日志信息输出到stderr,并非文件。默认值为 false。
stderrthreshold
int
严重性级别在该门限值以上的日志信息除了写入日志文件以外,还要输出到stderr。各严重性级别对应的数值:INFO—0,WARNING—1,ERROR—2,FATAL—3
默认值为2.
minloglevel
int
严重性级别在该门限值以上的日志信息才进行记录。
默认值为0.
log_dir
string

日志信息记录路径。默认为空,如果没有指定信息输出到stderr,则信息保存在"/tmp/<program name>.<hostname>.<user name>.log.<severity level>.<date>.<time>.<pid>"文件中。 (e.g., "/tmp/hello_world.example.com.hamaji.log.INFO.20080709-222411.10474").

v
int
对于使用“  VLOG(m) ”(m为int型)表达式进行输出的日志信息,只在m的值小于该标志的值的时候,才进行输出。另外, 该设置可能被 vmodule标志给覆盖.默认为0.
vmodule
string

分模块(文件)设置VLOG(m)日志信息的输出基本。命令格式为以逗号分开的“<module name>=<log level>”表达式组成。其中<module name> 是“glob pattern”,支持通配符,<module name>不包括文件的扩展名(.h,.cc等)。

 
表1标志说明
还有其他的标志参数定义在logging.cc,可在文件中搜索“DEFINE_”来进行查看。
1.2     严重性分级记录信息
glog可通过根据指定的严重性等级,来选择性记录日志。日志信息严重性等级按由低到高排列依次为: INFOWARNINGERROR, 和  FATAL四级。使用者可以在命令行中设置严重性等级门限值来控制日志的输出,详细见“参数设置”部分的“ minloglevel”标志值的介绍。
1.3     有条件地记录日志信息
glog可以控制日志信息在指定条件下进行记录。具体使用如下:

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

上面的语句表示,只有当num_cookies > 10条件成立时,“Got lots of cookies”日志信息才被记录。

 

2, LOG_EVERY_N(INFO, 10) << "Got the " << COUNTER << "th cookie";

上面的语句表示,在程序中周期性的记录日志信息,在该语句第1、11、21……次被执行的时候,记录日志信息。COUNTER变量表示该语句被执行的次数。
 

3, LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << COUNTER<< 
"th big cookie";

上面的语句为1,2项功能的合并,size>1024的条件连续成立10次的时候记录日志信息。COUNTER变量表示该条件成立的次数。
 

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

上面的语句表示,当该语句只在首次执行了20次以后记录日志信息, COUNTER变量表示该语句被执行的次数。

1.4     有条件地中止程序
       glog提供了CHECK宏,用于在调试地时候中止程序,及早发现程序错误。当通过该宏指定的条件不成立的时候,程序会中止,并且记录对应的日志信息。功能类似于ASSERT,区别是CHECK宏不受NDEBUG约束,在release版中同样有效。具体使用如下:
                 CHECK(fp->Write(x) == 4) << "Write failed!";
       当fp->Write(x) == 4成立时,记录“Write failed!”日志信息,并且中止程序,其中fp->Write(x) == 4为判定条件,日志信息以c++的stream操作形式生成。
glog提供了多个便利的宏来处理特定关系的判定。具体有:

1,判定大小关系

CHECK_EQ, CHECK_NE, CHECK_LE, CHECK_LT, CHECK_GE, CHECK_GT,使用这些宏需要注意类型一致,如果出现类型不一致的,可使用static_cast转换。

2,判定指针是否为空

        CHECK_NOTNULL(some_ptr),可用于对象初始化的时候。

3,判定字符串是否相等

         CHECK_STREQCHECK_STRNECHECK_STRCASEEQCHECK_STRCASENE 。可进行大小写敏感或不敏感字符串来分别判定。
4,      判定浮点是否相等或相近
CHECK_DOUBLE_EQ ,CHECK_NEAR。这两个宏都需要指定一个可容忍的偏差上限。
当这些宏判定条件不成立时,glog会生成一个FATAL级别的日志信息,该信息包含比较的两个值和stream方式传入的字符串,然后中止程序。
1.5     异常信号处理
      glog提供了比较方便的程序异常处理机制。例如,当程序出现SIGSEGV异常信号时,glog的默认异常处理过程会导出非常有用的异常信息。异常处理过程可以通过google::InstallFailureSignalHandler()来自定义。下面为异常处理过程的输出例子:
 *** Aborted at 1225095260 (unix time) try "date -d @1225095260" if you are using GNU date ***

*** SIGSEGV (@0x0) received by PID 17711 (TID 0x7f893090a6f0) from PID 0; stack trace: ***

PC: @           0x412eb1 TestWaitingLogSink::send()

    @     0x7f892fb417d0 (unknown)
    @     0x412eb1 TestWaitingLogSink::send()

    @     0x7f89304f7f06 google::LogMessage::SendToLog()

    @     0x7f89304f35af google::LogMessage::Flush()

    @     0x7f89304f3739 google::LogMessage::~LogMessage()

    @     0x408cf4 TestLogSinkWaitTillSent()
    @     0x4115de main
    @     0x7f892f7ef1c4 (unknown)

    @     0x4046f9 (unknown)

默认情况下,异常信息是输出到stderr,通过InstallFailureWriter()可以改变输出目标。
 
1.6     支持debug功能
      glog提供特定的宏只在debug模式下生效。以下分别对应LOG、LOG_IF、DLOG_EVERY_N操作的专用宏。

   DLOG(INFO) << "Found cookies";

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

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

1.7     自定义日志信息
        glog提供VLOG宏,让用户自定义分级信息,该分级与LOG宏对应的严重性分级是独立管理,在命令行参数设置中独立设置“v”或“vmodule”参数来控制,具体见“参数设置”部分标志说明。VLOG宏便于用户调试、查找完问题以后,屏蔽日志信息,减轻负担。具体使用如下:
 
  VLOG_IF(1, (size > 1024))<< "I'm printed when size is more than 1024 and when you run the ""program with --v=1 or more";
       上面的语句,只有在size>1024成立时且命令行参数v的值不小于1,才记录日志信息。
 
  VLOG_EVERY_N(1, 10)<< "I'm printed every 10th occurrence, and when you run the program ""with --v=1 or more. Present occurence is " << COUNTER;
       上面的语句,只有在命令行参数v的值不小于1时,才会每执行10次记录一次日志信息。
 
  VLOG_IF_EVERY_N(1, (size > 1024), 10)<< "I'm printed on every 10th occurence of case when size is more "" than 1024, when you run the program with --v=1 or more. "; "Present occurence is " << COUNTER;
       上面的语句,只有在命令行参数v的值不小于1时,若size>1024条件连续成立10次,记录一次日志信息。
 
1.8     线程安全日志记录
      glog提供了线程安全的日志记录方式。在<glog/raw_logging.h>文件中提供了相关的宏,如,RAW_CHECK,RAW_LOG等。这些宏的功能与CHECK,LOG等一致,除此以外支持线程安全,不需要为其分配任何内存和提供额外的锁(lock)机制。
 
1.9     系统级日志记录
  glog除了提供了普通的日志记录宏,还提供SYSLOG, SYSLOG_IF,和 SYSLOG_EVERY_N宏,这些宏将日志信息通过syslog()函数记录到系统日志。
1.10   google perror风格日志信息
     glog提供了与LOG*和CHECK宏作用等价的PLOG()、PLOG_IF() 和PCHECK()宏,不同的是,后者在记录日志信息的时候,会将errno的状态及其描述附加到日志描述中。
如:

PCHECK(write(1, NULL, 2) >= 0) << "Write NULL failed";

当条件不成立时,会输出日志信息:

F0825 185142 test.cc:22] Check failed: write(1, NULL, 2) >= 0 Write NULL failed: Bad address [14]

1.11   精简日志字符串信息
      日志信息的字符串会占用比较大的内存空间,另外还带来隐私泄露的问题。glog提供了GOOGLE_STRIP_LOG宏在编译时候去除日志的字符串信息。
 
3.   其他说明
1, windows平台使用注意
因为glog的严重性级别中使用了ERROR宏,与<windows.h>文件中冲突,可通过以下两种方式避免:
     a,在包含<windows.h>文件之前,定义宏WIN32_LEAN_AND_MEAN 或者NOGDI。
     b,在包含<windows.h>文件之后,undef掉ERROR定义.
======================================================================================================================================================================
http://littlewhite.us/archives/157

glog安装及使用


作者:littlewhite
glog是Google的开源日志系统,使用简单,配置灵活,适合大小型程序的开发。本文介绍Linux平台的安装和使用

 

安装

推荐从源码安装,下载地址https://code.google.com/p/google-glog/downloads/list
下载解压后进入目录,和所有Linux程序的安装步骤一样

./configuer
make
make install

如果没有权限请在命令前加上sudo,如果想安装在指定目录,使用./configuer --prefix=your_dir

使用

glog的使用简单到令人发指
现有测试程序test.cpp如下

#include <glog/logging.h>
int main(int argc, char* argv[])
{
   google::InitGoogleLogging(argv[0]);
   LOG(INFO) << "info: hello world!";
   LOG(WARNING) << "warning: hello world!";
   LOG(ERROR) << "error: hello world!";
   VLOG(0) << "vlog0: hello world!";
   VLOG(1) << "vlog1: hello world!";
   VLOG(2) << "vlog2: hello world!";
   VLOG(3) << "vlog3: hello world!";
   DLOG(INFO) << "DLOG: hello world!";
   return 0;
}

假设你的glog库的路径为/usr/local/lib/libglog.a,头文件路径为/usr/local/include/glog/logging.h,那么编译命令如下

g++ test.cpp -o test -L/usr/local/lib -lglog -I/usr/local/include/glog

执行如下命令

GLOG_logtostderr=1 ./test

看看是不是将日志打印到屏幕上了,但是你会发现有些日志没有打印出来。接下来我来一一解释

日志级别

使用日志必须了解日志级别的概念,说白了就是将日志信息按照严重程度进行分类,glog提供四种日志级别:INFO, WARNING, ERROR, FATAL。它们对应的日志级别整数分别为0、1、2、3, 每个级别的日志对应一个日志文件,其中高级别的日志也会出现在低级别的日志文件中,也就是说FATAL日志会出现在INFO、WARNING、ERROR对应的日志文件中。FATAL日志会终止程序,没事别乱用。

日志文件

glog的日志文件默认是保存在/tmp目录下的,当然你可以指定日志路路径和日志名称
指定日志文件名字

google::InitGoogleLogging(argv[0])

你也可以指定其它字符串,比如本例指定的名字为test,那么日志文件就是test.INFO, test.WARNING这样的格式

指定参数

glog可以采用命令行的模式配置参数,这也是它灵活易用的体现,有两种指定参数的方法,一种依赖于gflag如下:

./your_application --logtostderr=1

或者通过环境变量指定:

GLOG_logtostderr=1 ./your_application

所有的环境变量均以GLOG_开头,我们推荐使用第二种,一来不必依赖于gflag,二来当参数很多时,可以写成脚本的形式,看起来更直观,GLOG支持的flag如下(只列出常用的,如果想看全部的,可以在源码的logging.cc文件下看到):

GLOG_logtostderr
bool,默认为FALSE,将日志打印到标准错误,而不是日志文件
GLOG_alsologtostderr
bool,默认为FALSE,将日志打印到日志文件,同时也打印到标准错误
GLOG_stderrthreshold
int,默认为2(ERROR),大于等于这个级别的日志才打印到标准错误,当指定这个参数时,GLOG_alsologtostderr参数将会失效
GLOG_minloglevel
int,默认为0(INFO), 小于这个日志级别的将不会打印
GLOG_log_dir
string类型,指定日志输出目录,目录必须存在
GLOG_max_log_size
int,指定日志文件最大size,超过会被切割,单位为MB
GLOG_stop_logging_if_full_disk
bool,默认为FALSE,当磁盘满了之后不再打印日志
GLOG_v
int,默认为0,指定GLOG_v=n时,对vlog(m),当m<=n时才会打印日志

知道了这些参数之后,我们可以在脚本中指定这些变量,还是以test程序为例,test.sh如下:

#!/bin/sh
export GLOG_log_dir=log
export GLOG_minloglevel=1
export GLOG_stderrthreshold=1
export GLOG_v=3
export GLOG_max_log_size=1
./test

执行脚本sh test.sh即可。这样看上去就非常清晰,修改起来也方便

打印日志

普通模式

LOG(INFO) << "info: hello world!";

打印日志为INFO级别

 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";

以上两者的组合

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

顾名思义,前20次执行的时候打印日志

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";

当编译的时候指定-D NDEBUG时,debug日志不会被输出,比如test.cpp的编译命令改为

g++ test.cpp -o test -L/usr/local/lib -lglog -I/usr/local/include/glog -D NDEBUG

那么就不会有debug日志输出

check模式

CHECK( fd != NULL ) << " fd is NULL, can not be used ! ";

当check的条件不成立时,程序打印完日志之后直接退出,其它命令包括CHECK_EQ, CHECK_NE, CHECK_LE, CHECK_LT, CHECK_GE, CHECK_GT。以CHECK_EQ为例,适用方式如下

CHECK_NE(1, 2) << ": The world must be ending!";

自定义日志级别

VLOG(1) << "vlog1: hello world!";
VLOG(2) << "vlog2: hello world!";

这个是独立于默认日志级别的,可以配合GLOG_v参数适用

总结

GLOG使用就是如此方便,你只需要在代码里指定日志文件名,然后就可以放心的在代码里添加日志而不需要管那些初始化和销毁的操作,其它都可以以命令行的方式来配置,简单灵活,而且基本功能也比较齐全。另外,如果想了解GLOG详细适用,可以参考官方文档http://google-glog.googlecode.com/svn/trunk/doc/glog.html

 =======================================================================================================================================================================

http://www.cnblogs.com/caolisong/archive/2007/04/25/726896.html

linux shell 中"2>&1"含义

 

脚本是:
      nohup /mnt/Nand3/H2000G  >/dev/null  2>&1  &
      对于& 1 更准确的说应该是文件描述符 1,而1 一般代表的就是STDOUT_FILENO,实际上这个操作就是一个dup2(2)调用.他标准输出到all_result ,然后复制标准输出到文件描述符2(STDERR_FILENO),其后果就是文件描述符1和2指向同一个文件表项,也可以说错误的输出被合并了.其中0表示键盘输入 1表示屏幕输出 2表示错误输出.把标准出错重定向到标准输出,然后扔到/DEV/NULL下面去。通俗的说,就是把所有标准输出和标准出错都扔到垃圾桶里面。
      command >out.file  2>&1 &
      command >out.file是将command的输出重定向到out.file文件,即输出内容不打印到屏幕上,而是输出到out.file文件中。2>&1 是将标准出错重定向到标准输出,这里的标准输出已经重定向到了out.file文件,即将标准出错也输出到out.file文件中。最后一个& , 是让该命令在后台执行。

      试想2>1代表什么,2与>结合代表错误重定向,而1则代表错误重定向到一个文件1,而不代表标准输出
换成2>&1,&与1结合就代表标准输出了,就变成错误重定向到标准输出.

      你可以用
            ls 2>1测试一下,不会报没有2文件的错误,但会输出一个空的文件1;
            ls xxx 2>1测试,没有xxx这个文件的错误输出到了1中;
            ls xxx 2>&1测试,不会生成1这个文件了,不过错误跑到标准输出了;
            ls xxx >out.txt 2>&1, 实际上可换成 ls xxx 1>out.txt 2>&1;重定向符号>默认是1,错误和输出都传到out.txt了。
      为何2>&1要写在后面?
      command > file 2>&1 
       首先是command > file将标准输出重定向到file中, 2>&1 是标准错误拷贝了标准输出的行为,也就是同样被重定向到file中,最终结果就是标准输出和错误都被重定向到file中。 
      command 2>&1 >file 
      2>&1 标准错误拷贝了标准输出的行为,但此时标准输出还是在终端。>file 后输出才被重定向到file,但标准错误仍然保持在终端

用strace可以看到: 
1. command > file 2>&1 
这个命令中实现重定向的关键系统调用序列是: 
open(file) == 3 
dup2(3,1) 
dup2(1,2) 

2. command 2>&1 >file 
这个命令中实现重定向的关键系统调用序列是: 
dup2(1,2) 
open(file) == 3 
dup2(3,1) 

      可以考虑一下不同的dup2()调用序列会产生怎样的文件共享结构。请参考APUE 3.10, 3.12 

===================================================================================================================================================

https://unix.stackexchange.com/questions/20469/difference-between-21-output-log-and-21-tee-output-log

Difference between 2>&1 > output.log and 2>&1 | tee output.log

问题:

I wanted to know the difference between the following two commands

2>&1 > output.log 

and

2>&1 | tee output.log

I saw one of my colleague use second option to redirect. I know what 2>&1 does, my only question is what is the purpose of using tee where a simple redirection ">" operator can be used?

回答:

2>&1 >output.log means first start sending all file handle 2 stuff (standard error) to file handle 1 (standard output) then send that to the file output.log. In other words, send standard error and standard output to the log file.

2>&1 | tee output.log is the same with the 2>&1 bit, it combines standard output and standard error on to the standard output stream. It then pipes that through the tee program which will send its standard input to its standard output (like cat) and also to the file. So it combines the two streams (error and output), then outputs that to the terminal and the file.

The bottom line is that the first sends stderr/stdout to the file, while the second sends it to both the file and standard output (which is probably the terminal unless you're inside another construct which has redirected standard output).

I mention that last possibility because you can have stuff like:

(echo hello | tee xyzzy.txt) >plugh.txt

where nothing ends up on the terminal.

---------------------------1 You have the syntax right, but not the semantics. Run cat /doesnotexist 2>&1 >output.txt - you will see see cat: /doesnotexist: No such file or directory displayed to the terminal and output.txt is an empty file. Order of precedence and closure are in play: 2>&1 (dup fd2 from the current fd1), then >output.txt (redirect fd1 to output.txt, not changing anything else). The reason that 2>&1 | is different is because of order of precedence: | before >. – Arcege Sep 10 '11 at 23:33

First command will do the another task:

After

2>&1 > output.log 

the old STDOUT will be saved (copied) in STDERR and then STDOUT will be redirected to file.

So, stdout will go to file and stderr will go to console.

And in

 2>&1 | tee output.log

both streams will be redirected to tee. Tee will duplicate any input to its stdout (the console in your case) and to file (output.log).

And there is another form of first:

 > output.log 2>&1

this will redirect both STDOUT and STDERR to the file.

===============================================================================================================================

http://luofeilong.github.io/2015/09/13/glog-study-0/

 

如何使用google日志库(glog)

每个软件都会对自身的运作情况进行一些记录,这些信息将会保存到日志文件中,以便分析运行状态和定位bug。因此我们都需要有一个日志库,简单而强大。

或许很多人都自己写过日志类,支持多线程写入,支持自定义存放目录,支持日志等级控制,支持文件前缀自定义,支持每天生成一个文件,支持日志文件最大大小控制等等。。。

这里就介绍一下google的日志库glog,主要是翻译了官网的说明文档。


如何使用google日志库(glog)

引言

google glog是一个实现应用级日志的库,提供了基于c++风格的流式和辅助宏的API接口。你可以简单地通过流式操作使用LOG(level)来记录日志,例如:

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

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

 

google glog定义了一系列宏来简化许多常用的日志操作。你可以使用日志等级来控制所需要记录的日志信息,可以使用命令行来控制日志行为,可以基于条件来记录日志,可以在预设条件不满足的时候终止程序,可以引进你自己的详细日志等级等等。本文描述的就是glog所提供的功能,但是请注意,本文并不是对glog库的所有特性进行详尽描述,而是只对最常用的特性进行描述。如果你想知道一些不是很常用的特性,那么请查看src/glog目录下的头文件。

严重等级

在使用过程中,你可以指定以下几种严重等级之一(严重级别以递增的方式): INFO,WARNING,ERROR和FATAL。当一个fatal级别的日志被记录后,程序将会被终止。需要注意的是,一个指定严重级别的日志不单单会在同等严重级别的日志文件中记录,同时也会在所有低于该等级的日志文件中记录。例如,一个fatal级别的日志会记录在fatal、error、warning或info级别的日志文件中。

DFATAL级别是在debug模式(即,没有定义NDEBUG宏)下的FATAL级别错误,但是却可以在生产环境中通过自动降级为ERROR级别来避免程序被终止。

除了额外指定外,glog默认会将日志写入到以下这个路径中
/tmp/program name.hostname.user name.log.severity level.date.time.pid (例如: “/tmp/hello_world.example.com.hamaji.log.INFO.20080709-222411.10474”)。
默认情况下,glog除了会将ERROR或FATAL级别的错误写入到日志文件中,同时也会将这两个级别的日志复制到标准错误输出中。

设置标志

有几种标志可以影响到glog的输出行为。如果你的电脑中安装了google gflags库,当你使用命令行的方式将标志传递给程序时,configure脚本会自动检测并使用这些标志。例如,如果你想使用–logtostderr标志,那么可以像下面这样来运行你的程序:

./your_application --logtostderr=1

 

如果你没有安装google gflags库,那么你可以通过环境变量来设置标志,但是标志名称必须以”GLOG_”开头,例如:

GLOG_logtostderr=1 ./your_application

 

以下是最常用的几种标志:

logtostderr (bool, default=false)

将日志输出到stderr,而不是输出到日志文件
注意:你可以使用1、true或yes来将二进制标志设置成true。同样,你可以使用0、false或no来将二进制标志设置为false。

stderrthreshold (int, default=2, which is ERROR)

将等于或高于该严重等级的日志复制到stderr,而不是日志文件。INFO、WARNING、ERROR和FATAL严重级别分别对应着0、1、2和3。

minloglevel (int, default=0, which is INFO)

记录等于或高于该严重级别的日志信息。同样,INFO、WARNING、ERROR和FATAL严重级别分别对应着0、1、2和3。

log_dir (string, default=””)

调用该函数后,日志将会保存在指定的目录,而不是默认目录

v (int, default=0)

显示所有VLOG(m)中所有小于或等于m严重等级的信息。可以通过–vmodule进行重写。具体内容可以查看关于日志详细记录部分。

vmodule (string, default=””)

指定每个模块的日志级别。参数必须使用[module name]=[log level]的形式,并且中间以逗号进行分隔。[module name]其实可以是一个通配格式(例如,gfs*其实代表的是所有以gfs开头的模块),根据文件名来匹配(但是却跳过了文件名中的某些后缀 .cc/.//-inl.h)。[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";

 

条件型/临时型日志

有些时候,你可能想在某些条件成立的时候才去记录日志。在这种情况下,你可以使用下面这样的方式来达到目的:

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

 

上面代码表示的意思是,在变量num_cookies大于10的时候记录一条”Got lots of cookies”日志。有时候某行代码被执行多次,但是我们想在执行次数超过某个值时记录一条日志。这种情况,我们可以使用下面这种方式来记录:

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次调用时就输出一条日志的情况,我们也是可以通过限定最多输出前面多少次日志:

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

 

上面的处理是,当最先20次发生时才会输出日志,同样,次数是由google::COUNTER来计算的。

调试模式支持

“debug mode”日志宏只会在调试模式下才能生效,非调试模式下就没有任何日志输出。使用这些宏可以避免由于过度的日志输出导致的程序性能下降。

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宏提供了在条件不满足时终止程序的能力,就像标准C库中的assert宏一样。

当某个条件不为true时,CHECK宏会终止程序运行。但是它不像assert宏,它不受非debug模式的控制,所以不管在何种模式下都会有效果。因此,在下面这个例子中,fp->Write(x)是一直有效的:

CHECK(fp->Write(x) == 4) << "Write failed!";

 

除了上面说的check宏,还有一些用于检查等于/不等于的宏 - CHECK_EQ, CHECK_NE, CHECK_LE, CHECK_LT, CHECK_GE, and CHECK_GT.这些宏都是比较两个参数值的,当结果不满足预想条件时将会记录一条FATAL错误日志,同时会将两个比较变量的值也记录在日志中,但是前提是两个比较变量值类型必须支持操作符<<。

通过下面这样使用,你可以在日志文件中增加一条日志:

CHECK_NE(1, 2) << ": The world must be ending!";

 

我们非常小心谨慎去确保每个参数都被检查一次,因此所有能够作为函数的合法参数对象在这里都是合法的。特别是,参数可能是临时变量参数表达式。例如:

CHECK_EQ(string("abc")[1], 'b');

 

如果其中一个参数是指针,而另外一个却是NULL的话,编译器会报告一个错误。为了能够正常工作,可以简单地调用static_cast将NULL转换为对应类型指针。

CHECK_EQ(some_ptr, static_cast<SomeType*>(NULL));

 

更好的是,我们可以使用CHECK_NOTNULL宏:

CHECK_NOTNULL(some_ptr);
some_ptr->DoSomething();

 

由于该宏返回的是一个已存在的指针,所以这个宏构造函数初始化列表中非常有用。

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

 

但是要注意的是,你不能使用该宏来作为C++流。请使用上面描述的CHECK_EQ宏来在终止程序前进行日志记录。

如果你正在比较string值,那么这里也有一系列的宏可以使用 - CHECK_STREQ, CHECK_STRNE, CHECK_STRCASEEQ, and CHECK_STRCASENE. 而CASE版本是区分大小写的,你可以非常放心地将NULL指针传递给这些宏,他们会将NULL和非NULL字符串判断为不相等的,而两个NULL就判断为相等。

注意,两个参数都可能是一个由函数返回的临时字符串。

CHECK_DOUBLE_EQ宏用来检查两个浮点数值是否相等,并且允许两个值有很小的误差。CHECK_NEAR却能接收第三个浮点数,同时也是允许存在一个小的误差值。

详细记录

当你在跟踪调试一个很复杂的bug,那么详细的日志信息是很有帮助的。但是你可能又想在非开发环境下避免输出这些太详细的日志。对于详细日志,glog提供了VLOG宏,这个宏允许你自定义自己的日志等级。使用命令行参数–v可以控制输出哪些详细日志。

VLOG(1) << "I'm printed when you run the program with --v=1 or higher";
VLOG(2) << "I'm printed when you run the program with --v=2 or higher";

 

在使用VLOG的时候,我们定义详细日志等级越低,那么将会有更多的可能信息将会被输出到日志文件中。例如,如果我们调用VLOG的时候设置–v==1,那么VLOG(1)将会记录日志,但是VLOG(2)将不会被记录日志。这个和严重等级刚好是相反的。

每一个模块都能通过命令行控制详细日志的输出:

--vmodule=mapreduce=2,file=1,gfs*=3 --v=0

 

以上命令行参数指定了一系列的输出等级:

  • a.mapreduce模块中的VLOG(2)或者更低级别日志将会被输出
  • b.文件中的VLOG(1)或者更低级别的日志将会被输出
  • c.前缀为gfs的文件中VLOG(3)或者更低级别的日志将会被输出
  • d.其他情况下的VLOG(0)或更低级别日志将会被输出

以上显示了可以使用通配符,不但支持*号通配,同时也支持?通配符。

这里也有基于条件的宏VLOG_IS_ON(n),当参数–v参数值等于或者大于n时,该宏将会返回true值。例如下面使用方式:

if (VLOG_IS_ON(2)) {
// do some logging preparation and logging
// that can't be accomplished with just VLOG(2) << ...;
}

 

详细级别的条件宏VLOG_IF, VLOG_EVERY_N和VLOG_IF_EVERY_N,他们的功能表现类似于LOG_IF, LOG_EVERY_N和LOF_IF_EVERY,但是他们接受一个数字型的详细等级而不是严重等级。

VLOG_IF(1, (size > 1024))
<< "I'm printed when size is more than 1024 and when you run the "
"program with --v=1 or more";
VLOG_EVERY_N(1, 10)
<< "I'm printed every 10th occurrence, and when you run the program "
"with --v=1 or more. Present occurence is " << google::COUNTER;
VLOG_IF_EVERY_N(1, (size > 1024), 10)
<< "I'm printed on every 10th occurence of case when size is more "
" than 1024, when you run the program with --v=1 or more. ";
"Present occurence is " << google::COUNTER;

 

失败信号处理

该库提供了一个方便的程序异常信号处理器,就是当程序出现异常信号(例如SIGSEGV)出现时,该库会将有用程序的有用信息都转储出来。该信号处理器可以通过google::InstallFailureSignalHandler()进行安装。下面代码就是该异常信号处理器的输出内容例子:

*** Aborted at 1225095260 (unix time) try "date -d @1225095260" if you are using GNU date ***
*** SIGSEGV (@0x0) received by PID 17711 (TID 0x7f893090a6f0) from PID 0; stack trace: ***
PC: @ 0x412eb1 TestWaitingLogSink::send()
@ 0x7f892fb417d0 (unknown)
@ 0x412eb1 TestWaitingLogSink::send()
@ 0x7f89304f7f06 google::LogMessage::SendToLog()
@ 0x7f89304f35af google::LogMessage::Flush()
@ 0x7f89304f3739 google::LogMessage::~LogMessage()
@ 0x408cf4 TestLogSinkWaitTillSent()
@ 0x4115de main
@ 0x7f892f7ef1c4 (unknown)
@ 0x4046f9 (unknown)

 

默认情况下,该异常处理器会将异常信息都输出到标准错误输出中。你可以通过InstallFailureWriter()来自定义异常信息输出目标。

其他注意项

消息性能

glog中提供的条件日志宏在使用过程中需要小心,因为当条件false的时候,右边表达式并不会被执行。

CHECK(obj.ok) << obj.CreatePrettyFormattedStringButVerySlow();

 

自定义失败处理函数

FATAL严重级别日志和未满足条件的CHECK宏都会终止你的程序,但是你可以通过InstallFailureFunction函数来修改终止的行为。

void YourFailureFunction() {
// Reports something...
exit(1);
}

int main(int argc, char* argv[]) {
google::InstallFailureFunction(&YourFailureFunction);
}

 

默认情况下,glog会尝试将堆栈信息都转存出来,并设置程序退出码为1.当然,这个堆栈跟踪的前提是你的程序支持才行。

原始日志

文件中定义了线程安全的日志操作,这些操作不会申请任何的内存或获取任何的锁。因此,在这个头文件中定义的这些宏能够用于低级别的内存申请和同步代码。具体请查看src/glog/raw_logging.h中的代码。

google风格的perror()

PLOG()、PLOG_IF()和PCHECK()的表现与LOG*、CHECK非常相似。例如

PCHECK(write(1, NULL, 2) >= 0) << "Write NULL failed";

 

条件检查失败的日志输出如下格式:

F0825 185142 test.cc:22] Check failed: write(1, NULL, 2) >= 0 Write NULL failed: Bad address [14]

 

Syslog

SYSLOG, SYSLOG_IF和SYSLOG_EVERY_N这几个宏都是可以使用的,而这些syslog日志是对普通日志的一个增加。但是要注意,syslog系列日志操作会对性能有较大影响,特别是当syslog用于远程记录日志时。在你使用这些宏之前,确保你已经明确了解了这些宏的含义。一般来说,谨慎使用这些宏是明智的选择。

windows用户须知

google的glog定义了一个严重级别ERROR,这个级别宏同事也在windows.h文件中定义了。你在通过在包含glog/logging.h之前定义宏GLOG_NO_ABBREVIATED_SEVERITIES,这样就能使得glog不去定义INFO, WARNING, ERROR和FATAL这几个宏了。就算使用了这个宏,你还是可以想日志工具一样使用iostream。

#define GLOG_NO_ABBREVIATED_SEVERITIES
#include <windows.h>
#include <glog/logging.h>

// ...

LOG(ERROR) << "This should work";
LOG_IF(ERROR, x > y) << "This should be also OK";

但是,在使用glog/logging.h中定义的函数的时候,你再也不能使用这个宏(INFO, WARNING, ERROR,FATAL)了。

#define GLOG_NO_ABBREVIATED_SEVERITIES
#include <windows.h>
#include <glog/logging.h>

// ...

// This won't work.
// google::FlushLogFiles(google::ERROR);

// Use this instead.
google::FlushLogFiles(google::GLOG_ERROR);

如果你不需要使用windows.h中定义的ERROR宏,这里还有几种方法可以实现的:

* #define WIN32_LEAN_AND_MEAN or NOGDI before you #include windows.h .
* #undef ERROR after you #include windows.h .

 

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM