fiber本身不提供日志轮转功能,需借助lumberjack等外部库或系统工具logrotate实现按大小或时间归档;lumberjack推荐用于代码内管理,logrotate更适配生产环境系统级管控。

直接上结论:Fiber 本身不提供日志轮转功能,fiber.Logger() 中间件只负责格式化输出到 io.Writer(比如 os.Stdout),真正的分割和清理必须交由外部 handler 或系统工具完成。
用 RotatingFileHandler 实现按大小自动切割
Go 标准库没有内置的 RotatingFileHandler,但社区有稳定可用的替代方案,比如 rotatelogs(lestrrat-go/file-rotatelogs)或更轻量的 lumberjack。后者更推荐,因它零依赖、API 简洁、生产验证充分。
常见错误现象:手写文件打开+判断大小逻辑,结果并发写入时出现 file is locked 或日志丢失。
- 必须用
lumberjack.Logger包裹os.File,它内部已加锁并处理原子重命名 -
MaxSize单位是字节,别写成10MB—— 正确写法是10 * 1024 * 1024 -
MaxBackups控制保留几个旧文件,MaxAge控制单个文件最长存活时间(二者可共存,但MaxAge不影响切割触发) - 示例初始化:
import ( "os" "github.com/natefinch/lumberjack" "github.com/gofiber/fiber/v2" ) <p>w := &lumberjack.Logger{ Filename: "logs/app.log", MaxSize: 10 <em> 1024 </em> 1024, // 10MB MaxBackups: 7, MaxAge: 28, // 天 Compress: true, }</p><p>app := fiber.New(fiber.Config{ ErrorHandler: func(c *fiber.Ctx, err error) error { // 错误日志也走 lumberjack w.Write([]byte(fmt.Sprintf("[%s] ERROR: %v\n", time.Now().Format("2006-01-02 15:04:05"), err))) return c.Status(fiber.StatusInternalServerError).SendString("Internal Server Error") }, })</p><p>// 日志中间件:所有请求日志写入 lumberjack app.Use(func(c *fiber.Ctx) error { start := time.Now() err := c.Next() logLine := fmt.Sprintf("[%s] %s %s %d %s\n", start.Format("2006-01-02 15:04:05"), c.Method(), c.Path(), c.Response().StatusCode(), time.Since(start), ) w.Write([]byte(logLine)) return err }) </p>用
TimedRotatingFileHandler实现按天归档Go 没有原生
TimedRotatingFileHandler,但rotatelogs支持基于时间的切割(如每天、每小时),且能自动压缩。注意它默认不删除旧文件,清理得靠自己或外部工具。容易踩的坑:
rotatelogs的WithLinkName会创建软链指向最新日志,但某些容器环境或 NFS 存储不支持软链,导致启动失败。- 使用
WithRotationTime设置切割周期,例如24 * time.Hour表示每天午夜切 -
WithMaxAge和WithRotationCount二选一即可控制保留策略;WithMaxAge更直观(如7 * 24 * time.Hour) - 压缩需额外调用
gzip命令或集成compress/gzip手动处理,rotatelogs本身不压缩 - 路径中务必包含时间占位符,否则无法生成带日期的文件名:
"logs/app-%Y-%m-%d.log"
Linux 系统级清理:用
logrotate替代代码内管理在容器或 systemd 服务中硬编码日志策略,不如交给
logrotate—— 它成熟、可靠、资源占用低,且与应用解耦。Fiber 应用只需把日志写进固定路径(如/var/log/myapp/app.log),剩下的全由系统接管。典型错误配置:
copytruncate被滥用。它适用于无法重开文件句柄的老服务,但 Fiber 可随时os.OpenFile(..., os.O_APPEND)追加,应优先用create+rotate,避免日志丢失窗口。- 配置示例(
/etc/logrotate.d/myapp):/var/log/myapp/app.log { daily missingok rotate 30 compress delaycompress notifempty create 0644 www-data www-data sharedscripts } -
sharedscripts表示所有匹配文件共用一次postrotate脚本,适合单进程应用 - 如果应用以非 root 用户运行,确保
create权限匹配,否则 rotate 后新文件无法写入 - 测试配置是否生效:
logrotate -d /etc/logrotate.d/myapp(debug 模式)
真正难的是协调:当
lumberjack在代码里设了MaxAge=28d,而logrotate又配了rotate 30,两个策略同时生效会导致文件被删两次或冲突。生产环境建议只留一种——要么全交给logrotate(推荐),要么全由 Go handler 管理(适合无 root 权限或嵌入式场景)。 - 使用











