## 结构化日志记录 记录日志的主要目的是便于在事件发生或过后检查系统的状态。当你有大量正在记录日志的微服务时,日志消息会很难梳理。 本节使用第三方库来对日志进行记录。 ### 实践 1. 获取第三方库: ``` go get github.com/sirupsen/logrus go get github.com/apex/log ``` 1. 建立logrus.go: ``` package structured import "github.com/sirupsen/logrus" // Hook 实现了logrus中的hook 接口 type Hook struct { id string } // Fire 在每次记录日志时都会触发 func (hook *Hook) Fire(entry *logrus.Entry) error { entry.Data["id"] = hook.id return nil } // Levels 日志等级 func (hook *Hook) Levels() []logrus.Level { return logrus.AllLevels } // Logrus 演示了一些基本的logrus库操作 func Logrus() { logrus.SetFormatter(&logrus.TextFormatter{}) logrus.SetLevel(logrus.InfoLevel) logrus.AddHook(&Hook{"123"}) fields := logrus.Fields{} fields["success"] = true fields["complex_struct"] = struct { Event string When string }{"Something happened", "Just now"} x := logrus.WithFields(fields) x.Warn("warning!") x.Error("error!") } ``` 2. 建立apex.go: ``` package structured import ( "errors" "os" "github.com/apex/log" "github.com/apex/log/handlers/text" ) // ThrowError抛出我们将追踪的错误 func ThrowError() error { err := errors.New("a crazy failure") log.WithField("id", "123").Trace("ThrowError").Stop(&err) return err } type CustomHandler struct { id string handler log.Handler } // HandleLog 会对日志进行处理 func (h *CustomHandler) HandleLog(e *log.Entry) error { e.WithField("id", h.id) return h.handler.HandleLog(e) } func Apex() { log.SetHandler(&CustomHandler{"123", text.New(os.Stdout)}) err := ThrowError() //WithError可以便利的记录错误 log.WithError(err).Error("an error occurred") } ``` 3. 建立main.go: ``` package main import ( "fmt" "github.com/agtorre/go-cookbook/chapter4/structured" ) func main() { fmt.Println("Logrus:") structured.Logrus() fmt.Println() fmt.Println("Apex:") structured.Apex() } ``` 4. 这会输出: ``` Logrus: WARN[0000] warning! complex_struct={Something happened Just now} id=123 success=true ERRO[0000] error! complex_struct={Something happened Just now} id=123 success=true Apex: INFO[0000] ThrowError id=123 ERROR[0000] ThrowError duration=133ns error=a crazy failure id=123 ERROR[0000] an error occurred error=a crazy failure ``` ### 说明 sirupsen/logrus和apex/log包都是优秀的结构化日志库。二者都提供了用于发送到多个事件或向日志条目添加额外字段的处理方案。其中使用logrus为日志和服务名称添加行号将相对简单。这方便了跨不同服务跟踪日志。 * * * * 学识浅薄,错误在所难免。欢迎在群中就本书提出修改意见,以飨后来者,长风拜谢。 Golang中国(211938256) beego实战(258969317) Go实践(386056972)