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.