How can I make each unicorn worker of my Rails application writting in a different log file ?
The why : problem of mixed log files...
In its default configuration, Rails will write its log messages to a single log file: log/<environment>.log
.
Unicorn workers will write to the same log file at once, the messages can get mixed up. This is a problem when request-log-analyzer parses a log file. An example:
Processing Controller1#action1 ...
Processing Controller2#action2 ...
Completed in 100ms...
Completed in 567ms...
In this example, what action was completed in 100ms, and what action in 567 ms? We can never be sure.
In a Rails app, logs are stored under the /log folder.
Unicorn is an application server, like Passenger or Puma, that enables your Rails application to process requests concurrently. As Unicorn is not designed to be accessed by users directly, we will use Nginx as a reverse proxy that will buffer requests and responses between users and your Rails application.
To write in the current log use the logger. (debug|info|warn|error|fatal|unknown) method from within a controller, model, or mailer: logger. debug "Person attributes hash: #{@person.
Unicorn is a Rack HTTP server that uses forked processes to handle multiple incoming requests concurrently.
add this code to after_fork in unicorn.rb:
#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
@slact's answer doesn't work on Rails 3. This works:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With