Better logging in Rails in production mode

December 28th, 2008 3 Comments »

I’m quite surprised, that even of version 2.2.2 of Rails, the logs are written in a way that makes them almost useless, as there’s no time stamp or severity level.
The solution I’ve come up with, is (instead of monkey patching the BufferedLogger) to create a new type of logger which inherits from the BufferedLogger and then change the ‘add’ method in order to produce nicer logs.
This file is lib/audit_logger.rb :

class AuditLogger < ActiveSupport::BufferedLogger
 
  SEVERITIES = Severity.constants.inject([]) {|arr,c| arr[Severity.const_get(c)] = c; arr}
 
  # Redefine the ActiveSupport::BufferedLogger#add
  def add(severity, message = nil, progname = nil, &block)
    return if @level > severity
    message = (message || (block && block.call) || progname).to_s
    # This is the line that was changed:
    message = "#{Time.now.to_formatted_s(:db)} #{SEVERITIES[severity]} #{message.strip}\n"
    buffer << message
    auto_flush
    message
  end
end

Then, in config/environments/production.rb you need to add:

require 'audit_logger'
config.logger = AuditLogger.new(config.log_path)
config.logger.level = AuditLogger::INFO #or other level
# This is what Rails does by default in production mode when using the default logger
config.logger.auto_flushing = false