SyntaxHighlighter

Monday, March 01, 2010

Rails Exception Logger Plugin

This is simple to set up, but not so easy to find on the web. Just writing it down so it's easier to find in one place.

First install the plugin. Do this from the app_root directory.

script/plugin install git://github.com/defunkt/exception_logger.git

Next, generate the migration and run it:

script/generate exception_migration
rake db:migrate

Add this to your ApplicationController

class ApplicationController
include ExceptionLoggable

Then, add to routes the following:

map.connect "logged_exceptions/:action/:id", :controller => "logged_exceptions"

Restart your system to pick up the plugin.

Pagination
To get pagination working with will_paginate, go into plugins/exception_logger/init.rb and modify it so it looks like this.

#$PAGINATION_TYPE = 'none'
require 'will_paginate'
$PAGINATION_TYPE = 'will_paginate'
WillPaginate.enable
#require 'paginating_find'
#$PAGINATION_TYPE = 'paginating_find'
LoggedExceptionsController.view_paths = [File.join(directory, 'views')]

And, in my case, I didn't have redcloth installed, so I modified plugins/exception_logger/views/logged_exceptions/_show.rhtml

I removed textilize and used 'simple_format'

By the way, there is part of the logged_exceptions README that encourages you to overwrite a few methods, including render_404(exception)

To do this, you would do something like the following. In your application_controller:

def render_404(exception)
log_exception(exception)
render :file => '/errors/400', :status => 400
end

This would be good if you wanted to reuse your layouts and show a dynamic page instead of using one of the static pages in the /public directory.

One last thing
If you want to restrict access to the logged_exception controller and you are using authlogic from binary logic, here is one way to do it:

In authorization_rules.rb, add the privilege to manage logged_exceptions

role :administrator do
has_permission_on :logged_exceptions, :to => :manage
end

Then, in the plugins/exception_logger/lib/logged_exceptions_controller.rb

I changed the file to look like this:

class LoggedExceptionsController .. ApplicationController

filter_access_to :query, require => :manage
filter_access_to :destroy_all, :require => :manage

And - the icing on the cake. I a free rss app for the iphone. Entered the url for the rss feed with the authlogic user_credentials parameter attached to the url

http://yourapp.com/logged_exceptions?format=rss&user_credentials=single_access_token

You can get the single_access_token from the user table - just use your admin user to access the rss feed. Very handy to have an rss feed of the latest exceptions right on your iphone. You can also modify the views to add more information to the rss item if you need to.

3 comments:

  1. Anonymous7:13 PM

    Thanks for posting this, very helpful. You could maybe suggest some change to the README.

    ReplyDelete
  2. Anonymous4:09 PM

    Nice to see validation for the exception logger. I saw it on railscasts but both the video and the last update to the plugin were so old I was worried it won;t work.
    Kudos!!

    ReplyDelete
  3. Anonymous8:05 PM

    Great article. Everything went fine except when trying to secure access to '/logged_exceptions'.

    Tried several things which all failed. Ended up doing the following. Maybe it'll be helpful to someone.

    logged_exceptions_controller.rb:
    before_filter :authorizeme

    def authorizeme
    # get current user id, if none, do not allow access

    unless session['user_credentials_id'].nil?
    user ||= User.find(session['user_credentials_id'])
    else
    flash[:error] = "Access Denied for " + controller_name.titleize
    redirect_to home_url and return
    end

    # Check if user has security role, if not, do not allow access

    unless user.security_role?("admin")
    flash[:error] = "Access Denied for " + controller_name.titleize
    redirect_to home_url and return
    end
    end

    user.rb:

    def security_role?(security_role)
    security_roles.collect{|r| r.name}.include? security_role.to_s
    end

    ReplyDelete