Go第三方日誌庫logrus

更新、更全的《Go從入門到放棄》的更新網站,更有python、go、人工智能教學等着你:http://www.javashuo.com/article/p-mxrjjcnn-hn.htmlpython

日誌是程序中必不可少的一個環節,因爲Go語言內置的日誌庫功能比較簡潔,咱們在實際開發中一般會選擇使用第三方的日誌庫來進行開發。本文介紹了logrus這個日誌庫的基本使用。git

1、logrus介紹

Logrus是Go(golang)的結構化logger,與標準庫logger徹底API兼容。github

它有如下特色:golang

  • 徹底兼容標準日誌庫,擁有七種日誌級別:Trace, Debug, Info, Warning, Error, Fataland Panic
  • 可擴展的Hook機制,容許使用者經過Hook的方式將日誌分發到任意地方,如本地文件系統,logstash,elasticsearch或者mq等,或者經過Hook定義日誌內容和格式等
  • 可選的日誌輸出格式,內置了兩種日誌格式JSONFormater和TextFormatter,還能夠自定義日誌格式
  • Field機制,經過Filed機制進行結構化的日誌記錄
  • 線程安全

2、安裝

go get github.com/sirupsen/logrus

3、基本示例

使用Logrus最簡單的方法是簡單的包級導出日誌程序:json

package main

import (
  log "github.com/sirupsen/logrus"
)

func main() {
  log.WithFields(log.Fields{
    "animal": "dog",
  }).Info("一條舔狗出現了。")
}

4、進階示例

對於更高級的用法,例如在同一應用程序記錄到多個位置,你還能夠建立logrus Logger的實例:安全

package main

import (
  "os"
  "github.com/sirupsen/logrus"
)

// 建立一個新的logger實例。能夠建立任意多個。
var log = logrus.New()

func main() {
  // 設置日誌輸出爲os.Stdout
  log.Out = os.Stdout

  // 能夠設置像文件等任意`io.Writer`類型做爲日誌輸出
  // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
  // if err == nil {
  //  log.Out = file
  // } else {
  //  log.Info("Failed to log to file, using default stderr")
  // }

  log.WithFields(logrus.Fields{
    "animal": "dog",
    "size":   10,
  }).Info("一羣舔狗出現了。")
}

5、日誌級別

Logrus有七個日誌級別:Trace, Debug, Info, Warning, Error, Fataland Panicbash

log.Trace("Something very low level.")
log.Debug("Useful debugging information.")
log.Info("Something noteworthy happened!")
log.Warn("You should probably take a look at this.")
log.Error("Something failed but I'm not quitting.")
// 記完日誌後會調用os.Exit(1) 
log.Fatal("Bye.")
// 記完日誌後會調用 panic() 
log.Panic("I'm bailing.")

5.1 設置日誌級別

你能夠在Logger上設置日誌記錄級別,而後它只會記錄具備該級別或以上級別任何內容的條目:併發

// 會記錄info及以上級別 (warn, error, fatal, panic)
log.SetLevel(log.InfoLevel)

若是你的程序支持debug或環境變量模式,設置log.Level = logrus.DebugLevel會頗有幫助。app

6、字段

Logrus鼓勵經過日誌字段進行謹慎的結構化日誌記錄,而不是冗長的、不可解析的錯誤消息。

例如,區別於使用log.Fatalf("Failed to send event %s to topic %s with key %d"),你應該使用以下方式記錄更容易發現的內容:

log.WithFields(log.Fields{
  "event": event,
  "topic": topic,
  "key": key,
}).Fatal("Failed to send event")

WithFields的調用是可選的。

7、默認字段

一般,將一些字段始終附加到應用程序的所有或部分的日誌語句中會頗有幫助。例如,你可能但願始終在請求的上下文中記錄request_iduser_ip

區別於在每一行日誌中寫上log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip}),你能夠向下面的示例代碼同樣建立一個logrus.Entry去傳遞這些字段。

requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})
requestLogger.Info("something happened on that request") # will log request_id and user_ip
requestLogger.Warn("something not great happened")

8、日誌條目

除了使用WithFieldWithFields添加的字段外,一些字段會自動添加到全部日誌記錄事中:

  • time:記錄日誌時的時間戳
  • msg:記錄的日誌信息
  • level:記錄的日誌級別

9、Hooks

你能夠添加日誌級別的鉤子(Hook)。例如,向異常跟蹤服務發送ErrorFatalPanic、信息到StatsD或同時將日誌發送到多個位置,例如syslog。

Logrus配有內置鉤子。在init中添加這些內置鉤子或你自定義的鉤子:

import (
  log "github.com/sirupsen/logrus"
  "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake"
  logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
  "log/syslog"
)

func init() {

  // Use the Airbrake hook to report errors that have Error severity or above to
  // an exception tracker. You can create custom hooks, see the Hooks section.
  log.AddHook(airbrake.NewHook(123, "xyz", "production"))

  hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
  if err != nil {
    log.Error("Unable to connect to local syslog daemon")
  } else {
    log.AddHook(hook)
  }
}

意:Syslog鉤子還支持鏈接到本地syslog(例如. 「/dev/log」 or 「/var/run/syslog」 or 「/var/run/log」)。有關詳細信息,請查看syslog hook README

10、格式化

logrus內置如下兩種日誌格式化程序:

logrus.TextFormatter logrus.JSONFormatter

還支持一些第三方的格式化程序,詳見項目首頁。

11、記錄函數名

若是你但願將調用的函數名添加爲字段,請經過如下方式設置:

log.SetReportCaller(true)

這會將調用者添加爲」method」,以下所示:

{"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by",
"time":"2014-03-10 19:57:38.562543129 -0400 EDT"}
```

注意:,開啓這個模式會增長性能開銷。

線程安全

默認的logger在併發寫的時候是被mutex保護的,好比當同時調用hook和寫log時mutex就會被請求,有另一種狀況,文件是以appending mode打開的, 此時的併發操做就是安全的,能夠用logger.SetNoLock()來關閉它。

gin框架使用logrus

// a gin with logrus demo

var log = logrus.New()

func init() {
    // Log as JSON instead of the default ASCII formatter.
    log.Formatter = &logrus.JSONFormatter{}
    // Output to stdout instead of the default stderr
    // Can be any io.Writer, see below for File example
    f, _ := os.Create("./gin.log")
    log.Out = f
    gin.SetMode(gin.ReleaseMode)
    gin.DefaultWriter = log.Out
    // Only log the warning severity or above.
    log.Level = logrus.InfoLevel
}

func main() {
    // 建立一個默認的路由引擎
    r := gin.Default()
    // GET:請求方式;/hello:請求的路徑
    // 當客戶端以GET方法請求/hello路徑時,會執行後面的匿名函數
    r.GET("/hello", func(c *gin.Context) {
        log.WithFields(logrus.Fields{
            "animal": "walrus",
            "size":   10,
        }).Warn("A group of walrus emerges from the ocean")
        // c.JSON:返回JSON格式的數據
        c.JSON(200, gin.H{
            "message": "Hello world!",
        })
    })
    // 啓動HTTP服務,默認在0.0.0.0:8080啓動服務
    r.Run()
}
logger.SetNoLock()// a gin with logrus demo var log = logrus.New() func init() { // Log as JSON instead of the default ASCII formatter. log.Formatter = &logrus.JSONFormatter{} // Output to stdout instead of the default stderr // Can be any io.Writer, see below for File example f, _ := os.Create("./gin.log") log.Out = f gin.SetMode(gin.ReleaseMode) gin.DefaultWriter = log.Out // Only log the warning severity or above. log.Level = logrus.InfoLevel } func main() { // 建立一個默認的路由引擎 r := gin.Default() // GET:請求方式;/hello:請求的路徑 // 當客戶端以GET方法請求/hello路徑時,會執行後面的匿名函數 r.GET("/hello", func(c *gin.Context) { log.WithFields(logrus.Fields{ "animal": "walrus", "size": 10, }).Warn("A group of walrus emerges from the ocean") // c.JSON:返回JSON格式的數據 c.JSON(200, gin.H{ "message": "Hello world!", }) }) // 啓動HTTP服務,默認在0.0.0.0:8080啓動服務 r.Run() }
相關文章
相關標籤/搜索