Posted over 7 years ago. Visible to the public.

Get notified when your application raises an error

This card describes how to configure your project so that application errors are sent to an e-mail address of your choice.

I improved the process by adding HTTP basic authentication to the /errors/new and also added a spec to keep people from accidentally disabling error notifications.

Please keep this card private because it contains credentials and mentions our fail@makandra.de address.

1) Install the Exception Notifier plugin

Be aware that the Exception Notifier plugin will send sensitive information like the session id or even the rails secret token for rails > 4 with its default settings! To prevent this, we do not use all information the plugin provides. We omit the session and environment sections and only use request and backtrace sections which provide enough information for debugging. This is done by manually provide the sections that should be used (see below).

For background_sections we only use the backtrace section, because on background jobs (e.g. cron jobs) no request is available. This is important, because exception notifier will raise an error itself if it tries to render a request section that is not available and therefore not send a notification!

Rails 4+:
For Rails 4, the Exception Notifier comes as a gem. Add the following to your Gemfile:

Copy
gem 'exception_notification'

Now run bundle install.

Now configure the notifier in config/initializers/exception_notification.rb:

Copy
require 'exception_notification/rails' ExceptionNotification.configure do |config| config.add_notifier :email, { email_prefix: "[myapp] ", sender_address: 'fail@makandra.de', sections: %w(request backtrace), background_sections: %w(backtrace), exception_recipients: ['fail@makandra.de'] } config.ignored_exceptions += [ 'ActionController::InvalidAuthenticityToken' # Occurs with tabbed browsing ] end

Rails 3:

For Rails 3, the Exception Notifier comes as a gem. Add the following to your Gemfile:

Copy
gem 'exception_notification'

Now run bundle install.

Now configure the notifier in application.rb.

If you are using a version of exception_notification >= 4.0.0 you need to say:

Copy
config.middleware.use ExceptionNotifier::Rack, :email => { :sender_address => 'fail@makandra.de', :exception_recipients => %w[ fail@makandra.de ], :email_prefix => "[myapp] ", :email_format => :html, :sections => %w[request backtrace], :background_sections => %w[backtrace] }

If you are using a lesser version:

Copy
config.middleware.use ExceptionNotifier, :sender_address => 'fail@makandra.de', :exception_recipients => %w[ fail@makandra.de ], :email_prefix => "[myapp] ", :email_format => :html, :sections => %w[request backtrace], :background_sections => %w[backtrace]

Restart your server and you're done.

Rails 2:

For Rails 2, the Exception Notifier comes as a Rails plugin. Run the following command from your console:

Copy
script/plugin install https://github.com/smartinez87/exception_notification.git

Configure the notifier in environment.rb:

Copy
ExceptionNotification::Notifier.sender_address = 'fail@makandra.de' ExceptionNotification::Notifier.exception_recipients = %w[ fail@makandra.de ] ExceptionNotification::Notifier.email_prefix = "[myapp] " ExceptionNotification::Notifier.sections = %w[request backtrace]

Add the following your ApplicationController:

Copy
include ExceptionNotification::Notifiable

Restart your server and you're done.

2) Create a controller to manually test exception notifications

Many things can prevent your notifications from being delivered (e.g. the application server cannot send mail). Hence you should manually test that exceptions are sent and received.

To do this we will create a controller for the sole purpose of raising a test error.

We want the controller to respond to the path /errors/new. Add the following route to your config/routes.rb:

Copy
# Rails 3: resources :errors, :only => :new # Rails 2: map.resources :errors, :only => 'new'

Now add the controller itself in app/controllers/errors_controller.rb:

Copy
class ErrorsController < ApplicationController # Prevents Consul's "never forget a power check" exception Consul::UncheckedPower # skip_power_check before_action :basic_authentication def new raise 'This is a test error. All is well.' end private def basic_authentication authenticate_or_request_with_http_basic do |user, password| user == 'admin@makandra.de' && password == 'foo123matic' # secret_sentry:no_secret end end end

The controller action will be protected by HTTP basic authentication (admin@makandra.de / foo123matic).

Be aware that basic authentication cannot be nested. If your staging root is already protected by basic authentication, you either have to use the same credentials in ErrorsController or you disable the basic authentication for this environment in basic_authentication (e.g. use unless (Rails.env == 'staging')).

3) Prevent other people from disabling exception notifications

Note that the spec below only works for Rails < 3.2.

Copy
require 'spec_helper' describe ErrorsController do describe '#new' do it 'should deliver a test error through the exception notifier' do credentials = ActionController::HttpAuthentication::Basic.encode_credentials 'admin@makandra.de', 'foo123matic' request.env['HTTP_AUTHORIZATION'] = credentials controller.should_receive(:notify_about_exception).with('test error') expect { get :new }.to raise_error(/test error/) # it's kind of hard to get Rails to handle errors in RSpec, so we call this method directly controller.send :rescue_action_in_public, 'test error' end end end

4) Manually test exception notification

  1. Deploy to staging.
  2. Go to http://yourapp.com/errors/new and enter the credentials admin@makandra.de / foo123matic.
  3. Make sure there's a notification e-mail in fail@makandra.de.

Note this when you test the setup on staging:
- For some (external) projects we don't send email on staging, so you will not receive the exception mails.
- For some projects we have basic authentication for the whole application. This will conflict with the second basic authentication in errors controller and you will always get a 401 Unauthorized error. You might want to have the before filter :basic_authentication unless Rails.env.staging? or if Rails.env.production?. Another solution is to reuse the same credentials.

Once an application no longer requires constant development, it needs periodic maintenance for stable and secure operation. makandra offers monthly maintenance contracts that let you focus on your business while we make sure the lights stay on.

Owner of this card:

Avatar
Henning Koch
Last edit:
4 months ago
by Jakob Scholz
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Henning Koch to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more