shift_age设为'daily'的Rails Logger小文件场景下不轮转如何解决
问题根因
Ruby 标准库自带的 Logger 类的按天轮转逻辑触发存在两个限制:
- 只有执行日志写入操作时才会触发时间校验,当日无任何日志写入的场景下不会主动触发轮转
- 仅当新写入日志的时间,与当前日志文件的修改时间不在同一天时,才会执行轮转操作
你遇到的 staging 环境不轮转问题,核心是两个原因共同导致:
- 代码里提前执行的
FileUtils.touch操作会人为更新日志文件的修改时间为服务部署/重启的时间,只要写入日志的时间和 touch 时间属于同一天,就不会触发轮转 - Staging 环境流量低,常出现当日无新增日志的情况,无法触发 Logger 内置的校验逻辑,而生产环境有持续流量写入,每次写入都会校验时间,因此可以正常轮转
修复方案
1. 移除多余的 touch 操作
Logger.new初始化时如果目标日志文件不存在会自动创建,不需要提前手动touch,同时优化参数写法避免歧义:
# 移除多余的 touch 操作 # FileUtils.touch(Rails.root.join('log/custom_log.json')) # 原写法的 shift_age = 'daily' 属于多余的局部变量赋值,推荐用关键字参数更清晰 @@custom_logger = Logger.new(Rails.root.join('log/custom_log.json'), shift_age: 'daily')
2. 低流量环境补充强制校验逻辑
如果 Staging 环境确实长期存在低写入量的情况,可以在服务启动时主动增加一次轮转校验:
log_path = Rails.root.join('log/custom_log.json') @@custom_logger = Logger.new(log_path, shift_age: 'daily') # 启动时主动校验是否需要轮转 if File.exist?(log_path) && File.mtime(log_path).to_date < Date.today @@custom_logger.shift_log_now end
3. 高稳定性可选方案
如果对日志轮转的准确率要求更高,推荐直接使用系统级的 logrotate 工具托管日志轮转,不受 Ruby Logger 自身逻辑限制,稳定性更强,可根据需求配置保留时长、压缩、大小兜底等规则。
内容的提问来源于stack exchange,提问作者Rajuk
相关产品推荐
相关产品推荐

