Apollo程式碼解析:2. log系統google glog
Apollo中的glog
在Apollo中google glog 被廣泛使用,glog 是 google 的一個 c++ 開源日誌系統,輕巧靈活,入門簡單,而且功能也比較完善。
1. 安裝
以下是官方的安裝方法,一句命令:
git clone https://github.com/google/glog.git
cd glog
./autogen.sh && ./configure && make && make install
2. 使用
2.1 菜鳥級
從一個最簡單的程式開始:
#include <glog/logging.h>
int main(int argc,char* argv[])
{
google::InitGoogleLogging(argv[0]); //初始化 glog
LOG(INFO) << "Hello,GOOGLE!";
}
編譯:
1. glog g++ glog_test2.cpp -lglog -lgflags -lpthread -o glog_test #編譯
2. glog ./glog_test
3. glog ll /tmp #ll是小寫的L
4. glog cat /tmp/glog_test.INFO
這裡 g++ 編譯的時候注意連結的庫是要按順序的(我也是才知道)。gcc 和 g++ 中庫的連結順序是從右往左進行,所以要把最基礎實現的庫放在最後,這樣左邊的 lib 就可以呼叫右邊的 lib 中的程式碼。
一開始沒注意順序出現各種找不到函式,用 nm -C
定位了好久。而且這裡我必須再連結上 gflags 才能成功編譯,看網上其他人都沒有。如果有大神知道為什麼麻煩帶帶我。
這裡沒有指定日誌檔案的目錄,預設會放在 /tmp 下,檔名的格式為 <program name>.<hostname>.<user name>.log.<severity level>.<date>.<time>.<pid>
。
2.2 新手級
日誌檔案的位置可以通過 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
glog ll log
這裡可以看到,我們通過 log_dir 指定了日誌存放目錄。而這裡雖然我們沒有輸出 WARNING 級別的日誌資訊,但卻有該級別的日誌。看一下分別是什麼:
glog cd log
log cat glog_test.ERROR
log cat glog_test.WARNING
log cat glog_test.INFO
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
我們可以看到,指定了 -v 50 後,只有小於等於 50 的 VLOG 及正常 LOG(INFO) 資訊被打印出來。如果你問如果不指定會怎樣,回答就是一條 VLOG 資訊都不會出現。
2.3進階版
如果你以為這裡還有進階版介紹的話,我只能向你表示抱歉。我的使用只是簡單級別,目前專案也沒有必要更復雜的 glog 介面。
當然,我們也可以像其他部落格把 glog 的功能全列出來:
- 引數設定,以命令列引數的方式設定標誌引數來控制日誌記錄行為
- 嚴重性分級,根據日誌嚴重性分級記錄日誌
- 可有條件地記錄日誌資訊
- 條件中止程式。豐富的條件判定巨集,可預設程式終止條件
- 異常訊號處理。程式異常情況,可自定義異常處理過程
- 支援debug功能。可只用於debug模式
- 自定義日誌資訊
- 執行緒安全日誌記錄方式
- 系統級日誌記錄
- google perror風格日誌資訊
- 精簡日誌字串資訊