1. 程式人生 > >google glog 簡單使用小結

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  73 22:04 glog_test.cheng.angryrookie.log.INFO.20160703-220405.6569
lrwxrwxrwx 1 angryrookie angryrookie   57  73 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  73 22:59 glog_test.cheng.angryrookie.log.ERROR.20160703-225913.6867
-rw-rw-r-- 1 angryrookie angryrookie 257  73 22:59 glog_test.cheng.angryrookie.log.INFO.20160703-225913.6867
-rw-rw-r-- 1 angryrookie angryrookie 196  73 22:59 glog_test.cheng.angryrookie.log.WARNING.20160703-225913.6867
lrwxrwxrwx 1 angryrookie angryrookie  58  73 22:59 glog_test.ERROR -> glog_test.cheng.angryrookie.log.ERROR.20160703-225913.6867
lrwxrwxrwx 1 angryrookie angryrookie  57  73 22:59 glog_test.INFO -> glog_test.cheng.angryrookie.log.INFO.20160703-225913.6867
lrwxrwxrwx 1 angryrookie angryrookie  60  73 22:59 glog_test.WARNING -> glog_test.cheng.angryrookie.log.WARNING.20160703-225913.6867

這裡可以看到,我們通過 log_dir 指定了日誌存放目錄。而這裡雖然我們沒有輸出 WARNING 級別的日誌資訊,但卻有該級別的日誌。看一下分別是什麼:

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

這是文件傳送門:文件