Set Rails Logging on Fire
Rails 2.3+ and Rails 3 rely on Rack, a minimal (and awesome) interface between Ruby and webservers. This has many advantages, one of which is the ability to easily swap Rack applications (middlewares) in & out of your Rails app. Modularity FTW!
One fun (and useful) example of a Rack middleware is a Firebug logger written by Simon Jefford for the CodeRack competition. This middleware allows you to send arbitrary messages directly to Firebug. Why? Since you’re already debugging much of your Rails app in a browser anyway, sending debug output to your browser’s console (instead of tailing a log file) makes a lot of sense.
NOTE: FirebugLogger plays nice with WebKit’s Web Inspector as well.
Simon also released a Rails plugin that you can install to set up the middleware for you, but it’s more fun (and informative) to set it up yourself. Here’s how:
Setup
The goal is to be able to send arbitrary messages to Firebug from any controller or view.
Rails autoloads (and namespaces) any code placed in the lib directory, so that is where we’ll place our FirebugLogger code. Grab the code from my gist, which is a fork of Simon’s original with minor improvements, and place it inside your Rails app in:
lib/rack/firebug_logger.rb
Rails will load the code for us, but we need to manually activate the middleware. Since this bit of code is only useful during development, we’ll load it up in that environment only.
# config/environments/development.rb # ... other stuff ... config.middleware.use ::Rack::FirebugLogger
Using FirebugLogger
Using the middleware is pretty straight forward. It will process an array of arrays, each of which has a log level and a message. Add a single line like the one below to an existing controller action and load up the page:
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
def index
@posts = Post.all
request.env['firebug.logs'] = [[:info, "hello from rack!"]]
end
# ... other actions ...
end
Open Firebug and you should see “hello from rack!” glaring back at you. You can do the same thing in views:
# app/views/posts/index.html.erb <% request.env['firebug.logs'] = [[:warn, "inside a view!"]] %>
Adding a Helper
Using the logger like this is a bit tedious, and it’s not easy to create multiple messages for a single request. Let’s wrap the functionality up into a method that we can call. This method should be placed in the application controller so that all other controllers inherit it.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
# ... other stuff ...
helper_method :firebug
private
def firebug(message,type = :debug)
request.env['firebug.logs'] ||= []
request.env['firebug.logs'] << [type.to_sym, message.to_s]
end
end
This method will initialize an empty array the first time it is called and then push new messages on to the array on subsequent calls. Notice that it calls to_s on the message variable before passing it on. This means you can send the method a string or any object that responds to to_s and it will just work. Specifying a log type is optional, the method is private and it is explicitly added as a helper_method so that you can access it from views as well.
Now writing logs to Firebug is as easy as:
firebug "woop woop!" # optionally specify a log level firebug "it's a trap!", :warning
Here are a few ideas of helpful messages to send to Firebug:
# inspect the attributes of an object firebug @posts.first.inspect # dump the session firebug session # check a user's roles firebug current_user.roles.inspect
I highly encourage you to try this in one of your Rails apps. It has proven a useful addition to my toolkit. Let me know how it works for you by leaving a comment!
Jerod Santo is an Editor at Fuel Your Coding and a contract software developer at RSDi where he works daily with Ruby, JavaScript, and related technologies. He loves shiny toys, powerful tools, and open-source initiatives. Learn more about Jerod by visiting his homepage or following him on Twitter.

It was a great idea to put a rack middleware and firebug together. It has been remendously helpful to me, but I’ve ran into a problem that I think may be a bug.
The middleware works fine, until you try to map a route from within a namespace just like the following:
map.namespace :admin do |admin|
admin.resources :subjects do |subjects|
subjects.resources :topics do |topics|
end
end
Whenever I try to access “admin/subjects/1/topics” URI, it throws an unknown action error.
I’ve tried to debug by putting a “return @app.call(env)” into call method, it keep throwing though, therefore I think it’s a Rack bug.
Hi Bruno-
Try disabling the middleware piece (just comment out the line added to development.rb) and restart the application. If you still get an unknown action error then its not firebug_logger’s fault.
Let me know what happens, I’ll be glad to take a look at it otherwise.
Thank’s for replying.
I did that and it get back to normal, actually every rack middleware
I’ve enabled ran into the same problem, I also tried with a blank rails application.
I’m pretty sure that it’s a bug of rails and rack. I’m still using rails 2.3.5, so that I don’t know if it still happens at rails 3.
Hi
I have followed you instructions but I cannot get the autoloading “xxx/lib/rack/firebug_logger.rb” after running this in my dev env
config.middleware.use ::Rack::FirebugLogger
I’m using rails 3 – is there some extra trick?
thanks! x
Hi Sharron-
Rails 3 still autloads everything in the ‘lib’ directory, so that shouldn’t be the problem. You can confirm this by loading the console and typing:
firebug = ::Rack::FirebugLogger.new(”")
It looks like you can just call ‘use’ inside of the ApplicationController in Rails 3 instead of adding a config line to development.rb.
class ApplicationController < ActionController::Base
use Rack::FirebugLogger
end
However, I just tried it and I get an error the second time the middleware is used. Once Rails 3 comes out of beta I will update the middleware to work properly and update this post.
It should go in lib/ not app/lib.
Daniel-
You are absolutely right! My mistake, fixed now.