Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

How to split up rails 3.x logger by unicorn workers

TLDR: Put this in your unicorn config. Make sure not to have duplicate after_fork calls

after_fork do |server, worker|
  if defined?(ActiveSupport::TaggedLogging) && Rails.logger.kind_of?(ActiveSupport::TaggedLogging)
    Rails.logger.instance_eval do
      level = @logger.level
      # flush and close logger to make sure we don't cut off any potential logging before this
      @logger && @logger.flush && @logger.close
      @logger ="log", "rails_#{Rails.env}.#{}.log").to_s, level)
  elsif Rails.logger.kind_of?(ActiveSupport::BufferedLogger)
    Rails.logger.instance_eval do
      @log && @log.flush && @log.close
      @log_path = Rails.root.join("log", "rails_#{Rails.env}.#{}.log").to_s
      if respond_to?(:open_logfile, true)
        @log = open_logfile(@log_path)
      elsif respond_to?(:open_log, true)
        if File.exist?(@log_path)
          @log = open_log(@log_path, (File::WRONLY | File::APPEND))
          @log = open_log(l@log_path, (File::WRONLY | File::APPEND | File::CREAT))

How this works!

There is no easy way to change the path of a log or swap out the logger. When rails is instantiated ActionController and ActiveRecord assigns their local logger from Rails.logger. So if you reassign Rails.logger to a new one ActionController and ActiveRecord will continue to use the old rails logger.

There are no methods to change or swap out the log path in the Logging class. In order to change the log path we have to change instance variables to either a new logger or a new file handler.

In Rails 3.2 ActiveSupport::TaggedLogging was added!
If you look here you can see how Rails.logger is assigned! (source)
As you can see TaggedLogging basically just wraps a buffered logger. So when we open up Rails.logger we can patch what TaggedLogging wraps by modifying the @logger variable.
If TaggedLogging isn’t used we can use the open_logfile command and just insert a path.

In Rails 3.0 and Rails 3.1 TaggedLogging isn’t used and by default uses BufferedLogger.
We have to create a new file handler using the open_log method and reassign the @log variable.

  1. tasa says:

    Hey guys,

    Looks like this approach is broken in Rails 4.1, after all the rails logger changes.

    How did you solve it, any ideas?

  2. Trung Lê says:

    In Rails 4.0, it is same technique with one minor difference is that BufferedLogger has been deprecated and thus all instances of BufferedLogger need to be replaced with just ActiveSupport::Logger

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *