一、glog是什么:
Google glog是一個基於程序級記錄日志信息的c++庫,編程使用方式與c++的stream操作類似,例:
LOG(INFO) << "Found " << num << " cookies";
“LOG”宏為日志輸出關鍵字,“INFO”為嚴重性程度。
主要支持功能:
1, 參數設置,以命令行參數的方式設置標志參數來控制日志記錄行為;
2, 嚴重性分級,根據日志嚴重性分級記錄日志;
3, 可有條件地記錄日志信息;
4, 條件中止程序。豐富的條件判定宏,可預設程序終止條件;
5, 異常信號處理。程序異常情況,可自定義異常處理過程;
6, 支持debug功能。可只用於debug模式;
7, 自定義日志信息;
8, 線程安全日志記錄方式;
9, 系統級日志記錄;
10, google perror風格日志信息;
11, 精簡日志字符串信息。
二、下載安裝
1.下載:https://github.com/google/glog/releases
2.解壓安裝
tar zxvf glog-0.3.3.tar && cd glog-0.3.3 && ./configure && make && make install
三、glog的主要內容
1.日志等級
1)系統預定義等級:INFO(=0)<WARNING(=1)<ERROR(=2)<FATAL(=3)以上是簡寫形式,可通過宏關閉簡寫形式,其原始定義是有GLOG_前綴.
在windows中可能存在ERROR宏沖突的問題,通過宏監測會在編譯器提示.
2)最嚴重級別是FATAL級別,對應DEBUG模式是DFATAL級別
2.1)在輸出FATAL日志消息后,會終止程序運行.
2.2)DEBUG模式中,DFATAL級別對應ERROR--便於調試,而非 DEBUG模式則對應FATAL.
3)每個級別都對應有相應的日志文件,日志文件的位置及名稱定義如下:
3.1)文件默認存放在臨時文件中,windows下為 "C:\Users\user_name\AppData\Local\Temp",Linux是"/tmp"
3.2)文件名稱: programname.hostname.user_name.log.severity_level.dat e.time.pid
3.3)Linux系還會為每個文件創建一個文件鏈接
4)日志輸出采用如下規則:
4.1)每個級別的日志除了輸出到對應日志文件中,還輸出到每個低級別日志文件中
4.2)如一個ERROR日志,會輸出到INFO,WARNING,ERROR三個日志文件中
4.3)默認,ERROR和FATAL消息除了輸出到日志文件中之外,還會輸出到標准錯誤中
2.DEBUG模式支持
1)DEBUG模式日志輸出形式,增加前綴D表示DEBUG模式日志,如DLOG(log_severity),DLOG_IF(log_severity,condition)
2)采用DEBUG宏控制,非DEBUG模式中DEBUG日志不會編譯進程序就避免了程序冗余
3.豐富的助手宏
功能類似assert斷言,但不受DEBUG模式控制即非DEBUG模式也生效.如果驗證失敗,會寫FATAL日志並終止程序運行.
1)比較驗證
CHECK_EQ(arg1,arg2)
CHECK_NE(arg1,arg2)
CHECK_LE(arg1,arg2)
CHECK_LT(arg1,arg2)
CHECK_GE(arg1,arg2)
CHECK_GT(arg1,arg2)
2)CHECK_NOTNULL(arg)
3)字符串比較
CHECK_STREQ
CHECK_STRNE
CHECK_STRCASEEQ
CHECK_STRCASENE
4.特定的信息處理
1)針對可能導致程序崩潰的信號會輸出dump信息
2)處理的信號包括:SIGSEGV,SIGILL,SIGABRT,SIGBUS,SIGTERM
3)相關函數:
google::InstallFailureSignalHandler() ,信號處理函數。
google::InstallFailureWriter(void (writer)(const char data,int size)) 默認dump信息輸出到STDERR,可通過該函數定制dump輸出目標。
5.日志類型
LOG //內置日志
VLOG //自定義日志
DLOG //DEBUG模式可輸出的日志
DVLOG //DEBUG模式可輸出的自定義日志
SYSLOG //系統日志,同時通過 syslog() 函數寫入到/var/log/message 文件
PLOG //perror風格日志,設置errno狀態並輸出到日志中
RAW_LOG //線程安全的日志,需要#include <glog/raw_logging.h>
6.幾個常用參數
FLAGS_logtostderr = true; // 設置日志消息是否轉到標准輸出而不是日志文件
FLAGS_alsologtostderr = true; // 設置日志消息除了日志文件之外是否去標准輸出
FLAGS_colorlogtostderr = true; // 設置記錄到標准輸出的顏色消息(如果終端支持)
FLAGS_log_prefix = true; // 設置日志前綴是否應該添加到每行輸出
FLAGS_logbufsecs = ; // 設置可以緩沖日志的最大秒數,0指實時輸出
FLAGS_max_log_size = ; // 設置最大日志文件大小(以MB為單位)
FLAGS_stop_logging_if_full_disk = true; // 設置是否在磁盤已滿時避免日志記錄到磁盤
7.幾個常用函數
google::SetLogDestination(google::INFO, "log/INFO_"); // 設置特定嚴重級別的日志的輸出目錄和前綴。第一個參數為日志級別,第二個參數表示輸出目錄及日志文件名前綴
google::SetLogFilenameExtension("logExtension"); // 在日志文件名中級別后添加一個擴展名。適用於所有嚴重級
google::SetStderrLogging(google::INFO); // 大於指定級別的日志都輸出到標准輸出
google::InstallFailureSignalHandler(); // 將 coredumped 信息輸出到 stderr
四、自定義日志打印格式
要自定義glog輸出格式並不難,可以直接修改logging.cc文件中的LogMessage::Init函數,修改的位置:
glog大部分常用功能在該文件中實現,可通過修改該文件來實現自己想要的功能
if (FLAGS_log_prefix && (line != kNoLogPrefix)) { stream() << LogSeverityNames[severity][0] << setw(2) << 1+data_->tm_time_.tm_mon << setw(2) << data_->tm_time_.tm_mday << ' ' << setw(2) << data_->tm_time_.tm_hour << ':' << setw(2) << data_->tm_time_.tm_min << ':' << setw(2) << data_->tm_time_.tm_sec << "." << setw(6) << usecs << ' ' << setfill(' ') << setw(5) << static_cast<unsigned int>(GetTID()) << setfill('0') << ' ' << data_->basename_ << ':' << data_->line_ << "] "; } 修改這個地方的格式
五、簡單示例(使用默認配置)
1 #include <iostream> 2 #include <glog/logging.h> 3 4 int main(int argc, char** argv) { 5 google::InitGoogleLogging(argv[0]); 6 LOG(INFO) << "Hello,GOOGLE!"; 7 }
編譯執行:
g++ test.cpp -lglog -lgflags ./a.out 默認生成路徑為/tmp,cd進入/tmp目錄,可以看到生成了兩個文件: a.out.INFO a.out.test.yanghao.log.INFO.20171208-095841.12698
六、增加嚴重度的種類
將系統中用來統計profile的日志單獨打印到一個日志文件中,以便於定位問題與分析性能問題,所以我增加了一個LOG(PROFILE)的日志格式
修改以下源碼部分(修改后記得重新編譯):
src/logging.cc:337: "INFO", "WARNING", "ERROR", "FATAL", "PROFILE" src/glog/logging.h:418:#define COMPACT_GOOGLE_LOG_PROFILE google::LogMessage( \ src/glog/logging.h:419: __FILE__, __LINE__, google::GLOG_PROFILE) src/glog/logging.h:420:#define LOG_TO_STRING_PROFILE(message) google::LogMessage( \ src/glog/logging.h:421: __FILE__, __LINE__, google::GLOG_PROFILE, message) src/glog/logging.h:423:#define COMPACT_GOOGLE_LOG_PROFILE google::NullStream() src/glog/logging.h:424:#define LOG_TO_STRING_PROFILE(message) google::NullStream() src/glog/logging.h:466:#define GOOGLE_LOG_PROFILE(counter) \ src/glog/logging.h:467: google::LogMessage(__FILE__, __LINE__, google::GLOG_PROFILE, counter, \ src/glog/logging.h:469:#define SYSLOG_PROFILE(counter) \ src/glog/logging.h:470: google::LogMessage(__FILE__, __LINE__, google::GLOG_PROFILE, counter, \ src/glog/logging.h.in:418:#define COMPACT_GOOGLE_LOG_PROFILE @ac_google_namespace@::LogMessage( \ src/glog/logging.h.in:419: __FILE__, __LINE__, @ac_google_namespace@::GLOG_PROFILE) src/glog/logging.h.in:420:#define LOG_TO_STRING_PROFILE(message) @ac_google_namespace@::LogMessage( \ src/glog/logging.h.in:421: __FILE__, __LINE__, @ac_google_namespace@::GLOG_PROFILE, message) src/glog/logging.h.in:423:#define COMPACT_GOOGLE_LOG_PROFILE @ac_google_namespace@::NullStream() src/glog/logging.h.in:424:#define LOG_TO_STRING_PROFILE(message) @ac_google_namespace@::NullStream() src/glog/logging.h.in:466:#define GOOGLE_LOG_PROFILE(counter) \ src/glog/logging.h.in:467: @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_PROFILE, counter, \ src/glog/logging.h.in:469:#define SYSLOG_PROFILE(counter) \ src/glog/logging.h.in:470: @ac_google_namespace@::LogMessage(__FILE__, __LINE__, @ac_google_namespace@::GLOG_PROFILE, counter, \ src/glog/log_severity.h:47:const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3, GLOG_PROFILE = 4, src/glog/log_severity.h:54: ERROR = GLOG_ERROR, FATAL = GLOG_FATAL, PROFILE = GLOG_PROFILE;
測試:
#include <iostream> #include <glog/logging.h> #include <cstdlib> int main(int argc, char** argv) { google::InitGoogleLogging(argv[0]); // create logpath std::string str_des; str_des.append("mkdir -p "); str_des.append("log"); system(str_des.c_str()); // INFO std::string str_info; str_info.append("./log"); str_info.append("/INFO_"); google::SetLogDestination(google::INFO, str_info.c_str()); // WARNING std::string str_warn; str_warn.append("./log"); str_warn.append("/WARNING_"); google::SetLogDestination(google::WARNING, str_warn.c_str()); LOG(WARNING) << "The is a warning!"; // my own type std::string str_pro; str_pro.append("./log"); str_pro.append("/PROFILE_"); google::SetLogDestination(google::WARNING, str_pro.c_str()); LOG(WARNING) << "The is my own type!"; // stop glog google::ShutdownGoogleLogging();
編譯執行: g++ -g test.cpp -lglog -lgflags && ./a.out 之后在該目錄下會生成一個log目錄 a.out log test.cpp cd log a.out.INFO a.out.WARNING a.out.PROFILE INFO_20171208-151843.18256 PROFILE_20171208-151843.18256 WARNING_20171208-151843.18256 打開PROFILE_20171208-151843.18256 1 Log file created at: 2017/12/08 15:18:43 2 Running on machine: test 3 Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg 4 W1208 15:18:43.879918 18256 test.cpp:28] The is my own type! 如果系統長時間運行,可以設置日志文件的大小,當文件超過該限制后就會重新生成一個新的log文件,glog有提供該功能
glog在Mac上可能存在打印線程號錯誤的情況, 此時修改glog源代碼中的utilities.cc文件中的GetTID()接口,將最后一行 return (pid_t)(uintptr_t)pthread_self();改為 return ::pthread_mach_thread_np(pthread_self());
參考鏈接:
