Eki*_*bal 5 ruby logging ruby-on-rails
我正在使用ruby标准记录器,我想每天轮换一次,所以在我的代码中我有:
Logger.new("#{$ROOT_PATH}/log/errors.log", 'daily')
Run Code Online (Sandbox Code Playgroud)
它工作得很好,但它创建了两个文件errors.log.20130217和errors.log.20130217.1.
我如何强制它每天只创建一个文件?
joe*_*son 11
您的代码适用于长时间运行的应用程序.
发生的事情是你在某一天不止一次运行代码.
第一次运行它时,Ruby会创建一个日志文件"errors.log".
当日期更改时,Ruby会将文件重命名为"errors.log.20130217".
但不知何故,你再次运行代码,也许你正在运行使用类似代码的两个应用程序(或进程,工作者或线程),并且你的记录器看到文件名"errors.log.20130217"已经存在.
您的记录器不想破坏该文件,但仍需要将"errors.log"重命名为日期,因此记录器创建了另一个文件名"errors.log.20130217.1"
要解决此问题,请仅运行一次代码.
如果您正在运行名为"foo"和"bar"的多个应用程序,则使用"foo-errors.log"和"bar-errors.log"等日志文件名.或者,如果您使用多个工作人员,请为每个工作人员提供自己的日志文件名(例如,使用工作人员的进程ID或工作池数组索引,或者您是否跟踪工作人员).
如果你真的想用Ruby记录器解决这个问题,你需要覆盖记录器#shift_log_period,这样就不会选择".1"后缀.您可以将Logger子类化并编写您已磨损的#shift_log_period以检测该日期是否存在现有日志文件,如果是,则使用它而不是执行文件重命名.
这是从记录器中导致它的代码:
def shift_log_period(period_end)
postfix = period_end.strftime("%Y%m%d") # YYYYMMDD
age_file = "#{@filename}.#{postfix}"
if FileTest.exist?(age_file)
# try to avoid filename crash caused by Timestamp change.
idx = 0
# .99 can be overridden; avoid too much file search with 'loop do'
while idx < 100
idx += 1
age_file = "#{@filename}.#{postfix}.#{idx}"
break unless FileTest.exist?(age_file)
end
end
@dev.close rescue nil
File.rename("#{@filename}", age_file)
@dev = create_logfile(@filename)
return true
Run Code Online (Sandbox Code Playgroud)
没有解决方案(AFAIK)使用Ruby记录器及其内置旋转器来同时管理由多个应用程序(也称为工作者,进程,线程)编写的日志.这是因为每个应用程序都有自己的日志文件句柄.
或者,使用任何良好的日志旋转工具,例如Tin Man用户在问题评论中建议的logrotate:http://linuxcommand.org/man_pages/logrotate8.html
一般来说,logrotate将是你最好的赌注恕我直言.