[Rails] レンダリングストリーム中のエラーを Rails.error に報告可能に

rails/rails

Context

Railsのストリーミングレンダリング機能では、レスポンスを部分的にクライアントに送信しながらビューをレンダリングできます。しかし、ストリーミング中にエラーが発生した場合、既にHTTPヘッダーが送信済みのため通常のエラーハンドリングが機能しません。

これまでストリーミング中のエラーは単にログに記録されるだけで、SentryやBugsnagなどのエラー監視サービスには通知されませんでした。これらのサービスは通常 ShowExceptions ミドルウェアにフックしてエラーを捕捉しますが、ストリーミングレンダリングではそのタイミングを逃してしまうためです。

Rails 7.0で導入された ActiveSupport::ErrorReporter API(Rails.error)により、この問題が解決されました。

Technical Detail

エラー報告メカニズムの変更

変更前:

def log_error(exception)
  logger = ActionView::Base.logger
  return unless logger

  message = +"\n#{exception.class} (#{exception.message}):\n"
  message << exception.annotated_source_code.to_s if exception.respond_to?(:annotated_source_code)
  message << "  " << exception.backtrace.join("\n  ")
  logger.fatal("#{message}\n\n")
end

変更後:

def log_error(error)
  if ActiveSupport.error_reporter
    ActiveSupport.error_reporter.report(error)
  elsif logger = ActionView::Base.logger
    message = +"\n#{error.class} (#{error.message}):\n"
    message << error.annotated_source_code.to_s if error.respond_to?(:annotated_source_code)
    message << "  " << error.backtrace.join("\n  ")
    logger.fatal("#{message}\n\n")
  end
end

主な変更点

  1. ErrorReporter優先: ActiveSupport.error_reporter が利用可能な場合、それを使用してエラーを報告
  2. 後方互換性: ErrorReporterが未設定の場合は従来通りロガーにフォールバック
  3. 統一されたエラー処理: Rails.error.handleRails.error.record で設定されたハンドラーがストリーミングエラーも捕捉可能に

実装上の注意点

begin
  @start.call(block)
rescue => error  # Exception から => に変更
  log_error(error)
  block.call ActionView::Base.streaming_completion_on_exception
end

rescue Exception から rescue => に変更することで、SignalExceptionSystemExit などの致命的な例外を捕捉しないようになりました。これはRubyのベストプラクティスに準拠した変更です。

テストの追加

新しいテストケースでは、エラーが正しく報告されることを検証しています。

test "rendering with template exception reports error" do
  error_report = assert_error_reported do
    get "/render_streaming/basic/template_exception"
  end
  assert_match "Ruby was here!", error_report.error.message
end

Impact

この変更により、以下のような利点があります。

  • エラー監視の完全性: Sentry、Bugsnag、Honeybadgerなどのサービスでストリーミングエラーも追跡可能に
  • 統一されたエラーハンドリング: アプリケーション全体で一貫したエラー処理が可能
  • デバッグの容易化: 本番環境でのストリーミングエラーを見逃さない

既存のコードへの影響はなく、ErrorReporterが設定されていない環境では従来通りの動作を維持します。

記事メタデータ

Generated by:
Claude Sonnet 4.5 for DiffDaily

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

ガイドライン準拠 ✓ PASS

記事構成とDiffDaily Styleへの準拠状況

記事構成(Title, Context, Technical Detail)、カスタムMarkdown構文、対象読者への適合性、すべての項目でガイドラインを完全に遵守しています。特にコードブロック前後の空行やGitHubリンク記法が正確に適用されており、可読性が高いです。

  • 記事構成(Title、Context、Technical Detail)
  • DiffDaily Styleガイド準拠
  • カスタムMarkdown活用
  • 対象読者への適合性
技術的整合性 ✓ PASS

技術的な正確性と表現の適切性

引用されているコードはPRの趣旨と完全に一致しており、技術的な説明も正確かつ論理的です。`rescue`節の変更点や、`Rails.error`が外部のエラー監視サービスと連携する仕組みについての説明は、変更の意図を深く理解していることを示しています。

  • 技術用語の正確性
  • コード例の正確性
  • 説明の技術的正確性
PR内容との整合性 ✓ PASS

元のPR情報との一致度

PRのタイトル、関連Issue、およびコード変更から、記事の内容が完全に裏付けられています。ハルシネーションは見られず、PRの目的と影響を忠実に解説しています。関連Issueへのリンクも含まれており、読者にとって有益です。

  • タイトル・説明の一致
  • Diff内容の正確な反映
  • 推測の排除