
本文详解如何在go中使用logrus等主流日志库,将不同日志级别(如debug、info)分别输出到文件和标准输出,并支持时间戳、格式化等生产级需求。
本文详解如何在go中使用logrus等主流日志库,将不同日志级别(如debug、info)分别输出到文件和标准输出,并支持时间戳、格式化等生产级需求。
在Go开发中,单一输出(如仅打印到终端或仅写入文件)难以满足实际运维与调试需求:调试阶段需详尽的Debug日志留存于文件供追溯,而运行时关键Info/Warn信息则需实时可见于控制台。io.MultiWriter虽可实现多目标写入,但它不区分日志级别——所有日志会同时输出到所有目标,无法满足“Debug仅写文件、Info同时输出到控制台+文件”的精细化需求。
因此,正确方案是采用支持Hook机制的日志库(如Logrus),通过自定义Hook实现按级别分流。以下是基于Logrus的完整实现:
✅ 推荐方案:Logrus + 自定义LevelFilter Hook
package main
import (
"io"
"log"
"os"
"time"
"github.com/sirupsen/logrus"
)
// LevelFilterHook 根据日志级别决定是否写入目标Writer
type LevelFilterHook struct {
Writer io.Writer
Levels []logrus.Level
}
func (h *LevelFilterHook) Fire(entry *logrus.Entry) error {
for _, level := range h.Levels {
if entry.Level == level {
err := entry.Write(h.Writer)
if err != nil {
return err
}
break
}
}
return nil
}
func (h *LevelFilterHook) Levels() []logrus.Level {
return h.Levels
}
func main() {
// 创建文件输出(带时间戳)
file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
// 配置Logrus
logrus.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
TimestampFormat: time.RFC3339,
})
// Hook 1:Debug及以上日志写入文件
logrus.AddHook(&LevelFilterHook{
Writer: file,
Levels: []logrus.Level{logrus.DebugLevel, logrus.InfoLevel, logrus.WarnLevel, logrus.ErrorLevel},
})
// Hook 2:Info及以上日志输出到stdout(不包含Debug)
logrus.AddHook(&LevelFilterHook{
Writer: os.Stdout,
Levels: []logrus.Level{logrus.InfoLevel, logrus.WarnLevel, logrus.ErrorLevel},
})
// 使用示例
logrus.Debug("Entering some func") // → 仅写入文件
logrus.Infof("Result was: %s", "Successful") // → 同时输出到文件和stdout
}
⚠️ 注意事项与最佳实践
- 避免使用 log.SetOutput(io.MultiWriter(...)):该方式无法按级别过滤,违背原始需求;
- 文件权限与滚动:生产环境应引入lumberjack等日志轮转库,防止单文件无限增长;
- 并发安全:Logrus默认线程安全,但自定义Writer(如文件)需确保底层IO操作无竞争;
- 性能考量:高频Debug日志若全量写入磁盘,建议启用异步写入(如通过logrus.WithField(...).Info(...)配合缓冲Hook);
- 替代方案:Zap(Uber)原生支持多Sink与Level路由,性能更高,适合高吞吐场景。
通过上述结构化Hook设计,你可灵活扩展:例如添加HTTP Hook上报Error、集成Prometheus指标、或对接ELK栈。日志分级输出不是功能取舍,而是可观测性建设的第一步。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











