如何使我Rails应用程序的每个独立工作进程记录到不同的文件?

9

如何让我的 Rails 应用程序的每个独角兽 worker 写入不同的日志文件?

原因:混合日志文件的问题... 在默认配置中,Rails 将其日志消息写入单个日志文件:log/<environment>.log

Unicorn workers 将同时写入同一日志文件,这些消息可能会混在一起。当 request-log-analyzer 解析日志文件时,这将是一个问题。例如:

Processing Controller1#action1 ...
Processing Controller2#action2 ...
Completed in 100ms...
Completed in 567ms...

在这个例子中,哪个动作在100ms内完成了,哪个动作在567ms内完成了?我们永远无法确定。
2个回答

3

将以下代码添加到unicorn.rb的after_fork中:

#one log per unicorn worker
if log = Rails.logger.instance_values['log']
  ext = File.extname log.path
  new_path =log.path.gsub %r{(.*)(#{Regexp.escape ext})}, "\\1.#{worker.nr}\\2"
  Rails.logger.instance_eval do
    @log.close
    @log= open_log new_path, 'a+'
  end
end

这个实现在Rails 2.3应用程序中能够工作吗?这个帖子里没有人具体说明他们的代码可以在哪些版本中工作,而我正在尝试在一个相当老的应用程序中完成这个确切的事情,但不确定该如何去做。 - Jesse Dupuy

2

@slact的答案在Rails 3上不起作用。 这个方法可以解决

after_fork do |server, worker|

  # Override the default logger to use a separate log for each Unicorn worker.
  # https://github.com/rails/rails/blob/3-2-stable/railties/lib/rails/application/bootstrap.rb#L23-L49
  Rails.logger = ActiveRecord::Base.logger = ActionController::Base.logger = begin
    path = Rails.configuration.paths["log"].first
    f = File.open(path.sub(".log", "-#{worker.nr}.log"), "a")
    f.binmode
    f.sync = true
    logger = ActiveSupport::TaggedLogging.new(ActiveSupport::BufferedLogger.new(f))
    logger.level = ActiveSupport::BufferedLogger.const_get(Rails.configuration.log_level.to_s.upcase)
    logger
  end
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接