😎

Railsアプリのエラー追跡にSentryを使ってみた

2024/11/30に公開

https://zenn.dev/syokunin/scraps/3bbfea50cc9850
スクラップから移行して作成した記事です。
自分自身何度も読み直しているので記事に移行しました。

Sentryとは

https://sentry.io/welcome

Sentryは、アプリケーションのパフォーマンス監視とエラー追跡ソフトウェアです。Sentryは、開発者がアプリケーションのエラーを修正するのに役立ちます。

Sentryは、エラーを特定、デバッグ、解決できます。また、エラーを優先順位付けして、最も多くの顧客に影響を与えているエラーを表示できます。さらに、Sentryは、パフォーマンスの問題を自動的に検出して開発者に通知することもできます。

Sentryは、Webアプリケーション、モバイルアプリケーション、サーバーアプリケーションなど、さまざまな種類のアプリケーションで使用できます。

by Gemini

導入

https://docs.sentry.io/platforms/ruby/guides/rails/
https://github.com/getsentry/sentry-ruby/tree/master/sentry-rails/examples/rails-7.0

# config/initializers/sentry.rb
Sentry.init do |config|
  config.dsn = ENV['SENTRY_DSN']
  config.enable_tracing = true
  config.traces_sample_rate = 0.1
end
  • dsn
  • enable_tracing
    • パフォーマンス測定を使用するため、trueにしました。
  • traces_sample_rate
    • 1.0 を設定すると、すべてのイベントを送信することを意味します。お試しのため、0.1としました。

Sentryで用意されているエラー通知用のメソッドを仕込む

    begin
      1 / 0
    rescue ZeroDivisionError => exception
      Sentry.capture_exception(exception)
    end

このようなコードです。
お試しで0除算によるエラーを発生させています。
それでは動作確認をしてみます。

SentryのIssuesに通知されていることが確認できました。

任意のタイミングで通知を出したい

Sentry.capture_message("test message")

capture_messageメソッドで通知を飛ばすことができます。

エラーレポーターにサブスクライブする

https://railsguides.jp/error_reporting.html

Rails 7.1 では、ErrorReporter という機能を使用できます。

1.1 エラーレポーターにサブスクライブする
エラーレポーターを利用するにはサブスクライバ(subscriber)が必要です。サブスクライバは、reportメソッドを持つ任意のオブジェクトのことです。アプリケーションでエラーが発生したり、手動で通知されたりすると、Railsのエラーレポーターはエラーオブジェクトといくつかのオプションを使ってこのメソッドを呼び出します。
SentryやHoneybadgerなどのように、自動的にサブスクライバを登録してくれるエラー通知ライブラリもあります。詳しくはプロバイダのドキュメントを参照してください。

ふむ・・・なるほど、ということでRailsガイドのリンクからsentry-rubyのソースコードを見てみます。

https://github.com/getsentry/sentry-ruby/blob/e18ce4b6dcce2ebd37778c1e96164684a1e9ebfc/sentry-rails/lib/sentry/rails/error_subscriber.rb

すでにsentry-rubyでエラーレポーターが定義されていました。

config.rails.register_error_subscriber = true

を設定するだけで、エラーレポーターにサブスクライブできるらしいので、

Rails.error.handle(NameError) do
  do_something
end

テストで上記のようなコードを仕込みました。

エラーがSentryに通知されました。

Rails.error.handleをおさらい

Rails.error.handle(NameError) do
  do_something
end

先ほど登場したこのコードの引数NameErrorを無くすとどうなるでしょうか。

Railsのコードを覗いてみます。

https://github.com/rails/rails/blob/35e3ff3667872598f901979cafcc5ac1bf3cd71e/activesupport/lib/active_support/error_reporter.rb#L29

https://github.com/rails/rails/blob/35e3ff3667872598f901979cafcc5ac1bf3cd71e/activesupport/lib/active_support/error_reporter.rb#L78-L84

StandardError がデフォルトで設定されるため、すべてのエラーをキャッチして、通知を出してくれるような実装になっているようです。

ちなみにRailsガイドにも書いてありますが、

1.2.1 エラーを通知して握りつぶす
Rails.error.handle は、ブロック内で発生したエラーを通知してから、そのエラーを握りつぶします。ブロックの外の残りのコードは通常通り続行されます。

エラーは握り潰されるので、スルーされたくない処理には使用しない、または一工夫する必要がありそうです。

Rails.error.handleの戻り値

user = Rails.error.handle(fallback: -> { User.anonymous }) do
  User.find_by(params[:id])
end

Rails.error.handleは戻り値を受け取ることができ、例外が発生した場合の値も設定できます。

Rails.error.record

似たようなメソッドでRails.error.recordがあります。

https://github.com/rails/rails/blob/35e3ff3667872598f901979cafcc5ac1bf3cd71e/activesupport/lib/active_support/error_reporter.rb#L114-L120

例外を握り潰さず、raiseするようになっています。

Rails.error.report

begin
  # code
rescue StandardError => e
  Rails.error.report(e)
end

Rails.error.reportを呼び出して手動でエラーを通知することも可能です。

SMARTCAMP Engineer Blog

Discussion