1. 程式人生 > >Apollo程式碼解析:2. log系統google glog

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風格日誌資訊
  • 精簡日誌字串資訊