google glog 簡單使用小結
glog 是 google 的一個 c++ 開源日誌系統,輕巧靈活,入門簡單,而且功能也比較完善。
安裝
以下是官方的安裝方法,一句命令:
➜ code git clone https://github.com/google/glog.git
➜ code cd glog
➜ glog git:(master) ✗ ./configure && make && make install
然而我出現了 N 個錯誤,以下是兩個編譯的錯誤:
錯誤記錄:
Issue1: 出現 aclocal-1.14: command not found
recipe for target 'aclocal.m4' failed
的錯誤提示。 解決方法:
➜ glog git:(master) ✗ sudo apt-get install automake
➜ glog git:(master) ✗ sudo autoreconf -ivf
Issue2:之後出現另一個錯誤:error: expected initializer before 'Demangle'
。
解決方法:
➜ code cd glog
➜ glog git:(master) ✗ mkdir build && cd build
➜ build git:(master) ✗ export CXXFLAGS="-fPIC" && cmake .. && make VERBOSE=1
➜ build git:(master) ✗ make
➜ build git:(master) ✗ sudo make install
使用
菜鳥級
從一個最簡單的程式開始:
#include <glog/logging.h>
int main(int argc,char* argv[])
{
google::InitGoogleLogging(argv[0]); //初始化 glog
LOG(INFO) << "Hello,GOOGLE!" ;
}
編譯:
➜ glog g++ glog_test2.cpp -lglog -lgflags -lpthread -o glog_test #編譯
➜ glog ./glog_test
➜ glog ll /tmp # 預設日誌在 /tmp 下
total 28K
-rw-rw-r-- 1 angryrookie angryrookie 193 7月 3 22:04 glog_test.cheng.angryrookie.log.INFO.20160703-220405.6569
lrwxrwxrwx 1 angryrookie angryrookie 57 7月 3 22:04 glog_test.INFO -> glog_test.cheng.angryrookie.log.INFO.20160703-220405.6569
➜ glog cat /tmp/glog_test.INFO
Log file created at: 2016/07/03 22:04:05
Running on machine: cheng
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
I0703 22:04:05.242153 6569 glog_test2.cpp:7] Hello,GLOG!
這裡 g++ 編譯的時候注意連結的庫是要按順序的(我也是才知道)。gcc 和 g++ 中庫的連結順序是從右往左進行,所以要把最基礎實現的庫放在最後,這樣左邊的 lib 就可以呼叫右邊的 lib 中的程式碼。
一開始沒注意順序出現各種找不到函式,用 nm -C
定位了好久。而且這裡我必須再連結上 gflags 才能成功編譯,看網上其他人都沒有。如果有大神知道為什麼麻煩帶帶我。
這裡沒有指定日誌檔案的目錄,預設會放在 /tmp 下,檔名的格式為 <program name>.<hostname>.<user name>.log.<severity level>.<date>.<time>.<pid>
。我們再看一下程式碼打印出的日誌資訊:
I0703 22:04:05.242153 6569 glog_test2.cpp:7] Hello,GLOG!
這一行資訊對應的分別是:I+日期 時:分:秒.微秒 執行緒號 原始檔名:行數] 資訊
,這些資訊對定位問題,做統計都很有效,可以根據具體專案來做分析。
新手級
日誌檔案的位置可以通過 gflags 命令列引數 log_dir 來指定,這時注意在 main 函式開始時初始化 gflags: google::ParseCommandLineFlags(&argc, &argv, true);
,也可以直接在程式碼裡 指定 FLAGS_log_dir
的值。這裡還是推薦標準的做法,即用命令列引數。
glog 的日誌會根據日誌嚴重性分級記錄日誌,標準的分級為:INFO, WARNING, ERROR, FATAL。不同級別的日誌資訊會輸出到不同檔案,同時高級別的日誌也會寫入到低級別中。
再看個例子:
#include <glog/logging.h>
int main(int argc,char* argv[])
{
google::InitGoogleLogging(argv[0]); // 初始化 glog
google::ParseCommandLineFlags(&argc, &argv, true); // 初始化 gflags
LOG(INFO) << "Hello, GOOGLE!"; // INFO 級別的日誌
LOG(ERROR) << "ERROR, GOOGLE!"; // ERROR 級別的日誌
return 0;
}
再次編譯執行:
➜ glog g++ glog_test2.cpp -lglog -lgflags -lpthread -o glog_test
➜ glog mkdir log # 建一個目錄放日誌檔案
➜ glog ./glog_test -log_dir=./log
E0703 22:59:13.380125 6867 glog_test2.cpp:8] ERROR, GOOGLE! # 這裡 ERROR 級別的日誌還作為 stderr 輸出了到控制檯
➜ glog ll log
total 16K
-rw-rw-r-- 1 angryrookie angryrookie 196 7月 3 22:59 glog_test.cheng.angryrookie.log.ERROR.20160703-225913.6867
-rw-rw-r-- 1 angryrookie angryrookie 257 7月 3 22:59 glog_test.cheng.angryrookie.log.INFO.20160703-225913.6867
-rw-rw-r-- 1 angryrookie angryrookie 196 7月 3 22:59 glog_test.cheng.angryrookie.log.WARNING.20160703-225913.6867
lrwxrwxrwx 1 angryrookie angryrookie 58 7月 3 22:59 glog_test.ERROR -> glog_test.cheng.angryrookie.log.ERROR.20160703-225913.6867
lrwxrwxrwx 1 angryrookie angryrookie 57 7月 3 22:59 glog_test.INFO -> glog_test.cheng.angryrookie.log.INFO.20160703-225913.6867
lrwxrwxrwx 1 angryrookie angryrookie 60 7月 3 22:59 glog_test.WARNING -> glog_test.cheng.angryrookie.log.WARNING.20160703-225913.6867
這裡可以看到,我們通過 log_dir 指定了日誌存放目錄。而這裡雖然我們沒有輸出 WARNING 級別的日誌資訊,但卻有該級別的日誌。看一下分別是什麼:
➜ glog cd log
➜ log cat glog_test.ERROR
Log file created at: 2016/07/03 22:59:13
Running on machine: cheng
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0703 22:59:13.380125 6867 glog_test2.cpp:8] ERROR, GOOGLE!
➜ log cat glog_test.WARNING
Log file created at: 2016/07/03 22:59:13
Running on machine: cheng
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
E0703 22:59:13.380125 6867 glog_test2.cpp:8] ERROR, GOOGLE!
➜ log cat glog_test.INFO
Log file created at: 2016/07/03 22:59:13
Running on machine: cheng
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
I0703 22:59:13.379570 6867 glog_test2.cpp:7] Hello, GOOGLE!
E0703 22:59:13.380125 6867 glog_test2.cpp:8] ERROR, GOOGLE!
WARNING 級別的日誌裡放了 ERROR 的輸出資訊,這就是我們說的高級別的日誌會寫入到低級別中,而且是每個低級別。
還有一個常用的日誌輸出語句,即自定義日誌型別 VLOG。VLOG 的用法也很簡單,像這樣 VLOG(50) << "MY VLOG INFO";
。這裡的 50 只是自己定義的一個級別,事實上你可以定義任何一個數字,但一般越小的數字代表這條輸出日誌越重要。通過命令列引數 -v 50 這樣子來指定 VLOG 輸出的級別,-v 50 意味著只有小於 50 以下的 VLOG 才會被輸出(這裡不會影響 LOG(INFO)
這些)。一般專案裡越底層的庫使用越大數字的 VLOG 來列印除錯資訊,這樣可以使得日誌不會被一堆底層庫的執行資訊淹沒。
再看個例子:
#include <glog/logging.h>
int main(int argc,char* argv[])
{
google::InitGoogleLogging(argv[0]);
google::ParseCommandLineFlags(&argc, &argv, true);
LOG(INFO) << "Hello, GOOGLE!";
VLOG(100) << "VLOG INFO 100";
VLOG(50) << "VLOG INFO 50";
VLOG(10) << "VLOG INFO 10";
return 0;
}
這裡我們有三條 VLOG 資訊,分別是 100 50 10 三個級別。VLOG 的資訊只會出現在 INFO 級別的日誌中:
➜ glog g++ glog_test3.cpp -lglog -lgflags -lpthread -o glog_test
➜ glog ./glog_test -log_dir=./log -v 50
➜ glog cat log/glog_test.INFO
Log file created at: 2016/07/03 23:24:32
Running on machine: cheng
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
I0703 23:24:32.225793 7046 glog_test3.cpp:7] Hello, GOOGLE!
I0703 23:24:32.226384 7046 glog_test3.cpp:9] VLOG INFO 50
I0703 23:24:32.226410 7046 glog_test3.cpp:10] VLOG INFO 10
我們可以看到,指定了 -v 50 後,只有小於等於 50 的 VLOG 及正常 LOG(INFO) 資訊被打印出來。如果你問如果不指定會怎樣,回答就是一條 VLOG 資訊都不會出現。
進階版
如果你以為這裡還有進階版介紹的話,我只能向你表示抱歉。我的使用只是簡單級別,目前專案也沒有必要更復雜的 glog 介面。
當然,我們也可以像其他部落格把 glog 的功能全列出來:
- 引數設定,以命令列引數的方式設定標誌引數來控制日誌記錄行為
- 嚴重性分級,根據日誌嚴重性分級記錄日誌
- 可有條件地記錄日誌資訊
- 條件中止程式。豐富的條件判定巨集,可預設程式終止條件
- 異常訊號處理。程式異常情況,可自定義異常處理過程
- 支援debug功能。可只用於debug模式
- 自定義日誌資訊
- 執行緒安全日誌記錄方式
- 系統級日誌記錄
- google perror風格日誌資訊
- 精簡日誌字串資訊
這是文件傳送門:文件