RailsのProduction環境でErrorを管理者にメールで自動通知する方法(ErrorMail on Rails)
categories: Ruby Rails tags: Error HowTo Programming Rails Ruby
アプリケーションを本番環境に移行すると、ブラウザではエラーの詳細が表示されませんし、ユーザはエラーの発生を教えてくれる訳ではありません。そこでエラーが発生したときには、エラーメッセージの内容を、管理者へ自動的にメールしてくれると助かります。
今回はRailsでエラーメッセージを自動送信する方法についてです。内容はRails本に書いてある通りだけど。
| RailsによるアジャイルWebアプリケーション開発 | |
![]() | 前田 修吾 オーム社 2006-02-25 売り上げランキング : 14017 Amazonで詳しく見るby G-Tools |
まず、Railsでエラーが発生した場合、必ず呼ばれるメソッドが、
rescue_action_in_public(exception)
です。こいつをオーバーライドすることで、エラーメッセージを送信できるようにしてやります。
まず、ApplicationControllerに以下のメソッドを追加します。(app/controllers/application_controller.rb)
def rescue_action_in_public(exception)
case exception
when ActiveRecord::RecordNotFound
flash[:notice] = "404 NOT FOUND"
render(:file => "#{RAILS_ROOT}/public/404.html", :status => "404 NOT FOUND")
SystemNotifier.deliver_exception_notification(self, request, exception)
else
flash[:notice] = "500 ERROR"
render(:file => "#{RAILS_ROOT}/public/500.html", :status => "500 ERROR")
SystemNotifier.deliver_exception_notification(self, request, exception)
end
end
この中の
SystemNotifier.deliver_exception_notification(self, request, exception)
とうやつが、エラーメッセージを送信する部分です。
次にSystemNotifierモデルを定義します。(app/models/system_notifiler.rb)
require "pathname"
class SystemNotifier < Iso2022jpMailer
SYSTEM_EMAIL_ADDRESS = %{"YourApplication::ErrorNotifier" <エラーメッセージの送信元アドレス>}
EXCEPTION_RECIPIENTS = %w{エラーメッセージの送信先アドレス}
def exception_notification(controller, request, exception, sent_on=Time.now)
@subject = sprintf("[ERROR on WANTED] %s#%s (%s) %s", controller.controller_name,
controller.action_name,
exception.class,
exception.message.inspect)
@body = { :controller => controller,
:request => request,
:exception => exception,
:backtrace => sanitize_backtrace(exception.backtrace),
:host => request.env["HTTP_HOST"],
:rails_root => rails_root }
@sent_on = sent_on
@from = SYSTEM_EMAIL_ADDRESS
@recipients = EXCEPTION_RECIPIENTS
@headers = {}
end
private
def sanitize_backtrace(trace)
re = Regexp.new(/^#{Regexp.escape(rails_root)}/)
trace.map do |line|
Pathname.new(line.gsub(re, "[RAILS_ROOT]")).cleanpath.to_s
end
end
def rails_root
@rails_root ||= Pathname.new(RAILS_ROOT).cleanpath.to_s
end
end
それからエラーメッセージのテンプレートを用意します。(app/views/system_notifier/exception_notification.rhtml)
<% require 'pp' %> A <%= @exception.class %> occured in <%= @controller.controller_name %>#<%= @controller.action_name %>: <%= @exception.message %> <%= @backtrace.first %> **** リクエスト情報 **** URL:<%= @request.protocol %><%= @host %><%= @request.request_uri %> パラメータ:<%= @request.parameters.inspect %> リファラ:<%= @request.referer %> Railsルート:<%= @rails_root %> **** セッションダンプ **** <% for variable in @request.session.instance_variables -%> <% next if variable =~ /^@db/ -%> <%= variable %>: <%= PP.pp(@request.session.instance_variable_get(variable), "").gsub(/\n/, "\n").strip %> <% end -%> **** 環境 **** <% for key, value in @request.env -%> <%= key %>:<%= value.to_s.strip %> <% end -%> **** フル実行バックトレース **** <%= @backtrace.join "\n " %> エラー発生時刻 <%= Time.now %>
これでRailsアプリケーションで発生したエラーは自動的に設定した送信先にメールされます。ただしApplicationControllerまで処理が渡された場合のみですが。(ルーティングエラーなどは補足できないので、config/routes.rbでコントローラが見つからなかったりしてもメールは来ない)
注)ちなみに、こんなのもあります。Railsでエラーが起こったらメールで通知するプラグイン
