フレームワーク内部イベントのペイロードフィルタリングを無効化

rails/rails

フレームワークの内部イベントに対するパラメータフィルタリングが無効化され、SQLクエリ名などのメタデータが正しく表示されるようになりました。これにより、config.filter_parameters の設定がログの可読性を損なう問題が解消されます。

背景

EventReporter は、イベントのペイロードに対して ParameterFilter を適用してから購読者に配信する仕組みになっていました。54264bde でフレームワークのログ購読者が EventReporter 経由でイベントを受け取るように変更された結果、SQLクエリ名や内部メタデータまでフィルタリングされる副作用が生じていました。

具体的には、config.filter_parameters += [:name] のような設定により、以下のようにログが破壊されていました:

意図しない動作:

[FILTERED] (0.4ms)  SELECT "people".* FROM "people" WHERE ...

期待される動作:

Person Load (0.4ms)  SELECT "people".* FROM "people" WHERE ...

この問題は、フレームワーク内部のメタデータ(SQLクエリの種類を示す「Person Load」など)がユーザーの機密パラメータと同じ扱いを受けてしまうことに起因していました。

技術的な変更

EventReporternotify メソッドと debug メソッドに filter_payload: オプションが追加され、ペイロードのフィルタリングを制御できるようになりました。

EventReporter の拡張

activesupport/lib/active_support/event_reporter.rb で、メソッドシグネチャが以下のように変更されました:

変更後:

def notify(name_or_object, payload = nil, caller_depth: 1, filter_payload: true, **kwargs)
  # ...
  payload = resolve_payload(name_or_object, payload, filter_payload, **kwargs)
  # ...
end

def debug(name_or_object, payload = nil, caller_depth: 1, filter_payload: true, **kwargs)
  if debug_mode?
    if block_given?
      notify(name_or_object, payload, caller_depth: caller_depth + 1, filter_payload: filter_payload, **kwargs.merge(yield))
    else
      notify(name_or_object, payload, caller_depth: caller_depth + 1, filter_payload: filter_payload, **kwargs)
    end
  end
end

resolve_payload メソッドも filter パラメータを受け取るように変更され、filterfalse の場合はフィルタリングをスキップします:

def resolve_payload(name_or_object, payload, filter, **kwargs)
  case name_or_object
  when String, Symbol
    if kwargs.any?
      resolved = kwargs.transform_keys(&:to_sym)
      filter ? payload_filter.filter(resolved) : resolved
    elsif payload
      resolved = payload.transform_keys(&:to_sym)
      filter ? payload_filter.filter(resolved) : resolved
    end
  # ...
  end
end

StructuredEventSubscriber での適用

StructuredEventSubscriberemit_eventemit_debug_event メソッドが、filter_payload: false を渡すように変更されました:

def emit_event(name, payload = nil, caller_depth: 1, **kwargs)
  ActiveSupport.event_reporter.notify(name, payload, caller_depth: caller_depth + 1, filter_payload: false, **kwargs)
rescue => e
  handle_event_error(name, e)
end

def emit_debug_event(name, payload = nil, caller_depth: 1, **kwargs)
  ActiveSupport.event_reporter.debug(name, payload, caller_depth: caller_depth + 1, filter_payload: false, **kwargs)
rescue => e
  handle_event_error(name, e)
end

この変更により、ActionView の render イベントを含む全てのフレームワーク購読者が、購読者ごとの修正なしに恩恵を受けます。actionview/lib/action_view/structured_event_subscriber.rb では、render_start イベント発行時に直接 event_reporter.debug を呼び出しているため、同様に filter_payload: false が追加されています。

テストケースの追加

変更の正しさを検証するため、複数のテストケースが追加されました:

  • EventReporternotifydebug メソッドで filter_payload: false が正しく動作することを確認するテスト(activesupport/test/event_reporter_test.rb
  • StructuredEventSubscriberemit_eventemit_debug_event がペイロードをフィルタリングしないことを確認するテスト(activesupport/test/structured_event_subscriber_test.rb
  • ActionView の render_start イベントで identifier がフィルタリングされないことを確認するテスト(actionview/test/template/structured_event_subscriber_test.rb

設計判断

デフォルト値を true にして後方互換性を維持する設計 が採用されました。

filter_payload: オプションは既存の挙動を変えないよう true がデフォルトです。これにより、ユーザーコードで EventReporter#notifyEventReporter#debug を直接呼び出している場合でも、従来通りペイロードがフィルタリングされます。

フレームワーク内部の購読者は StructuredEventSubscriber を継承しており、その基底クラスで一括して filter_payload: false を指定する設計になっています。このアプローチにより、個別の購読者を修正することなく、フレームワーク全体に修正を適用できました。

まとめ

本PRは、ユーザーが設定した filter_parameters がフレームワーク内部のメタデータまで隠してしまう問題を解決しました。filter_payload: オプションの導入により、ユーザーデータと内部メタデータを区別してフィルタリングできるようになり、ログの可読性が向上します。既存コードへの影響を最小限に抑えつつ、フレームワーク全体で一貫した動作を実現した設計といえます。

記事メタデータ

Generated by:
Claude Sonnet 4.5 for DiffDaily

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

品質レビュー結果

Review Status:
リトライ後承認
Review Count:
2回 (改善を経て承認)
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)→背景・技術詳細(各論)→まとめ(結論)の3部構成が明確に適用されています。設計判断セクションも設けられており、変更の意図が理解しやすい構成です。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きのシンタックスハイライト、コミットIDとPR番号のGitHubリンク記法が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

フレームワーク内部のコンポーネントに関する詳細な解説であり、専門知識を持つエンジニアという対象読者に完全に適合しています。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが総論→各論の構成になっており、各段落はトピックセンテンスで始まるなど、パラグラフ・ライティングの原則が守られています。非常に読みやすい文章です。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内で引用されているコードは、提供されたDiffの内容と正確に一致しています。変更点(`filter_payload:`オプションの追加など)が的確に抽出されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

EventReporter, StructuredEventSubscriber, payloadなどの技術用語が正確に使用されています。PR Descriptionでは`filter:`と記載されていたオプション名を、実際のコードに合わせて`filter_payload:`と正しく記述しており、精度が高いです。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

ペイロードがフィルタリングされてしまう問題の原因と、`filter_payload: false`を追加して解決するという説明は、技術的に正確かつ論理的です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張(問題の背景、解決策、後方互換性への配慮など)は、PRのDescriptionやDiffの内容によって裏付けられており、ハルシネーションは検出されませんでした。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#56837)や言及されているコミットID(54264bde)は正確です。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトル「フレームワーク内部イベントのペイロードフィルタリングを無効化」は、PRの主題「Don't filter StructuredEventSubscriber payloads」を的確に和訳し、内容を正確に表現しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

記事の内容は提供されたPR情報に限定されており、バージョン情報やリリース予定など、PR外の知識の追記は見られません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

過去の変更と今回の変更の関係性について、時間的な表現に誤りはありません。