Golang glog使用詳解


golang/glog 是 C++ 版本 google/glog 的 Go 版本實現,基本實現了原生 glog 的日志格式。在 Kuberntes 中,glog 是默認日志庫。

glog 的使用與特性

通用功能

glog 將日志級別分為 4 種,分別是:

  • INFO:普通日志;
  • WARNING:告警日志;
  • ERROR:錯誤日志;
  • FATAL:嚴重錯誤日志,打印完日志后程序將會推出(os.Exit()

glog 的使用很簡單,可參考下面這個例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import (
"flag"

"github.com/golang/glog"
)

func main() {
flag.Parse()
defer glog.Flush()

glog.Info("This is info message")
glog.Infof("This is info message: %v", 12345)
glog.InfoDepth(1, "This is info message", 12345)

glog.Warning("This is warning message")
glog.Warningf("This is warning message: %v", 12345)
glog.WarningDepth(1, "This is warning message", 12345)

glog.Error("This is error message")
glog.Errorf("This is error message: %v", 12345)
glog.ErrorDepth(1, "This is error message", 12345)

glog.Fatal("This is fatal message")
glog.Fatalf("This is fatal message: %v", 12345)
glog.FatalDepth(1, "This is fatal message", 12345)
}

當我們運行:

1
$ mkdir -p log && go run main.go -log_dir=log -alsologtostderr

以上打印日志將會同時打印在 log/ 目錄和標准錯誤輸出中(-alsologtostderr)。

其中在 log/ 中將會產生如下日志文件:

1
2
3
4
5
6
7
8
main.INFO -> main.ut1.test.log.INFO.20180715-130428.27339
main.WARNING -> main.ut1.test.log.WARNING.20180715-130428.27339
main.ERROR -> main.ut1.test.log.ERROR.20180715-130428.27339
main.FATAL -> main.ut1.test.log.FATAL.20180715-130428.27339
main.ut1.test.log.ERROR.20180715-130428.27339
main.ut1.test.log.FATAL.20180715-130428.27339
main.ut1.test.log.INFO.20180715-130428.27339
main.ut1.test.log.WARNING.20180715-130428.27339

其中 main.INFO 這類文件表示的是 INFO 日志對應的符號鏈接。當單個日志文件達到一定大小時,glog 將會有 rotate 的動作:即關閉已經滿量的文件,新建日志文件

vmodule 功能

glog 最常用的就是 V level 的功能,如下所示:

1
2
3
4
5
6
7
8
9
func main() {
flag.Parse()
defer glog.Flush()

glog.V(3).Info("LEVEL 3 message") // 使用日志級別 3
glog.V(4).Info("LEVEL 4 message") // 使用日志級別 4
glog.V(5).Info("LEVEL 5 message") // 使用日志級別 5
glog.V(8).Info("LEVEL 8 message") // 使用日志級別 8
}

當我們重新運行:

1
$ go run main.go -log_dir=log -alsologtostderr

將不會看到任何輸出,因為日志級別不夠,我們通過指定日志級別(-v,log level):

1
$ go run main.go -v=4 -log_dir=log -alsologtostderr

此時,日志級別小於或等於 4 的日志將被打印出來:

1
2
I0715 13:15:41.380611   29471 main.go:13] LEVEL 3 message
I0715 13:15:41.388777 29471 main.go:14] LEVEL 4 message

如果我們想對不同的文件實行不同的日志級別,可以用 vmodule 功能,如下代碼:

1
2
3
4
5
6
7
8
9
10
func main() {
flag.Parse()
defer glog.Flush()

bar()
glog.V(3).Info("LEVEL 3 message")
glog.V(4).Info("LEVEL 4 message")
glog.V(5).Info("LEVEL 5 message")
glog.V(8).Info("LEVEL 8 message")
}

其中 bar() 的實現在 bar.go

1
2
3
func bar() {
glog.V(4).Info("LEVEL 4: level 4 message in bar.go")
}

當我們執行:

1
$ go run main.go bar.go -v=3 -log_dir=log -alsologtostderr -vmodule=bar=5

對所有文件的日志級別設定為 3 (-v=3),但是對 bar.go (-vmodule 的輸入參數省去 .go 后綴,且必須以 -vmodule=recordio=2,file=1,gfs*=3 的語法格式)的日志級別設定為 5,此時會輸出:

1
2
I0715 13:20:28.381611   30447 bar.go:6] LEVEL 4: level 4 message in bar.go
I0715 13:20:28.383866 30447 main.go:14] LEVEL 3 message

通過該功能,可以對指定模塊采用不同日志級別的輸出,可有效提升調試效率。

traceLocation 功能

traceLocation 的命令格式為 -log_backtrace_at=gopherflakes.go:234,當運行到指定代碼處時,將把該代碼的棧信息打印出來,延續上面的代碼,我們運行:

1
$ go run main.go bar.go -v=3 -log_dir=log -alsologtostderr -vmodule=bar=5 -log_backtrace_at=bar.go:6

可見如下輸出:

1
2
3
I0715 13:28:17.915837   31920 bar.go:6] LEVEL 4: level 4 message in bar.go
... 打印 backtrace,此處省略 ...
I0715 13:28:17.923715 31920 main.go:14] LEVEL 3 message

日志格式

從上面的例子可以看出,glog 打印的日志基本格式為:

1
<header>] <message>

header 和 message 之間用 ] 分隔。其中 header 的格式為:

1
Lmmdd hh:mm:ss.uuuuuu threadid file:line

這里要注意的是 L,它代表了 glog 原本的日志級別:

1
2
3
4
I -> INFO
W -> WARNING
E -> ERROR
F -> FATAL

后面幾個字段分別代表的是時間信息。在 C++ 中,threadid 表示的是線程信息,但在 Go 版本實現中,threadid 是進程 PID,即 os.Getpid() 的調用結果。

這部分詳細代碼可參考:glog.go 中的 formatHeader() 函數。

glog 的實現

其實,用 Go 實現一個日志庫並不困難,其本質就是:在 buffer 中寫入格式化的內容並定期刷入文件中。glog 的基本實現邏輯也是如此。

參考

  1. 深入學習 Go 語言函數調用信息
  2. An example of how to use golang/glog


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM