Golang: Logging: logrus

4th January 2021 at 1:28pm
Golang: Logging

logrus 模型比内置库复杂一点:

  • 多了 formatter 结构,可以输出成多种结构化文本,如 JSONFormatter。但是社区还是没有类似 Python 的格式字符串 formatter
  • 多了 hook 机制,可以按各消息不同的 loglevel 做逻辑,比如 ERROR 消息写 error.log,DEBUG 消息写 debug.log
  • 可以带 context 输出,logrus.WithFields()
  • 可以判断 writer 是不是终端,如果是,给漂亮的带颜色输出;否则给普通输出
  • 不提供 log rotation 能力

基本用法

参考 Github

默认 context 参数

logger = logger.WithFields(logrus.Fields{"reqId": requestId, "command": c.Command.Name})
logger.Debugf("...")
logger.Fetalf("...")

多个输出端

rifflock/lfshook 提供了不同 log level 写不同文件的 hook,可以实现同时输出到文件和 stdout:

l := logrus.New()

ex, _ := os.Executable()
logFile := filepath.Dir(ex) + "/tsf-instance-agent.log"
writer := os.Open(logFile, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0755)

l.Hooks.Add(lfshook.NewHook(
    lfshook.WriterMap{
        logrus.DebugLevel: writer,
    },
    &logrus.TextFormatter{},
))
l.Out = os.Stdout

logger = logrus.NewEntry(l)

l.Out = io.MultiWriter(writer, os.Stdout) 时,stdout 的带颜色输出就不生效了。logrus 没有原生的支持多 writer(也可能是 Go 内置的 log 库带了节奏)。看看这个 Github issue 有无新动态。

Log Rotation

lestrrat-go/file-rotatelogs 实现 log rotation。Log rotation 整合多端输出:

func SetupLogging() {
    l := logrus.New()
    l.SetLevel(logrus.DebugLevel)

    ex, _ := os.Executable()
    logFile := filepath.Dir(ex) + "/tsf-instance-agent.log"

    writer, _ := rotatelogs.New(
        logFile+".%Y%m%d",
        rotatelogs.WithLinkName(logFile),

        rotatelogs.WithMaxAge(time.Hour*24*30),
        rotatelogs.WithRotationTime(time.Hour*24),
    )

    l.Hooks.Add(lfshook.NewHook(
        lfshook.WriterMap{
            logrus.DebugLevel: writer,
        },
        &logrus.TextFormatter{},
    ))
    l.Out = os.Stdout

    logger = logrus.NewEntry(l)
}