ProblemDuring 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. SolutionInstall 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" DiscussionAfter 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:
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
|