程序中記錄日誌的首要目的:Troubleshooting。經過記錄程序中對外部系統與模塊的依賴調用、重要狀態信息的變化、關鍵變量、關鍵邏輯等,顯示基於時間軸的程序運行軌跡,顯示業務是否正常、是否存在非預期執行,在出問題時方便還原現場,推斷程序運行過程、理清問題的方向。git
本文將討論在實現日誌功能過程當中常見的一些問題,包括基礎API、格式化、日誌轉發及可視化等方面,代碼採用Go語言描述。github
一、後臺輸出golang
package main import ( "fmt" ) func main(){ fmt.Println("------hello world-----") }
二、There are no exceptions in Golang, only errors.bash
Go語言不支持傳統的 try…catch…finally 這種異常,由於Go語言的設計者們認爲,將異常與控制結構混在一塊兒會很容易使得代碼變得混亂。由於開發者很容易濫用異常,甚至一個小小的錯誤都拋出一個異常,替代方案是使用多值返回來返回錯誤。固然Go並非全面否認異常的存在,或者用recover+panic語法實現,只是極力不鼓勵多用異常。tcp
package main import ( "log" "errors" "fmt" ) func main() { /* local variable definition */ ... /* function for division which return an error if divide by 0 */ ret,err = div(a, b) if err != nil { log.Fatal(err) } fmt.Println(ret) }
三、寫入日誌文件:ide
package main import ( "log" "os" ) func main(){ f,err :=os.OpenFile("test.log",os.O_WRONLY|os.O_CREATE|os.O_APPEND,0644) if err !=nil{ log.Fatal(err) } defer f.Close() log.SetOutput(f) log.Println("==========works==============") }
YRMacBook-Pro:go-log yanrui$ more test.log 2017/05/24 21:46:25 ==========works==============
推薦日誌工具庫:logrus工具
$ go get github.com/Sirupsen/logrus
一、JSON formatui
package main import ( log "github.com/Sirupsen/logrus" "github.com/logmatic/logmatic-go" ) func main() { // use JSONFormatter log.SetFormatter(&logmatic.JSONFormatter{}) // log an event as usual with logrus log.WithFields(log.Fields{"string": "foo", "int": 1, "float": 1.1 }).Info("My first ssl event from golang") }
日誌輸出樣式:設計
{ "@marker":["sourcecode","golang"], "date":"2017-05-24T15:27:40+08:00", "float":1.1,"int":1,"level":"info", "message":"My first ssl event from golang", "string":"foo" }
經過logrus庫能夠加入一些上下文信息,例如:主機名稱,程序名稱或者會話參數等。日誌
contextLogger := log.WithFields(log.Fields{ "common": "XXX common content XXX", "other": "YYY special context YYY", }) contextLogger.Info("AAAAAAAAAAAA") contextLogger.Info("BBBBBBBBBBBB")
日誌輸出樣式:
YRMacBook-Pro:go-log yanrui$ go run LogMatic.go {"@marker":["sourcecode","golang"],"common":"XXX common content XXX","date":"2017-05-24T17:00:08+08:00","level":"info","message":"AAAAAAAAAAAA","other":"YYY special context YYY"} {"@marker":["sourcecode","golang"],"common":"XXX common content XXX","date":"2017-05-24T17:00:08+08:00","level":"info","message":"BBBBBBBBBBBB","other":"YYY special context YYY"} YRMacBook-Pro:go-log yanrui$
咱們還能夠利用Hook機制實現日誌功能擴展,例如Syslog hook,將輸出的日誌發送到指定的Syslog服務。
package main import ( log "github.com/sirupsen/logrus" "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake" logrus_syslog "github.com/sirupsen/logrus/hooks/syslog" "log/syslog" ) func main(){ hook, err := logrus_syslog.NewSyslogHook("udp", "59.37.0.1:514", syslog.LOG_INFO, "") if err != nil { log.Error("Unable to connect to local syslog daemon") } else { log.AddHook(hook) } }
驗證是否發送Syslog:
$ sudo tcpdump | grep 59.37.0.1 tcpdump: data link type PKTAP tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on pktap, link-type PKTAP (Apple DLT_PKTAP), capture size 262144 bytes 18:51:05.663612 IP 192.168.199.15.58819 > 59.37.0.1.syslog: SYSLOG kernel.info, length: 314 18:51:05.663657 IP 192.168.199.15.58819 > 59.37.0.1.syslog: SYSLOG kernel.info, length: 314
在真實場景中日誌數據體量很是龐大,日誌存儲只是第一步,更多的狀況是須要查看特定指標或者可以快速檢索信息,此時日誌分析平臺就發揮做用了。以logmatic爲例,能夠在它的官網註冊https://logmatic.io/,免費體驗。
在使用logmatic以前,須要下載它的hook支持:
$ go get github.com/logmatic/logmatic-go
func main() { // instantiate a new Logger with your Logmatic APIKey // 國內訪問比較慢 log.AddHook(logmatic.NewLogmaticHook("p53uTkOhSEqI3-116DynkQ")) // .......... }
效果以下:
更多精彩內容掃碼關注公衆號:RiboseYim's Blog:https://riboseyim.github.io