Recipe 10.6. Emailing Application Exceptions


Problem

During development, you watch the log closely as you exercise new features. When your application fails, you usually see it in the logs and in your browser. Once the application moves to production, the burden of reporting errors often falls on your users. This is far from ideal. If an error occurs, you want to be the first one on the scene with a fixif possible, even before the users notice. To make this kind of awareness feasible, you want the application to send an email when critical exceptions are thrown.

Solution

Install the exception notification plug-in and have critical application errors emailed to your development team. From the root of your application, run:

$ ruby script/plugin install \ >     http://dev.rubyonrails.com/svn/rails/plugins/exception_notification/             

With the plug-in installed, the next step is to mix-in the plug-in's ExceptionNotifiable module by adding include ExceptionNotifiable to the controllers that you want to send exception notifications. To enable this behavior application-wide, put this line in application.rb:

app/controllers/application.rb:

class ApplicationController < ActionController::Base   include ExceptionNotifiable   #... end

The remaining step is to specify one or more recipients for the emails in environment.rb:

config/environment.rb:

ExceptionNotifier.exception_recipients = %w(rob@railscookbook.org                                             bugs@railscookbook.org)

By default, the plug-in does not send email notifications for local requests, that is, requests with an IP address of 127.0.0.1. (The assumption is that local requests are coming from a developer, who should be watching the logs.) If you want the plug-in to send notifications for exceptions that occur while handling local requests, and you are in development mode, set the following config option in environments/development.rb to false:

environments/development.rb:

config.action_controller.consider_all_requests_local = false

If your application is not running in development mode, this option is likely set to TRue. In any case, setting it to false allows you to override what Rails considers a local request. The following line effectively tells the plug-in that no addresses are to be considered local:

app/controllers/application.rb:

class ApplicationController < ActionController::Base   include ExceptionNotifiable   local_addresses.clear   #... end

On the other hand, if you want to expand the definition of local to include a specific IP address to list of addresses, you can pass them to consider_local in your controller:

consider_local "208.201.239.37"

Discussion

After restarting the server, the next time your application throws a critical exception an email with the exception name and environment details is emailed to the address you specified. The following Rails exceptions are not considered critical and will result in HTTP 404 errors: RecordNotFound, UnknownController, and UnknownAction. All other errors result in an HTTP 500 response, and an email is sent.

To test the plug-in, you can throw a specific exception that you know will trigger the notification mechanism. For example, create a Test Controller with an index action that tries to divide by zero.

app/controller/test_controller.rb:

class TestController < ApplicationController   def index     1/0   end end

Web requests to this action will throw a ZeroDivisionError exception and send an email that will look something like this:

From: Application Error <app.error@localhost> To: rob@orsini.us Subject: [APP] test#index (ZeroDivisionError) "divided by 0" Content-Type: text/plain; charset=utf-8 A ZeroDivisionError occurred in test#index:   divided by 0   [RAILS_ROOT]/app/controllers/test_controller.rb:4:in `/' ------------------------------- Request: -------------------------------   * URL: http://localhost:3000/test   * Parameters: {"action"=>"index", "controller"=>"test"}   * Rails root: /Users/orsini/rails-cookbook/recipes/Debugging/     Emailing_Application_Exceptions ------------------------------- Session: -------------------------------   * @new_session: false   * @data: {"flash"=>{}}   * @session_id: "ab612d8b4e83664a1d7c1f52bea87ef4" ------------------------------- Environment: -------------------------------   * GATEWAY_INTERFACE   : CGI/1.2   * HTTP_ACCEPT         : text/xml,application/xml,application/xhtml+xml, text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5   ... ------------------------------- Backtrace: -------------------------------   [RAILS_ROOT]/app/controllers/test_controller.rb:4:in `/'   [RAILS_ROOT]/app/controllers/test_controller.rb:4:in `index'   ...

To configure the sender address of the emails, set the sender_address for your environment:

ExceptionNotifier.sender_address =     %("Application Error" <app.error@yourapp.com>)

You can also configure the prefix of the subject line in the emails sent, with:

ExceptionNotifier.email_prefix = "[YOURAPP] "

The plug-in comes with a nice facility for configuring the body of the email. To override the default message, create specially named partials in a directory named app/views/exception_notifier. The default email body contains four sections, as defined in this line from the ExceptionNotifiable module definition:

@@sections = %w(request session environment backtrace)

You can customize the order or even the format of these sections. To change the order and exclude the backtrace section, for example, add this line to your environment configuration:

ExceptionNotifier.sections = %w(                   
request environment session
)

So, to override the layout of the request section, you create a file named _request.rhtml and place it in app/views/exception_notifier. The following variables (from the plug-in's RDoc) are available to use within your customized templates:


@controller

The controller that caused the error


request

The current request object


@exception

The exception that was raised


@host

The name of the host that made the request


@backtrace

A sanitized version of the exception's backtrace


@rails_root

A sanitized version of RAILS_ROOT


@data

A hash of optional data values that were passed to the notifier


@sections

The array of sections to include in the email

By creating the following partial, the environment section of the notification email displays only the address of the host the request originated from and the user agent:

app/views/exception_notifier/_environment.rhtml:

* REMOTE_ADDR : <%= request.env['REMOTE_ADDR'].to_s %> * HTTP_USER_AGENT : <%= request.env['HTTP_USER_AGENT'].to_s %>

Such a partial produces this environment section within the email:

------------------------------- Environment: -------------------------------   * REMOTE_ADDR : 127.0.0.1   * HTTP_USER_AGENT : Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O;  en-US; rv:1.8.0.4) Gecko/20060508 Firefox/1.5.0.4

See Also

  • Section 9.5"




Rails Cookbook
Rails Cookbook (Cookbooks (OReilly))
ISBN: 0596527314
EAN: 2147483647
Year: 2007
Pages: 250
Authors: Rob Orsini

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net