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

Rails 5应用:能否为自定义日志器实现时间+大小双维度日志轮转?

Rails 5 自定义日志器实现时间+大小双维度轮转

完全可以实现,下面提供两种实用方案,分别适合代码自定义控制和系统级稳定管理场景:

方案一:纯Ruby代码实现自定义轮转日志器

通过继承Rails的ActiveSupport::Logger,重写日志写入逻辑,同时校验文件大小和时间阈值触发轮转:

# config/initializers/custom_logger.rb
class RotatingLogger < ActiveSupport::Logger
  def initialize(logdev, shift_days = 7, max_size = 10 * 1024 * 1024)
    super(logdev, shift_days, max_size)
    @last_rotate_date = Time.now.to_date
  end

  def add(severity, message = nil, progname = nil, &block)
    trigger_rotation_if_needed
    super
  end

  private

  def trigger_rotation_if_needed
    current_date = Time.now.to_date
    # 按时间轮转:每天0点触发
    if current_date > @last_rotate_date
      rotate_by_date(current_date)
      @last_rotate_date = current_date
    end

    # 按大小轮转:文件超过设定阈值触发
    file_size = File.size?(logdev.path) || 0
    if file_size >= shift_size
      rotate_by_size
    end
  end

  def rotate_by_date(date)
    date_suffix = date.strftime("%Y%m%d")
    target_path = "#{logdev.path}.#{date_suffix}"
    # 避免重复创建当日轮转文件
    unless File.exist?(target_path)
      File.rename(logdev.path, target_path)
      logdev.reopen(logdev.path, "a")
    end
  end

  def rotate_by_size
    # 复用Logger原生的大小轮转逻辑,生成带数字后缀的日志文件
    super
  end
end

# 替换Rails默认日志器
Rails.logger = RotatingLogger.new(
  Rails.root.join("log", "#{Rails.env}.log"),
  7, # 保留7天的日期轮转日志
  10 * 1024 * 1024 # 单文件最大10MB
)

方案说明

  • 每次写入日志前,先检查两个条件:当前日期是否超过上次轮转日期、文件大小是否超出阈值,满足任一条件就触发轮转
  • 按时间轮转的日志会带上YYYYMMDD后缀,按大小轮转的日志会带上数字后缀(如production.log.1)
  • 多进程环境(如Puma多Worker)下,建议给日志操作加文件锁,避免轮转冲突

方案二:系统logrotate工具(生产环境推荐)

如果不想编写复杂的Ruby逻辑,直接用Linux系统自带的logrotate工具,它原生支持同时按时间和大小轮转,稳定性更高:

  1. 创建logrotate配置文件:
sudo touch /etc/logrotate.d/your_rails_app
  1. 写入配置内容(替换为你的Rails应用日志路径):
/var/www/your_rails_app/log/*.log {
  daily
  size 10M
  rotate 7
  compress
  missingok
  notifempty
  copytruncate
}

配置参数解释

  • daily:每天自动轮转一次
  • size 10M:日志文件达到10MB时立即触发轮转
  • rotate 7:保留最近7份轮转日志
  • compress:自动压缩旧日志节省磁盘空间
  • copytruncate:复制日志内容后清空原文件,避免Rails日志器丢失文件句柄

生效方式

logrotate默认每天通过系统定时任务执行,无需额外启动进程,重启Rails应用即可生效。

内容的提问来源于stack exchange,提问作者Uday Magdum

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:50:31