1.logrus特色
golang標準庫的日誌框架很簡單,logrus框架的特色:
1)徹底兼容標準日誌庫
六種日誌級別:debug, info, warn, error, fatal, panic
2)可擴展的Hook機制
容許使用者經過Hook的方式將日誌分發到任意地方,如本地文件系統,logstash,elasticsearch或者mq等,或者經過Hook定義日誌內容和格式等
3)可選的日誌輸出格式
內置了兩種日誌格式JSONFormater和TextFormatter,還能夠自定義日誌格式
4)Field機制
經過Filed機制進行結構化的日誌記錄
5)線程安全git
logrus不提供的功能以下:
1)沒有提供行號和文件名的支持
2)輸出到本地文件系統沒有提供日誌分割功能
3)沒有提供輸出到ELK等日誌處理中心的功能
這些功能均可以經過自定義hook來實現github
2.使用示例golang
package main import ( log "github.com/sirupsen/logrus" ) func main() { log.WithFields(log.Fields{ "animal": "walrus", }).Info("a walrus appears") }
運行結果:redis
time="2019-01-24T18:43:57+08:00" level=info msg="a walrus appears" animal=walrus
3.設置log的參數api
func init(){ log.SetFormatter(&log.JSONFormatter{}) log.SetOutput(os.Stdout) log.SetLevel(log.InfoLevel) }
運行結果:安全
{"animal":"walrus","level":"info","msg":"a walrus appears","time":"2019-01-24T18:51:00+08:00"}
4.建立Logger實例
logrus有一個默認的Logger
當一個應用中,須要向多個地方輸出時,須要不一樣的Logger實例app
var log = logrus.New()
可使用以上語句,建立Logger實例框架
package main import ( "github.com/sirupsen/logrus" "os" ) var log = logrus.New() func main() { file ,err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666) if err == nil{ log.Out = file }else{ log.Info("Failed to log to file") } log.WithFields(logrus.Fields{ "filename": "123.txt", }).Info("打開文件失敗") }
運行結果:
logrus.log文件elasticsearch
time="2019-01-24T19:02:21+08:00" level=info msg="打開文件失敗" filename=123.txt
5.Fields
1)做用
結構化信息記錄,傳統的記錄方式如:函數
log.Fatalf("Failed to send event %s to topic %s with key %d", event, topic, key)
在logrus中不提倡這樣寫,鼓勵使用Fields結構化日誌內容,如:
log.WithFields(log.Fields{ "event": event, "topic": topic, "key": key, }).Fatal("Failed to send event")
2)固定Fields
能夠固定Fields不用每次都寫
package main import ( "github.com/sirupsen/logrus" ) var log = logrus.New() func main() { entry := logrus.WithFields(logrus.Fields{ "name": "test", }) entry.Info("message1") entry.Info("message2") }
運行結果:
time="2019-01-24T19:04:51+08:00" level=info msg=message1 name=test time="2019-01-24T19:04:51+08:00" level=info msg=message2 name=test
6.hook
hook的原理是,在logrus寫入日誌時攔截,修改logrus.Entry
type Hook interface { Levels() []Level Fire(*Entry) error }
使用示例:
自定義一個hook DefaultFieldHook,在全部級別的日誌消息中加入默認字段appName="myAppName"
type DefaultFieldHook struct { } func (hook *DefaultFieldHook) Fire(entry *log.Entry) error { entry.Data["appName"] = "MyAppName" return nil } func (hook *DefaultFieldHook) Levels() []log.Level { return log.AllLevels }
在初始化時,調用logrus.AddHook(hook)
添加響應的hook便可
7.記錄文件名和行號
8.日誌文件本地分割
經過hook插件file-rotatelogs進行日誌本地文件分割
import ( "github.com/lestrrat-go/file-rotatelogs" "github.com/rifflock/lfshook" log "github.com/sirupsen/logrus" "time" ) func newLfsHook(logLevel *string, maxRemainCnt uint) log.Hook { writer, err := rotatelogs.New( logName+".%Y%m%d%H", // WithLinkName爲最新的日誌創建軟鏈接,以方便隨着找到當前日誌文件 rotatelogs.WithLinkName(logName), // WithRotationTime設置日誌分割的時間,這裏設置爲一小時分割一次 rotatelogs.WithRotationTime(time.Hour), // WithMaxAge和WithRotationCount兩者只能設置一個, // WithMaxAge設置文件清理前的最長保存時間, // WithRotationCount設置文件清理前最多保存的個數。 //rotatelogs.WithMaxAge(time.Hour*24), rotatelogs.WithRotationCount(maxRemainCnt), ) if err != nil { log.Errorf("config local file system for logger error: %v", err) } level, ok := logLevels[*logLevel] if ok { log.SetLevel(level) } else { log.SetLevel(log.WarnLevel) } lfsHook := lfshook.NewHook(lfshook.WriterMap{ log.DebugLevel: writer, log.InfoLevel: writer, log.WarnLevel: writer, log.ErrorLevel: writer, log.FatalLevel: writer, log.PanicLevel: writer, }, &log.TextFormatter{DisableColors: true}) return lfsHook }
9.日誌文件發送到elasticsearch
將logrus日誌發送到elasticsearch的原理是在hook的每次fire調用時,使用golang的es客戶端將日誌信息寫入elasticsearch
import ( "github.com/olivere/elastic" "gopkg.in/sohlich/elogrus" ) func initLog() { client, err := elastic.NewClient(elastic.SetURL("http://localhost:9200")) if err != nil { log.Panic(err) } hook, err := elogrus.NewElasticHook(client, "localhost", log.DebugLevel, "mylog") if err != nil { log.Panic(err) } log.AddHook(hook) }
10.將日誌發送到其餘位置
logrus_amqp:Logrus hook for Activemq。 logrus-logstash-hook:Logstash hook for logrus。 mgorus:Mongodb Hooks for Logrus。 logrus_influxdb:InfluxDB Hook for Logrus。 logrus-redis-hook:Hook for Logrus which enables logging to RELK stack (Redis, Elasticsearch, Logstash and Kibana)。
11.Fatal處理 和不少日誌框架同樣,logrus的Fatal系列函數會執行os.Exit(1)。可是logrus提供能夠註冊一個或多個fatal handler函數的接口logrus.RegisterExitHandler(handler func() {} ),讓logrus在執行os.Exit(1)以前進行相應的處理。fatal handler能夠在系統異常時調用一些資源釋放api等,讓應用正確的關閉。