Silencing the Rails log on a per-action basis

In our current project we are having an action that is polled every ten seconds by the clients. This clutters up the log, so I was looking for a way to completely silence the Rails logger for this action. It turns out that you have to swap the default logger with a custom one, because even when you use the Rails.logger.silence block in your action, you will still find a line in your log that is printed out before the request gets dispatched.

Here’s our custon logging class:

# lib/custom_logger.rb
class CustomLogger < Rails::Rack::Logger
  def initialize(app, opts = {})
    @app = app
    @opts = opts
    @opts[:silenced] ||= []
    super
  end

  def call(env)
    if env['X-SILENCE-LOGGER'] || @opts[:silenced].include?(env['PATH_INFO'])
      Rails.logger.silence do
        @app.call(env)
      end
    else
      super(env)
    end
  end
end

This way you can either define request paths that should not get logged or send the X-SILENCE-LOGGER header for the request you don’t want to log.

To make use of your own logger, you’ll have to swap the default logger, which is included as a Rack middleware:

# config/application.rb
require File.dirname(__FILE__) + '/../lib/custom_logger.rb'

module MyApp
  class Application < Rails::Application
    # Middlewares
    config.middleware.swap Rails::Rack::Logger, CustomLogger, :silenced => ["/noisy/action.json"]
  end
end

Updated on February 12th, 2013: Thanks to Andrew Premdas for letting me know that with Rails 3.2.11 one needs to call super in the initialize method.

iPhone app for GitHub

iOctocat

is GitHub in your pocket: The go to app for staying up to date with your projects on your iPhone, and iPod Touch.
It is