下载地址: github.com/sirupsen/logrus

简单使用

  • WithFields 添加字段 Logrus鼓励通过日志字段进行谨慎的结构化日志记录,而不是冗长的、不可解析的错误消息
  1. package main
  2. import (
  3. log "github.com/sirupsen/logrus"
  4. "os"
  5. )
  6. type s struct {
  7. Name string
  8. Age int
  9. }
  10. func main() {
  11. a := s{
  12. Name: "小乙",
  13. Age: 10,
  14. }
  15. // 设置日志等级
  16. log.SetLevel(log.DebugLevel)
  17. // 设置日志打到那里去
  18. log.SetOutput(os.Stdout)
  19. // 设置filename
  20. log.SetReportCaller(true)
  21. // 设置format text
  22. //log.SetFormatter(&log.TextFormatter{
  23. //
  24. // TimestampFormat: "2006-01-02 15:04:05",
  25. //})
  26. log.SetFormatter(&log.JSONFormatter{
  27. TimestampFormat: "2006-01-02 15:04:05",
  28. })
  29. log.Debug("调试信息")
  30. log.Info("提示信息")
  31. log.Warn("警告信息")
  32. log.Error("错误信息")
  33. log.Infof("[格式化打印结构体:%+v]", a)
  34. log.WithFields(log.Fields{
  35. "user_id": 123,
  36. "ip": "1.1.1.1",
  37. "request_id": "asdwdadmaskmdlasmldkmwqlkdkmakldm",
  38. }).Info("用户登录成功")
  39. }

全局的logger init函数

  • 设置level
  • 设置output
  • 设置format
  • 新建g/log.go
  1. package g
  2. import (
  3. "github.com/sirupsen/logrus"
  4. "os"
  5. )
  6. var Logger = logrus.New()
  7. func InitLogger(level string) {
  8. switch level {
  9. case "info":
  10. Logger.SetLevel(logrus.InfoLevel)
  11. case "debug":
  12. Logger.SetLevel(logrus.DebugLevel)
  13. case "warn":
  14. Logger.SetLevel(logrus.WarnLevel)
  15. }
  16. Logger.SetOutput(os.Stdout)
  17. // 设置filename
  18. Logger.SetReportCaller(true)
  19. // 设置format text
  20. //log.SetFormatter(&log.TextFormatter{
  21. //
  22. // TimestampFormat: "2006-01-02 15:04:05",
  23. //})
  24. Logger.SetFormatter(&logrus.JSONFormatter{
  25. TimestampFormat: "2006-01-02 15:04:05",
  26. })
  27. }
  • 使用
  1. g.InitLogger("info")
  2. g.Logger.Println("测试")

hook使用

hook字段说明

  • Levels 代表在哪几个级别下应用这个hook
  • Fire 代表 执行哪个函数
  1. type Hook interface {
  2. Levels() []Level
  3. Fire(*Entry) error
  4. }

日志发送钉钉样例

钉钉机器人发送群消息

  1. package main
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. logger "github.com/sirupsen/logrus"
  7. "net/http"
  8. )
  9. type dingHook struct {
  10. apiUrl string //钉钉 群机器人token url
  11. levels []logger.Level
  12. atMobiles []string // at谁
  13. appName string // 模块前缀
  14. jsonBodies chan []byte //异步发送内容队列
  15. closeChan chan bool //主进程关闭消息通道
  16. }
  17. //- Levels 代表在哪几个级别下应用这个hook
  18. func (dh *dingHook) Levels() []logger.Level {
  19. return dh.levels
  20. }
  21. //- Fire 代表 执行具体什么逻辑
  22. func (dh *dingHook) Fire(e *logger.Entry) error {
  23. msg, _ := e.String()
  24. dh.DirectSend(msg)
  25. return nil
  26. }
  27. // 同步发送钉钉的函数
  28. func (dh *dingHook) DirectSend(msg string) {
  29. dm := dingMsg{
  30. MsgType: "text",
  31. }
  32. dm.Text.Content = fmt.Sprintf("[日志告警log]\n[app=%s]\n"+
  33. "[日志详情:%s]", dh.appName, msg)
  34. dm.At.AtMobiles = dh.atMobiles
  35. bs, err := json.Marshal(dm)
  36. if err != nil {
  37. logger.Errorf("[消息json.marshal失败][error:%v][msg:%v]", err, msg)
  38. return
  39. }
  40. res, err := http.Post(dh.apiUrl, "application/json", bytes.NewBuffer(bs))
  41. if err != nil {
  42. logger.Errorf("[消息发送失败][error:%v][msg:%v]", err, msg)
  43. return
  44. }
  45. if res != nil && res.StatusCode != 200 {
  46. logger.Errorf("[钉钉返回错误][StatusCode:%v][msg:%v]", res.StatusCode, msg)
  47. return
  48. }
  49. }
  50. // 定义发钉钉信息的字段
  51. /*
  52. {
  53. "at": {
  54. "atMobiles":[
  55. "180xxxxxx"
  56. ],
  57. "atUserIds":[
  58. "user123"
  59. ],
  60. "isAtAll": false
  61. },
  62. "text": {
  63. "content":"我就是我, @XXX 是不一样的烟火"
  64. },
  65. "msgtype":"text"
  66. }
  67. */
  68. type dingMsg struct {
  69. MsgType string `json:"msgtype"`
  70. Text struct {
  71. Content string `json:"content"`
  72. } `json:"text"`
  73. At struct {
  74. AtMobiles []string `json:"atMobiles"`
  75. } `json:"at"`
  76. }
  77. func main() {
  78. dh := &dingHook{
  79. apiUrl: "https://oapi.dingtalk.com/robot/send?access_token=xxxxx",
  80. levels: []logger.Level{logger.WarnLevel, logger.InfoLevel},
  81. atMobiles: []string{"xxxx"},
  82. appName: "live",
  83. jsonBodies: make(chan []byte),
  84. closeChan: make(chan bool),
  85. }
  86. //dh.DirectSend("直接发送一波看看")
  87. level := logger.InfoLevel
  88. logger.SetLevel(level)
  89. // 设置filename
  90. logger.SetReportCaller(true)
  91. logger.SetFormatter(&logger.JSONFormatter{
  92. TimestampFormat: "2006-01-02 15:04:05",
  93. })
  94. // 添加hook
  95. logger.AddHook(dh)
  96. logger.Info("这是我自己hook的logrus")
  97. }

总结如何使用 logrus的hook功能

  1. 要去实现先Fire 和Levels方法 —> 实现那个hook接口
  2. 你的处理逻辑在Fire中
    • 比如发送到redis 、es 、钉钉、logstash
  3. addHook,直接打印日志发送就可以了

原理追踪

  • logrus.Info 对应{指定的GOPATH路径}\pkg\mod\github.com\sirupsen\logrus@v1.8.1\entry.go
  1. func (entry *Entry) Info(args ...interface{}) {
  2. entry.Log(InfoLevel, args...)
  3. }
  • D:\go_path\pkg\mod\github.com\sirupsen\logrus@v1.8.1\entry.go +241
  1. newEntry.fireHooks()
  • D:\go_path\pkg\mod\github.com\sirupsen\logrus@v1.8.1\hooks.go
  1. // Fire all the hooks for the passed level. Used by `entry.log` to fire
  2. // appropriate hooks for a log entry.
  3. func (hooks LevelHooks) Fire(level Level, entry *Entry) error {
  4. for _, hook := range hooks[level] {
  5. if err := hook.Fire(entry); err != nil {
  6. return err
  7. }
  8. }
  9. return nil
  10. }