Golang: Logging: logrus

 13th January 2022 at 3:21pm

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)
}