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工具,它原生支持同时按时间和大小轮转,稳定性更高:
- 创建logrotate配置文件:
sudo touch /etc/logrotate.d/your_rails_app
- 写入配置内容(替换为你的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
相关产品推荐
相关产品推荐

