You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golang项目如何实现按天日志轮转?logrus按日切割方案咨询

Golang logrus按天日志轮转实现方案

下面是三个可在项目代码层级完成配置、无需依赖系统额外配置的可行方案:

方案1:使用file-rotatelogs钩子直接实现按天轮转

这是目前生态中最常用的方案,不需要修改原有logrus调用逻辑,仅需在初始化时配置输出Writer即可。

  • 支持按自定义时间间隔(可精确到天/小时/分钟等)轮转
  • 可配置历史日志保留时长、自动清理过期日志
  • 支持自定义日志文件名格式
    示例初始化代码:
package main

import (
	"github.com/sirupsen/logrus"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"time"
)

func initLog() error {
	// 配置轮转规则
	writer, err := rotatelogs.New(
		// 日志文件名格式,%Y%m%d代表年月日
		"./app.log.%Y%m%d",
		// 指明日志软链接,始终指向最新日志文件
		rotatelogs.WithLinkName("./app.log"),
		// 配置历史日志保留7天
		rotatelogs.WithMaxAge(7 * 24 * time.Hour),
		// 配置按天轮转(24小时间隔)
		rotatelogs.WithRotationTime(24 * time.Hour),
	)
	if err != nil {
		return err
	}
	// 为logrus设置输出Writer
	logrus.SetOutput(writer)
	return nil
}

方案2:对原生lumberjack封装扩展实现按天+按大小双重轮转

如果需要同时保留按大小轮转的能力,可以在lumberjack外层加一层日期判断,跨天时主动触发lumberjack的轮转逻辑。

  • 兼顾按天轮转和按大小切割的需求
  • 复用lumberjack成熟的文件操作、压缩逻辑
    示例封装代码:
type DailyRotator struct {
	lumberjack.Logger
	lastDate string
}

func (d *DailyRotator) Write(p []byte) (n int, err error) {
	currentDate := time.Now().Format("20060102")
	// 日期发生变化时触发轮转
	if currentDate != d.lastDate {
		d.Logger.Rotate()
		d.lastDate = currentDate
	}
	return d.Logger.Write(p)
}

// 初始化用法
func initLog() {
	rotator := &DailyRotator{
		Logger: lumberjack.Logger{
			Filename:   "./app.log",
			MaxSize:    100, // 单文件最大100M
			MaxBackups: 30,  // 最多保留30个备份
			Compress:   true, // 启用压缩
		},
		lastDate: time.Now().Format("20060102"),
	}
	logrus.SetOutput(rotator)
}

方案3:自研极简按天轮转Writer

如果不想引入额外第三方依赖,可以自己实现一个满足io.Writer接口的轻量轮转组件,仅做日期判断和文件切换逻辑,代码量很小可控。

  • 无额外依赖,灵活性最高,可根据业务需求自定义规则
  • 性能开销极低,仅在跨天的时候做一次文件切换操作
    示例实现代码:
type SimpleDailyWriter struct {
	filename string
	file     *os.File
	lastDate string
	mu       sync.Mutex
}

func NewSimpleDailyWriter(filename string) (*SimpleDailyWriter, error) {
	w := &SimpleDailyWriter{filename: filename}
	if err := w.rotate(); err != nil {
		return nil, err
	}
	return w, nil
}

func (w *SimpleDailyWriter) Write(p []byte) (n int, err error) {
	w.mu.Lock()
	defer w.mu.Unlock()
	currentDate := time.Now().Format("20060102")
	if currentDate != w.lastDate {
		if err := w.rotate(); err != nil {
			return 0, err
		}
	}
	return w.file.Write(p)
}

func (w *SimpleDailyWriter) rotate() error {
	date := time.Now().Format("20060102")
	// 关闭旧文件
	if w.file != nil {
		w.file.Close()
	}
	// 打开新文件,文件名带日期后缀
	newFile, err := os.OpenFile(w.filename+"."+date, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		return err
	}
	w.file = newFile
	w.lastDate = date
	return nil
}

内容的提问来源于stack exchange,提问作者Sumit Bopche

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 11:24:03