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 software. Learn more about Jerod by visiting his homepage or following him on Twitter.

 

If you liked this article, please help spread the news on the following sites:

  • Bump It
  • Blend It
  • Bookmark on Delicious
  • Stumble It
  • Float This
  • Reddit This
  • Share on FriendFeed
  • Clip to Evernote