2012年8月3日金曜日

Herokuのエラー処理

Ruby on Rails3で作成したアプリをHeroku上で動かす際のエラー処理についてのまとめです。

環境はruby-1.9.3-p0, rails3.2.2, postgres, Herokuです。

難易度★★★☆☆

はじめに

この記事はHeroku上で動くアプリのエラーをどう扱うかを試行錯誤したまとめです。正直、あまり良い方法とは思えなかったのですが、現在は記事の内容で対応しています。

対応方法

アプリに例外が発生したらエラーのメールを投げることでエラーを管理者が確認できるようにしました。
exceptional_notificationというpluginが例外を自動キャッチしてメールを投げてくれるのですが、私のアプリは独自処理で例外をキャッチしていたのでexceptional_notificationを使用できませんでした。なので、自分で実装することになりました。

詳細

Heroku

Herokuは,Ruby on Rails/RubyのWebサービスのホスティングサービスです。無料で手軽にWEBサービスを構築することができ、アプリケーションの負荷が高くなれば有料にすることもできます。
小さくはじめるスタートアップに非常に向いているサービスです。

Herokuログ

Herokuのlogはターミナルから「heroku logs」で確認できます。logの内容はproduction.logです。

Herokuログの問題点

log rotateができません。なのにアプリが動作している限りログは追記されていくので、後でエラーの原因を調査しようと思っても、ログを追うことができません。

エラー処理仕様

  • 例外はキャッチして独自のエラーページを使用する。しかし、例外を独自処理でキャッチした場合exceptional_notificationは使えない。
  • exceptional_notificationのようにエラー発生時にメールを送りたい。でも、独自で例外を補足したい。
  • 有料のadd-onやサービスは利用したくない。なるべく無料が良い。
  • 無料のheroku logsだけでは不安である。エラーは発生時に知りたい。

我がまま過ぎるって?でも、そんなもんです人間は。金がないなら知識と技術で解決しましょう。さあ実装です。

Gmailを使う

エラーメッセージのお知らせにはgmailを利用します。無料で一日500件まで使えます。500件以上利用する場合は、あきらめてメールサーバーを立てるか有料サービスを使いましょう。サービス立ち上げ時には十分な件数のはずです。

/config/environments/production.rbに設定を記載します。


  config.action_mailer.default_url_options = { :host => 'your_app.heroku.com' }
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :address => 'smtp.gmail.com',
    :port => 587,
    :domain => 'your.host.name', # if local,  localhost.localdomain    
    :user_name => "your_username", # full email address (user@your.host.name.com)
    :password => "your_password",
    :authentication => 'plain',
    :enable_starttls_auto => true,
  }

開発環境でも利用したい場合は/config/environments/development.rbにコピーしてください。
GmailでIMAPが利用できるように設定されていることも確認してください。
GmailでIMAPを有効化にする

mailerを作成


  rails g mailer TestMailer sendmail_confirm

メーラーを作成します。作成されたコントローラー/app/mailers/test_mailer.rbに処理を記述します。


class TestMailer < ActionMailer::Base
  default :from => 'full email address'

  # Subject can be set in your I18n file at config/locales/en.yml
  # with the following lookup:
  #
  #   en.notice_mailer.sendmail_confirm.subject
  #
  def sendmail_confirm(exception)
    @exception = exception
    mail :to => "send_email_address", :subject => '[Web application Error]'
  end
end

sendmail_confirmアクションは引数で例外を受け取っています。
mailメソッドを呼び出すタイミングで、テンプレートtest_mailer/sendmail_confirm.text.erbが呼び出されます。
text.erbには、メールの内容を記述します。

text.erbを作成


エラーが発生しました、

<%= @exception.message %>

エラーの内容を出力するようにしています。他にも欲しい情報があれば、ここに記述します。

独自エラー処理に追加

独自エラー処理はapplication_controller.rbで処理するのが一般的です。なので、ここに作成したメール処理を追加します。


  # 例外ハンドル
  # ルーティングエラーと、データが見つからない場合は404エラー扱い
  rescue_from ActionController::RoutingError, ActiveRecord::RecordNotFound, :with => :render_404
  rescue_from Exception, :with => :render_500

  # 404エラーはログを取りエラー画面を表示
  def render_404(exception = nil)
    if exception
      logger.info "Rendering 404 with exception: #{exception.message}"
    end

    flash[:msg] = 'ページは見つかりませんでした。'
    render 'shared/error' , :status => 404
  end

  # 500エラーはログを取りエラー画面を表示
  def render_500(exception = nil)
    if exception
      NoticeMailer.sendmail_confirm(exception).deliver 
    end

    flash[:msg] = 'サーバーエラーが発生しました。'
    render 'shared/error', :status => 500 # statusがないとcompleted OKになってしまう。
  end

赤い太文字の箇所が追加した処理です。メールでエラーを投げて、独自のエラー画面に遷移するようにしています。

ユーザーは大きな不具合以外は意外と報告してくれないので、メールでエラーが送信される仕組みはあると便利だと思います。

以上です。


参考サイト

この記事がお役にたちましたらシェアをお願いします

このエントリーをはてなブックマークに追加

0 件のコメント:

コメントを投稿

Related Posts Plugin for WordPress, Blogger...