March 26, 2015

I haven’t seen a lot of great documentation for setting up Log4r with Rails 4 (4.2 specifically) so here goes.

When I started out, I decided to go into config/application.rb and set config.logger to a logger. It looked something like this

...
config.logger = Log4r::Logger.new 'blah'
...

The problem is that Rails 4.2 (not sure about other versions at the moment) expects a method on the logger called formatter(). Log4r, however, defines formatter() on each outputter of the logger (i.e. so that each outputter can have a different format). We could monkey-patch it like this

Log4r::Logger.class_eval do
  def formatter
    # Give it the first formatter we have?
    outputters[0].formatter if outputters.any?
  end
end

This is rather awkward and worst of all, we still get the logging that Rails itself outputs. A better way to do this is to use Rails’ instrumentation API and subscribe to particular hooks. First, let’s turn off the default Rails logging, in config/application.rb

...
config.log_level = :unknown
...

Now, let’s create an initializer called config/initializers/log4r.rb. You can subscribe to any of the hooks listed on this page and be able to log whatever you like! For example, we can hook into the processing of each controller action and ActiveRecord SQL transaction like so:

require 'log4r'

# Log4r configuration goes here

# Subscribe to each action
ActiveSupport::Notifications.subscribe("process_action.action_controller") do |name, start, finish, id, payload|
  # Code to log stuff goes here
end

# Subscribe to each SQL transaction
ActiveSupport::Notifications.subscribe "sql.active_record" do |name, start, finish, id, payload|
  # Code to log stuff goes here
end

Log4r is very complex and versatile in its configuration and you can find resources for setting it up here, here, here and here. Happy logging!

blog comments powered by Disqus