#104 Exception Notifications (revised)
- Download:
- source codeProject Files in Zip (81.1 KB)
- mp4Full Size H.264 Video (21.7 MB)
- m4vSmaller H.264 Video (10.2 MB)
- webmFull Size VP8 Video (8.56 MB)
- ogvFull Size Theora Video (31.4 MB)
Railsアプリケーションが複雑になるにつれ、例外が発生しやすくなります。一方下の図はとてもシンプルなアプリケーションで、大きな赤いボタンを持っています。
このシンプルなアプリケーションは、大きな赤いボタンをクリックすると例外を発生させます。
本番環境のアプリケーションで例外が発生したとき、エンドユーザがこのような詳細な情報を見ることはありません。その代わりに一般的なエラーページが表示されます。開発者としての我々の目的はこのページが決して表示されないようにすることで、エラーを根絶するために例外が発生したら通知を受けるようにしたいと思います。
アプリケーションに例外を通知する方法はいろいろありますが、今回はException Notification gemを使用します。これは古いプラグインですが、Sebastian Martinezによって今でもよくメンテナンスされています。設定が簡単で、例外が発生するごとにメールを送信します。Rackミドルウェアなので、設定項目の調整も簡単です。必要な作業は、対応する environmentの設定ファイルに1行追加するだけです。
Exception Notificationをインストールする
Exception Notificationのインストールは簡単です。Gemfile
に参照情報を追加してbundle
コマンドを実行するだけです。
source 'http://rubygems.org' gem 'rails', '3.1.1' gem 'sqlite3' # Gems used only for assets and not required # in production environments by default. group :assets do gem 'sass-rails', '~> 3.1.4' gem 'coffee-rails', '~> 3.1.1' gem 'uglifier', '>= 1.0.3' end gem 'jquery-rails' gem 'exception_notification'
インストールできたら/config/environment
ディレクトリの設定ファイルの一つで設定をできます。通常はproduction.rb
ファイルに追記しますが、今は試している状態なので、まずはdevelopment.rb
に追記して動作を見てみることにします。ファイルのブロックの最後に次のコードを追加します。
config.middleware.use ExceptionNotifier, sender_address: 'noreply@asciicasts.com', exception_recpients: 'eifion@asciicasts.com'
ここでいくつかのオプションを設定できますが、今はとりあえずsender_address
とexception_recipients
だけを設定します。recipientsに単純な文字列を使用しましたが、複数のアドレスにメールを送信したければ配列を使用します。
ExceptionNotifier
がメールを送信するので、action_mailer.delivery_method
を設定する必要があります。開発モードでdeliveryメソッドを設定するのは手間なので、これを簡単に行うためにLetter Openerというgemを利用します。このgemはアプリケーションが送信しようとするEメールをWebブラウザで開きます。いつもと同じようにこのgemをGemfile
に追加しbundle
を実行してインストールします。
gem 'letter_opener', group: :development
このgemがインストールされたら、:letter_opener
をdeliveryメソッドとして使用できます。
config.action_mailer.delivery_method = :letter_opener
アプリケーションの大きなボタンを押すと例外が表示されますが、今回は別のウィンドウが開いて送信されようとするメールがそこに表示されます。
このメールには発生した例外の詳細情報が含まれています。タイトルが[ERROR]
という文字を含んで、それらに簡単にフィルターをかけて別のフォルダに分けられるようにしています。
Exception Notifierのカスタマイズ
Exception Notifierミドルウェアをカスタマイズする方法がいくつかあります。例えばFor example we can add options to specify the email prefix (instead of the default [ERROR]
) or change the content of the email by passing in a :sections
option . 追加で増やしたい情報を含む独自のセクションを追加することもできます。これらについてはここでは変更は行いませんが、ドキュメントには詳しく記述されていない別のオプションを一ヶ所変更します。その前にソースコードの対応する部分を見てみて動作のしくみを理解します。ExceptionNotifier
クラスにはdefault_ignore_exceptions
というオプションが含まれていて、このファイルのソースコードにはException Notifierが無視する例外のリストがあります。
def self.default_ignore_exceptions [].tap do |exceptions| exceptions << ::ActiveRecord::RecordNotFound if defined? ::ActiveRecord::RecordNotFound exceptions << ::AbstractController::ActionNotFound if defined? ::AbstractController::ActionNotFound exceptions << ::ActionController::RoutingError if defined? ::ActionController::RoutingError end end
これらのエラーは、通常500ではなく404を投げるので無視されます。もしメールを受けとりたくないエラーについてアプリケーションが例外を投げる場合、それを無視する例外のリストに追加できます。アプリケーションが意図的に投げる例外はRuntimeError
なので、これをリストに追加します。
config.middleware.use ExceptionNotifier, sender_address: 'noreply@asciicasts.com', exception_recpients: 'eifion@asciicasts.com', ignore_exceptions: ExceptionNotifier.default_ignore_exceptions + [RuntimeError]
この変更を有効にするためにサーバを再起動します。再起動後、大きな赤いボタンをクリックすると相変わらず例外は投げられますが、Eメールは届きません。本番稼動するアプリケーションではRuntimeErrorは重要なので無視したくないですが、その他に例えばボットの訪問を受けたときのように無視してもいい例外もあります。
これでException Notifierを好きなように設定できるようになったので、development.rb
に書いたコードをproduction.rb
に移動します。また本番稼動モードではLetter Openerを使う代わりに実際のEメールが送信されるようにdeliveryメソッドを設定します。
その他の選択肢
Exception Notification gemの設定方法についての説明は以上です。使い方が簡単で、とても有用です。メール通知をしない方法を求めるなら、いくつか他の選択肢があります。一つ目はWhoopsです。これは例外の通知をMongoDBに保存し、表示用のユーザインタフェースを提供します。もう一つはAirbrakeで、以前はHoptoadという名前でした。これは有料サービスですが、Githubとの統合など他にはない機能を提供します。
これらのいずれもニーズに合わない場合は、mountable engineを使っていつでも自分で作成することが可能です。まさにその方法をエピソード277でも紹介しましたが、決して難しくはありません。