介绍
Google glog是一个应用层的库. 它提供基于C++风格的流和多种宏接口.例如:
#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定义了一系列的宏处理普通的日志工作. 你可以分级记录, control loggingbehavior from the command line, 按条件记录, abort theprogram when expected conditions are not met, introduce your ownverbose logging levels, 及其它. 文本只是简单的介绍了常用的glog功能而不是所有的细节.没介绍到的,自己读代码去吧.
严重等级
严重等级包括(按严重程度排序):
INFO
,WARNING
,ERROR
,和FATAL
.记录一个FATAL
级的错误后会自动终止程序执行(其实就是_asm int 3).一个严重等级高的记录不但记录在它自己的文件,也记录在比它低等的文件里.例如, 一个FATAL
级的记录将会记在
FATAL
,ERROR
,WARNING
, 和INFO
等级的日志里.在debug状态下
FATAL
级记录也可以用DFATAL
(当没定义NDEBUG
宏的时候),发给客户的程序最好不要用FATAL小心客户对你使用_asm int 3,这时ERROR
是个不错的选择.
glog默认把日志文件命名为"/tmp/...log...."(例如, "/tmp/hello_world.example.com.hamaji.log.INFO.20080709-222411.10474").glog默认把
ERROR
和FATAL
级的记录发送一份到stderr.
设置标志
标志可以改变glog的输出行为.如果你安装了Googlegflags library,
configure
脚本 (具体请参考它的INSTALL文件)会自动检测并使用标志,这时你可以通过命令行使用标志.例如, 若你想发送--logtostderr
标志,像下面这样:./your_application --logtostderr=1如果你没装Google gflags library,你就只能用带GLOG_的环境变量实现,例如.GLOG_logtostderr=1 ./your_application (貌似在Windows里不能这样用吧?)
常用的标志有:
-
写日志到stderr而不是日志文件.
Note: you can set binary flags totrue
by specifying1
,true
, oryes
(caseinsensitive).Also, you can set binary flags tofalse
by specifying0
,false
, orno
(again, caseinsensitive). -
-
将某级及以上级别的记录同时发送到stderr和日志文件. 严重等级
INFO
,WARNING
,ERROR
,FATAL
分别对应 0, 1, 2, 3. -
- 只记录某级及以上级别的记录.
-
- 指定日志保存的目录.
-
-
Show all
VLOG(m)
messages form
less orequal the value of this flag. Overridable by --vmodule.See the section about verbose logging for moredetail. -
-
Per-module verbose level. The argument has to contain acomma-separated list of =.is a glob pattern (e.g.,
gfs*
for all modules whose namestarts with "gfs"), matched against the filename base(that is, name ignoring .cc/.h./-inl.h). overrides any value given by --v.See also the section about verbose logging.
logtostderr
(
bool
, default=
false
)
stderrthreshold
(
int
, default=2, whichis
ERROR
)
minloglevel
(
int
, default=0, whichis
INFO
)
log_dir
(
string
, default="")
v
(
int
, default=0)
vmodule
(
string
, default="")
还有一些其它的标志,自己去logging.cc里面搜索"DEFINE_",爷就不多说了.
你也可以在程序里修改FLAGS_*
开头的全局变量. 通常设置FLAGS_*
开头的变量会立即生效,和日志文件名或路径相关的变量例外.例如FLAGS_log_dir
就不能放在google::InitGoogleLogging
后面.例子代码:
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";条件/ Occasional Logging
下面的宏用于根据条件写日志:
LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";只有当num_cookies > 10的时候才会记录"Got lots of cookies"如果有的代码执行非常频繁,你肯定不会希望每次都写入日志.这时,你可以使用下面的方法:
LOG_EVERY_N(INFO, 10) < Got the googleCOUNTER th cookiepre>上面的代码只有当第1次,第11次,第21次....执行时才写入日志.Note that the special
google::COUNTER
value is used to identify which repetition ishappening.条件和计次可以混合使用,例如:
LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << google::COUNTER << "th big cookie";除了间隔N次输出,还可以只输出前M次,例如:
LOG_FIRST_N(INFO, 20) < Got the googleCOUNTER th cookiepre>只输出前20次.
Debug mode支持
"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
宏就是干这个滴,它的功能和assert
一样,条件不符合时终止程序.与
assert
不同的是它*不*受NDEBUG
的限制,无论是不是debug编译它都执行.所以下面的fp-<Write(x)
会被执行:CHECK(fp->Write(x) == 4) << "Write failed!";有各种各样的宏用于CHECK相等/不相等,包括:
CHECK_EQ
,CHECK_NE
,CHECK_LE
,CHECK_LT
,CHECK_GE
,和CHECK_GT
.它们会记录一个FATAL
级的记录到日志,牛X的是他们还会把对比的两个值也一起记录.(那两个值必须定义了operator< ostreamcode> )
.例如:
CHECK_NE(1, 2) << ": The world must be ending!";We are very careful to ensure that each argument is evaluated exactlyonce, and that anything which is legal to pass as a function argument islegal here. In particular, the arguments may be temporary expressionswhich will end up being destroyed at the end of the apparent statement,for example:
CHECK_EQ(string("abc")[1], 'b');The compiler reports an error if one of the arguments is apointer and the other is NULL. To work around this, simply static_castNULL to the type of the desired pointer.
CHECK_EQ(some_ptr, static_cast(NULL));还有个好办法:用CHECK_NOTNULL宏:
CHECK_NOTNULL(some_ptr); some_ptr-<DoSomething();这宏也常用于构造函数中.
struct S { S(Something* ptr) : ptr_(CHECK_NOTNULL(ptr)) {} Something* ptr_; };这宏的缺点是不能跟C++流一起用.这时就得用
CHECK_EQ
了.如果你要对比一个C字符串(char *)可以用:
CHECK_STREQ
,CHECK_STRNE
,CHECK_STRCASEEQ
,和CHECK_STRCASENE
.带CASE的区分大小写. 这个宏参数可以用NULL
指针.NULL
与non-NULL
比不等.两个NULL
是相等的.Note that both arguments may be temporary strings which aredestructed at the end of the current "full expression"(e.g.,
CHECK_STREQ(Foo().c_str(), Bar().c_str())
whereFoo
andBar
return C++'sstd::string
).
CHECK_DOUBLE_EQ
用于对比浮点数,会有小小的误差.CHECK_NEAR
可以接受一个浮点数作为误差.详细日志
用
VLOG
宏,你还可以定义自己的严重等级. The--v
command line option controlswhich verbose messages are logged: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";With
VLOG
, the lower the verbose level, the morelikely messages are to be logged. For example, if--v==1
,VLOG(1)
will log, butVLOG(2)
will not log. This is opposite of the severitylevel, whereINFO
is 0, andERROR
is 2.--minloglevel
of 1 will logWARNING
andabove. Though you can specify any integers for bothVLOG
macro and--v
flag, the common values for them are smallpositive integers. For example, if you writeVLOG(0)
,you should specify--v=-1
or lower to silence it. Thisis less useful since we may not want verbose logs by default in mostcases. TheVLOG
macros always log at theINFO
log level (when they log at all).Verbose logging can be controlled from the command line on aper-module basis:
--vmodule=mapreduce=2,file=1,gfs*=3 --v=0will:
- a. Print VLOG(2) and lower messages from mapreduce.{h,cc}
- b. Print VLOG(1) and lower messages from file.{h,cc}
- c. Print VLOG(3) and lower messages from files prefixed with "gfs"
- d. Print VLOG(0) and lower messages from elsewhere
The wildcarding functionality shown by (c) supports both '*'(matches 0 or more characters) and '?' (matches any single character)wildcards. Please also check the section about command line flags.
There's also VLOG_IS_ON(n)
"verbose level" conditionmacro. This macro returns true when the --v
is equal orgreater than n
. To be used as
if (VLOG_IS_ON(2)) { // do some logging preparation and logging // that can't be accomplished with just VLOG(2) << ...; }Verbose level condition macros
VLOG_IF
,VLOG_EVERY_N
andVLOG_IF_EVERY_N
behaveanalogous toLOG_IF
,LOG_EVERY_N
,LOF_IF_EVERY
, but accept a numeric verbosity level asopposed to a severity level.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;Failure Signal Handler
The library provides a convenient signal handler that will dump usefulinformation when the program crashes on certain signals such as SIGSEGV.The signal handler can be installed bygoogle::InstallFailureSignalHandler(). The following is an example of outputfrom the signal handler.
*** 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)By default, the signal handler writes the failure dump to the standarderror. You can customize the destination by InstallFailureWriter().
Miscellaneous Notes
Performance of Messages
The conditional logging macros provided by glog (e.g.,
CHECK
,LOG_IF
,VLOG
, ...) arecarefully implemented and don't execute the right hand sideexpressions when the conditions are false. So, the following checkmay not sacrifice the performance of your application.CHECK(obj.ok) << obj.CreatePrettyFormattedStringButVerySlow();User-defined Failure Function
FATAL
severity level messages or unsatisfiedCHECK
condition terminate your program. You can changethe behavior of the termination byInstallFailureFunction
.void YourFailureFunction() { // Reports something... exit(1); } int main(int argc, char* argv[]) { google::InstallFailureFunction(&YourFailureFunction); }By default, glog tries to dump stacktrace and makes the programexit with status 1. The stacktrace is produced only when you run theprogram on an architecture for which glog supports stack tracing (asof September 2008, glog supports stack tracing for x86 and x86_64).
Raw Logging
The header file
can beused for thread-safe logging, which does not allocate any memory oracquire any locks. Therefore, the macros defined in thisheader file can be used by low-level memory allocation andsynchronization code.Please check
src/glog/raw_logging.h.in
for detail.Google Style perror()
PLOG()
andPLOG_IF()
andPCHECK()
behave exactly like theirLOG*
andCHECK
equivalents with the addition that they append adescription of the current state of errno to their output lines.E.g.PCHECK(write(1, NULL, 2) <= 0) < Write NULL failedpre>This check fails with the following error message.
F0825 185142 test.cc:22] Check failed: write(1, NULL, 2) <= 0 Write NULL failed: Bad address [14]Syslog
SYSLOG
,SYSLOG_IF
, andSYSLOG_EVERY_N
macros are available.These log to syslog in addition to the normal logs. Be aware thatlogging to syslog can drastically impact performance, especially ifsyslog is configured for remote logging! Make sure you understand theimplications of outputting to syslog before you use these macros. Ingeneral, it's wise to use these macros sparingly.Strip Logging Messages
Strings used in log messages can increase the size of your binaryand present a privacy concern. You can therefore instruct glog toremove all strings which fall below a certain severity level by usingthe GOOGLE_STRIP_LOG macro:
If your application has code like this:
#define GOOGLE_STRIP_LOG 1 // this must go before the #include! #include <glog/logging.h>The compiler will remove the log messages whose severities are lessthan the specified integer value. Since
VLOG
logs at the severity levelINFO
(numeric value0
),settingGOOGLE_STRIP_LOG
to 1 or greater removesall log messages associated withVLOG
s as well asINFO
log statements.对于Windows用户
glog的
ERROR
级错误与windows.h
冲突. You can make glog not defineINFO
,WARNING
,ERROR
,andFATAL
by definingGLOG_NO_ABBREVIATED_SEVERITIES
beforeincludingglog/logging.h
. Even with this macro, you canstill use the iostream like logging facilities:#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";However, you cannotuse
INFO
,WARNING
,ERROR
,andFATAL
anymore for functions definedinglog/logging.h
.#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);If you don't need
ERROR
definedbywindows.h
, there are a couple of more workaroundswhich sometimes don't work:
- #define
WIN32_LEAN_AND_MEAN
orNOGDI
before you #includewindows.h
. - #undef
ERROR
after you #includewindows.h
.
See this issue for more detail.