glog和gflag是工程中常常用到的兩個(gè)google的開源庫(kù),在這里一起介紹一下一些基本的用法。
1. Google glog
參考:官方文檔
glog全稱是Google Logging Library,是google的開源日志系統(tǒng),它輕巧靈活且功能完善,實(shí)現(xiàn)了程序級(jí)別的日志管理。
Google glog定義了一系列宏來簡(jiǎn)化日志工作。你可以:
- 按嚴(yán)重級(jí)別記錄日志
- 通過命令行管理日志行為
- 基于條件記錄日志
- 當(dāng)預(yù)期條件沒有達(dá)到時(shí)終止程序
- 引入自定義日志級(jí)別
#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";
}
1.1. 嚴(yán)重級(jí)別(Severity Level)
Glog所支持的日志級(jí)別包括:INFO、WARNING、ERROR和FATAL。當(dāng)記錄一個(gè)FATAL級(jí)別的日志后,程序會(huì)自動(dòng)終止。要注意的是,給定級(jí)別的信息不僅會(huì)記錄在該級(jí)別的日志里,也會(huì)記錄在更低級(jí)別的日志里。
FATAL級(jí)別的日志僅在debug模式下(沒有定義NDEBUG宏時(shí))才會(huì)記錄FATAL錯(cuò)誤,在生產(chǎn)過程中,則會(huì)自動(dòng)降級(jí)為ERROR以避免程序自動(dòng)終止。
除非另外聲明,glog會(huì)默認(rèn)將日志記錄在/tmp/<program name>.<hostname>.<user name>.log.<severity level>.<date>.<time>.<pid>路徑下,例如 /tmp/hello_world.example.com.hamaji.log.INFO.20080709-222411.10474。默認(rèn)情況下,glog也會(huì)另外將ERROR和FATAL級(jí)別的信息輸出至標(biāo)準(zhǔn)錯(cuò)誤。
1.2. 設(shè)置標(biāo)簽(Flags)
如果電腦上也安裝了Google gflags library,那configure腳本也會(huì)自動(dòng)檢測(cè)并使用它,這將允許你通過命令行傳輸標(biāo)簽。例如:
./your_application --logtostderr=1
如果沒安裝gflags,則可以通過環(huán)境變量設(shè)置標(biāo)簽,比如:
GLOG_logtostderr=1 ./your_application
在程序里面,則可以通過修改全局變量FLAGS_*來修改標(biāo)簽,比如:
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";
常見的標(biāo)簽有:
-
logtostderr(bool):輸出至標(biāo)準(zhǔn)錯(cuò)誤。 -
stderrthreshold(int,默認(rèn)為2):復(fù)制級(jí)別大于設(shè)定值的的日志至標(biāo)準(zhǔn)錯(cuò)誤。 -
minloglevel(int,默認(rèn)為0) -
log_dir(string):日志文件輸出的路徑。
1.3. 按條件記錄
- 按判斷條件篩選:
LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
- 每隔多少輸出一個(gè):
LOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
- 輸出前N個(gè):
LOG_FIRST_N(INFO, 20) << "Got the " << google::COUNTER << "th cookie";
1.4. CHECK宏
在程序中,定期檢查結(jié)果是否符合預(yù)期是及早發(fā)現(xiàn)錯(cuò)誤的好方式。CHECK宏提供了中斷程序的方式,類似于assert。
CHECK會(huì)在條件為假時(shí)終止程序,不同于assert,其不會(huì)受到NDEBUG選項(xiàng)影響。
舉例:
CHECK(fp->Write(x) == 4) << "Write failed!";
CHECK_NE(1, 2) << ": The world must be ending!";
CHECK_NOTNULL(some_ptr);
1.5. Verbose Logging
VLOG宏允許你自定義不同級(jí)別的日志并通過--v選項(xiàng)管理。
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";
此外--vmodule選項(xiàng)可以控制不同模塊的日志情況:
--vmodule=mapreduce=2,file=1,gfs*=3 --v=0
將會(huì):
- Print VLOG(2) and lower messages from mapreduce.{h,cc}
- Print VLOG(1) and lower messages from file.{h,cc}
- Print VLOG(3) and lower messages from files prefixed with "gfs"
- Print VLOG(0) and lower messages from elsewhere
此外還有VLOG_IS_ON(n)宏、VLOG_IF、VLOG_EVERY_N、VLOG_IF_EVERY_N等。
1.6. 錯(cuò)誤信息處理
可以使用google::InstallFailureSignalHandler()來啟用,錯(cuò)誤信息舉例:
*** 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)
2. Google gflag
參考:官方文檔
gflags是google使用的一個(gè)開源庫(kù),用于解析命令行標(biāo)記。
2.1. 下載安裝
git clone https://github.com/gflags/gflags.git
2.2. 定義Flags
示例:
#include <gflags/gflags.h>
DEFINE_bool(big_menu, true, "Include 'advanced' options in the menu listing");
DEFINE_string(languages, "english,french,german",
"comma-separated list of languages to offer in the 'lang' menu");
支持的flags類型:DEFINE_bool,DEFINE_int32,DEFINE_int64,DEFINE_uint64,DEFINE_double,DEFINE_string。
這些宏需要三個(gè)參數(shù):標(biāo)記的名字、默認(rèn)值、說明。說明可以通過--help選項(xiàng)顯示。
Flag只要定義一次,可以在頭文件中聲明(例如DECLARE_bool(big_menu)),這樣其他的源文件可以通過include這個(gè)頭文件來使用同樣的flag。
注意大多數(shù)函數(shù)定義在google命名空間中。
2.3. 使用Flags
所有定義的flags都可以在程序中像正常的變量一樣使用,只要添加前綴FLAGS_。
例如:
if (FLAGS_consider_made_up_languages)
FLAGS_languages += ",klingon"; // implied by --consider_made_up_languages
if (FLAGS_languages.find("finnish") != string::npos)
HandleFinnish();
2.4. 解析命令行中的Flags
通常在main()中使用:
gflags::ParseCommandLineFlags(&argc, &argv, true);
其中最后一個(gè)參數(shù)決定是否從argv中移除flags,并修改argc。
這樣,可以在程序調(diào)用的時(shí)候控制flags:
./app_containing_foo --nobig_menu -languages="chinese,japanese,korean" ...