Beego 原生无法实现精确小时级日志滚动归档,因其 logs.AdapterFile 仅支持 daily 或 maxsize 触发,缺乏时间精度控制;需替换为 rotatelogs 等第三方轮转库并手动 SetLoggerInterface。

Beego 自带的 logs 包不支持原生的「按小时滚动+自动归档」能力,它依赖外部轮转逻辑或手动干预;若需严格每小时生成新文件(如 app.2024-08-21_11.log)且永久保留,必须绕过 logs 的 AdapterFile,改用 Logback 风格的底层控制——但 Beego 是 Go 项目,Logback 不适用。结论很直接:**Beego 原生无法实现精确小时级日志滚动归档**,得靠组合方案补足。
为什么 beego/logs.AdapterFile 不能按时归档
Beego 的 AdapterFile 仅支持两种触发方式:daily(每天 00:00)和基于单文件大小的 maxsize。它没有 cron 或时间精度控制机制:
-
daily=true只在每日零点强制滚动,无法细化到小时 -
maxsize和maxlines是被动触发,空闲时可能数小时不生成新文件 - 即使设
maxdays=0,也只禁用清理,不解决“准时生成”问题 - 其内部使用
os.OpenFile追加写入,无 Quartz/Cron 调度器集成
可行替代方案:用第三方轮转库接管文件写入
Beego 允许自定义 logger 实现,只要满足 logs.LoggerInterface 接口即可。推荐接入 rotatelogs(Go 生态最成熟的时间轮转库),配合 lumberjack 也可,但 rotatelogs 支持 cron 表达式更贴近需求:
- 安装:
go get github.com/lestrrat-go/file-rotatelogs - 初始化时传入
WithClock+WithLinkName,确保软链指向最新日志 - cron 表达式用
"0 0 0/1 * * ?"(每小时整点)或"0 0 * * *"(Linux cron 风格,每小时) - 注意:Beego 的
logs.SetLogger第二个参数是 JSON 字符串,但自定义 logger 不走该路径,要直接调用logs.SetLoggerInterface - 示例关键片段:
rl, _ := rotatelogs.New( logDir+"/app.%Y-%m-%d_%H.log", rotatelogs.WithClock(rotatelogs.Local), rotatelogs.WithRotationTime(time.Hour), rotatelogs.WithLinkName(logDir+"/app.log"), ) logger := &customWriter{Writer: rl} logs.SetLoggerInterface(logger)
配置陷阱:maxdays=0 ≠ 永久保留,且与轮转库冲突
很多人误以为给 AdapterFile 设 "maxdays": 0 就能永久存档,实际它只影响 daily 模式下的清理逻辑,对非 daily 场景无效。更危险的是:
- 若同时启用
daily=true和第三方轮转,会出现两个进程争写同一文件,导致日志丢失或损坏 -
maxsize与rotatelogs的WithRotationTime冲突:前者按大小切,后者按时间切,结果不可控 - Windows 下文件名含冒号(
%H:%M)会报错,必须用下划线分隔,如%Y-%m-%d_%H - Beego 启动时若日志目录不存在,
rotatelogs不会自动创建父目录,需提前os.MkdirAll
真正可靠的小时归档,本质是放弃 Beego 日志模块的文件管理,把它降级为纯格式化+输出接口,把“何时切、切哪、存多久”全交给专业轮转库。这点常被忽略——不是配几个 JSON 字段就能搞定,而是要重写 logger 绑定逻辑。


















