suppressing-noisy-errors について
suppressing-noisy-errorsは、PostHogのエラートラッキング抑制ルールを評価するスキルです。ノイズのパターンを検証して条件を絞り、影響を事前確認したうえで、イベント取り込み時に破棄する前の承認を求めます。
主な機能
- 01頻度が高くユーザー数の少ないエラーを特定
- 02サンプル例外イベントを調査
- 03範囲を絞った条件を作成
- 04対象イシューと影響範囲を事前確認
- 05既存ルールを確認して承認を依頼
活用シーン
- 01ブラウザー拡張機能や外部サービスのエラーを抑制
- 02ボットやクローラー由来のエラーを減らす
- 03高頻度エラーをサンプリングして可視性を維持
MCP 対応
PostHogのMCPツールを使い、イシューと例外イベントの調査、抑制ルールの一覧・作成、ライブデータに対する条件のプレビューを行います。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ posthog/ skills --skill suppressing-noisy-errorsインストール後、Claude Code で/suppressing-noisy-errorsを入力して読み込まれたか確認します。
詳細
ノイズの多いエラーを抑制する
抑制は本質的に破壊的です。一致したイベントは取り込み時に破棄され、イシューになりません。誤ったルールを設定すると、実際のバグが気づかれないまま破棄されます。このスキルは、抑制が本当に対処不能なパターンにのみ適用され、関係のないエラーを巻き込まないよう十分に絞り込まれたフィルターが使われるようにするためのものです。
抑制が適切な場合
次のようなエラーには、抑制が適切です。
- 自分のコードでは対処不能 — ブラウザー拡張機能、サードパーティーのスクリプト、広告ブロッカー、ページ遷移後に発生するネットワークビーコンなどです。自分で書いたものではないため、修正できません。
- ブラウザーエンジンの特有の動作 —
ResizeObserver loop limit exceeded、Script error.、ペイロードが空のNon-Error promise rejection capturedなどです。 - ボットまたはクローラーのトラフィック — ヘッドレスブラウザーまたは既知のクローラーのユーザーエージェントからのみ発生するエラーです。
- サンプリングで十分な場合 — 発生量は多くても実際のエラーである場合は、完全に抑制するのではなく、
sampling_rateで発生頻度を抑えます。全額分のコストをかけずに、状況を把握し続けられます。
次の場合、抑制は適切ではありません。
- 現時点では対処不能でも、修正後には対処可能になる可能性があるエラー — イシューのステータスを
archivedまたはresolvedにして、再発したときに検出できるようにします。 - 通知だけをミュートしたい場合 — イシューをユーザーに割り当てる、ステータスを変更する、または通知ルールを使います。
- 別のエラーと重複している場合 — マージするか、グルーピングルール(
grouping-noisy-errors)を作成します。
利用可能なツール
| ツール | 目的 |
|---|---|
posthog:query-error-tracking-issues-list | 発生量と影響度を基に抑制候補を見つけます。filterGroup で候補フィルターをドライランします |
posthog:query-error-tracking-issue-events | サンプリングされた $exception イベントを調べ、パターンを確認します |
posthog:execute-sql | OR グループまたは filterGroup の許可リスト外の演算子が必要なフィルターをドライランするための代替手段です |
posthog:error-tracking-suppression-rules-list | 既存の抑制ルールを確認します |
posthog:error-tracking-suppression-rules-create | 抑制ルールを作成します |
posthog:error-tracking-issues-partial-update | 取り込み時にイベントを破棄せず、イシューのステータスで過去のデータを非表示にします |
ワークフロー
ステップ 1 — 候補を特定する
発生数が多く、個別ユーザー数が少ない場合は、最も強いノイズの兆候です。1 人のユーザー(または 1 つのボット)が大量のイベントを発生させています。
posthog:query-error-tracking-issues-list
{
"status": "active",
"orderBy": "occurrences",
"orderDirection": "DESC",
"dateRange": { "date_from": "-7d" },
"limit": 30,
"volumeResolution": 0
}
次の点を確認します。
occurrencesが多く、usersとの比率が低い(例:50,000 件の発生に対し 3 人のユーザー → ボットまたは拡張機能のループの可能性が高い)- 既知のノイズパターンに一致する例外メッセージ:
ResizeObserver loop、Script error.、拡張機能の名前空間(chrome-extension://、moz-extension://、safari-extension://) - ユーザーが管理していないサードパーティードメインが大半を占めるスタックトレース
ステップ 2 — パターンを確認する
候補ごとに、$exception イベントのサンプルを取得し、抑制する対象として意図したパターンと一致することを確認します。
posthog:query-error-tracking-issue-events
{
"issueId": "<candidate_issue_id>",
"limit": 10,
"include": ["exception", "stacktrace", "environment", "navigation"]
}
onlyAppFrames のデフォルトは true ですが、ノイズを調査するときは通常、サードパーティのフレームを表示したいはずです。onlyAppFrames: false を渡すと、スタックに拡張機能の URL やベンダーのドメインが表示されます。
次の点を確認します。
- サンプル全体で例外の型またはメッセージテキストに一貫性がある
- URL/ユーザーエージェント/ブラウザーに、ノイズに混じって実際のユーザートラフィックが含まれていない
- このパターンを抑制しても、同じ型を持つ将来の実際のバグが隠れない
サンプルのいずれかが一致しない場合は、フィルターを絞り込むか、その候補を見送ってください。
ステップ 3 — フィルターの範囲を厳密にする
抑制ルールは、グルーピングルールと同じフィルター形式で設定します。error-tracking-suppression-rules-create ツールの説明では、全件に一致するルールや、範囲が広すぎるルールを作成しないよう明記されています。可能な限り具体的なプロパティの組み合わせで照合してください。
| ノイズのパターン | 推奨フィルター |
|---|---|
| Chrome 拡張機能のエラー | $exception_sources icontains "chrome-extension://" |
| Firefox 拡張機能のエラー | $exception_sources icontains "moz-extension://" |
| Safari 拡張機能のエラー | $exception_sources icontains "safari-extension://" |
| ResizeObserver ループ | $exception_values icontains "ResizeObserver loop"(メッセージが具体的なため、型フィルターは任意です) |
| クロスオリジンの「Script error.」 | $exception_values icontains "Script error." AND $exception_types exact "Error" |
| ボットのユーザーエージェント | 単一の語句には $raw_user_agent regex "(?i)bot" を使用します。1 つのルールで複数のボット/クローラーの目印に一致させる場合は、以下の選択パターンを参照してください |
| サードパーティのネットワークビーコンの失敗 | $exception_sources icontains "<vendor-domain>" AND 型フィルター(例:$exception_types exact "TypeError") |
標準的な例外プロパティ($exception_types、$exception_values、
$exception_sources、$exception_functions)は、イベントのキャプチャ時に配列として記録されます。
PostHog のプロパティフィルターではこれらが特別に処理され、各フィルターは個々の配列要素と照合されます。そのため、すべての標準演算子(exact、
is_not、icontains、not_icontains、regex、not_regex)は、値をそのまま指定して機能します。exact "TypeError" のように指定し、exact '["TypeError"]' や
regex '"TypeError"' のようには指定しないでください。
単数形のプロパティ($exception_type、$exception_message)と
$exception_stack_trace_raw は、イベントの 1%未満にしか記録されません。これらを使ってフィルタリングすると、ルールが一致しないままになることがあります。
抑制ルールおよびグルーピングルールの regex 演算子は、HogVM の Operation::Regex にコンパイルされるため、大文字と小文字を区別します。大文字と小文字を区別しない照合には、インラインフラグ (?i) を使用してください(例:(?i)headlesschrome)。
複数のボットまたはクローラーの語句に一致させるには、選択のためのパイプをそのまま使用します。API を呼び出す際は、これを regex フィルターの value フィールドに渡してください(パーサーによってクローラーの目印が正規化されて消えることがあるため、$user_agent を解析した値より $raw_user_agent の方が信頼性が高いです)。
(?i)(HeadlessChrome|bot|crawler|spider)
可能な限り、2 つ以上の条件を AND で組み合わせてください。たとえば、型とメッセージ、またはメッセージと URL パターンを組み合わせることで、実際のノイズに対して具体的なルールになります。
ステップ 4 — 抑制するか、サンプリングするかを決める
ある程度の可視性を保ちたい場合は、sampling_rate に 0 から 1 の値を指定します。
sampling_rate: 1— 該当するものをすべて破棄します(完全に抑制)。sampling_rate: 0.95— 該当イベントの 95% を破棄し、5% をセンチネルデータとして残します。sampling_rate: 0.5— 半分の割合で残します。大量に発生するものの、実際のエラーである場合に役立ちます。
パターンが純粋なノイズだと確信できない場合は、デフォルトでサンプリング率を 1.0 未満にしてください。データからルールが実際の問題を捕捉していないと分かった後で、1.0 に引き上げられます。
ステップ 5 — ライブデータにフィルターを試しに適用する
確認を求める前に、候補のフィルターをイシュー一覧に対して実行し、過去 7 日間にルールが捕捉するイシューを正確に確認できるようにします。query-error-tracking-issues-list は filterGroup パラメーターを通じて、抑制ルールと同じプロパティフィルター形式を受け付けます。そのため、一般的な AND のみのルールでは、ルールのリーフフィルターをそのまま渡せます。HogQL への変換は不要です。
posthog:query-error-tracking-issues-list
{
"filterGroup": [
{ "type": "event", "key": "$exception_types", "operator": "exact", "value": "Error" },
{ "type": "event", "key": "$exception_values", "operator": "icontains", "value": "ResizeObserver loop" }
],
"dateRange": { "date_from": "-7d" },
"status": "all",
"filterTestAccounts": false,
"orderBy": "occurrences",
"limit": 25
}
抑制プレビューでは、次のデフォルト値を必ず上書きしてください。
status: "all"— 抑制はイシューのステータスにかかわらず適用されるため、デフォルトのactiveフィルターによって、すでにアーカイブされたノイズが隠れないようにします。filterTestAccounts: false— 取り込み時にルールはテストアカウントの切り替え設定を参照しません。プレビューも本番環境の実態に合わせる必要があります。
各行は、ルールが捕捉するイシューを 1 件ずつ示します。name(例外の種類)、description(サンプルメッセージ)、source、library に加えて、aggregations.occurrences と aggregations.users が含まれます。イシュー一覧そのものがイシューごとの内訳です。すべての行を確認してください。
最も重要な安全確認事項:結果を調べ、name/description/source が、ノイズではなくチームが修正したい実際のバグに見えるイシューがないか確認してください。メッセージテキストだけで絞り込んだフィルターは、同じフレーズを含む無関係なイシューにも定期的に一致します。ルールが有効になった後、この失敗によって実際のデータが気付かれないまま失われます。疑わしいものが見つかった場合は、フィルターを絞り込み(ステップ 3)、本物のノイズパターンだけが一覧に残るまでこのステップを再実行してください。
ステップ 6 でユーザーに提示する影響範囲の合計値を算出するため、各行の aggregations.occurrences と aggregations.users を合計してください。limit を超えるイシューを含む正確な合計が必要な場合は、offset を使ってページネーションするか、このステップの最後にある HogQL の集計に切り替えてください。
完全なスタックトレース付きの具体的なサンプルイベントを 1 件か 2 件確認するには、最も疑わしいイシューについて query-error-tracking-issue-events を実行してください。
posthog:query-error-tracking-issue-events
{
"issueId": "<id from the list>",
"limit": 3,
"include": ["exception", "stacktrace", "environment", "navigation"],
"onlyAppFrames": false
}
execute-sql に切り替える必要がある場合
filterGroup はフラットな AND 条件のみをサポートします。次の場合は HogQL を使ってください。
- 外側のグループまたはネストされた OR のいずれかで、ルールが
type: "OR"を使う場合。 - ルールが
filterGroupでサポートされていない演算子(例:between、in、semver_*)を使う場合。 - イシューごとの集計ではなく、イベント単位の正確な件数が必要な場合。
HogQL の形式は、抑制ルールのバイトコードがコンパイルされる形式に対応しています。マテリアライズされたプロパティ列は NULL 許容のため、coalesce(..., '[]') のラッパーが必要です。これがないと、ClickHouse はクエリを「Nested type Array(String) cannot be inside Nullable type」というエラーで拒否します。
SELECT
count() AS matched,
count(DISTINCT distinct_id) AS users,
count(DISTINCT properties.$exception_issue_id) AS issues
FROM events
WHERE event = '$exception'
AND timestamp > now() - INTERVAL 7 DAY
AND arrayExists(
v -> ifNull(ilike(v, '<pattern>'), 0),
JSONExtract(coalesce(properties.$exception_values, '[]'), 'Array(String)')
)
icontains には ilike、exact には通常の等価比較、regex には match(v, '<pattern>') を使ってください。ルールの regex は大文字と小文字を区別します。必要に応じてインラインで (?i) を追加してください。
ステップ 6 — 作成前にユーザーの確認を得る
API では destructive: false とされていますが、抑制は実質的に破壊的な操作です。作成前に、ユーザーに次の内容を提示してください。
- 送信するフィルターの正確な内容
- ステップ 5 のイシュー一覧と、それぞれの
occurrencesおよびusers、さらに集計値。実際のバグに見える行があれば明示します。 - 既存の抑制ルールと重複するかどうか(最初に
posthog:error-tracking-suppression-rules-listを実行します)
明示的な確認を待ってから作成してください。
posthog:error-tracking-suppression-rules-create
{
"filters": {
"type": "AND",
"values": [
{
"type": "event",
"key": "$exception_types",
"operator": "exact",
"value": "Error"
},
{
"type": "event",
"key": "$exception_values",
"operator": "icontains",
"value": "ResizeObserver loop"
}
]
},
"sampling_rate": 0.95
}
まずは 0.95(95% を破棄し、5% をセンチネルデータとして残す)に設定し、1.0 に引き上げる前に、ルールが実際のエラーを捕捉していないことを確認できるようにします。
ステップ 7 — ルールを 24~48 時間監視する
ルールを作成したら、次のことを行います。
- ルール作成後の短い期間に対象を絞り、同じフィルターを実行して、一致するイベントが収集されなくなったことを確認します
(例:1 時間が経過した時点で
WHERE timestamp > now() - INTERVAL 1 HOURを使用します)。 ステップ 5 の 7 日間の推定を再実行しないでください。抑制が適用されるのは新しいイベントのみなので、期間内の過去のイベントは引き続き残り、件数は減りません。 - 作成後の期間中に、関連するアクティブなイシューを監視します。関連しないイシューの件数が安定している一方で、関連するイシューの件数が減少すれば、ルールの適用範囲は適切です。
- 関連する実際のイシューの件数も減少する場合(誤検知)は、ユーザーに直ちに Project settings → Error tracking → Suppression rules からルールを無効にするよう依頼し、フィルターを絞り込んでから再作成してください。ルールの編集または削除を行う MCP ツール(
error-tracking-suppression-rules-partial-update、-destroy)は有効になっていないため、エージェントがプログラムから復旧する方法はありません。
ルール作成と同時に実際のイシューが発生しなくなるなど、誤検知の兆候が見られる場合は、ルールを削除するよりも無効にすることを優先してください。そうすれば、フォレンジックレビュー用にルールの設定を保持できます。
ヒント
- Project settings → Error tracking → Suppression rules には同じデータが表示されます。ユーザーから UI 上でルールがどこにあるか尋ねられた場合は、この場所を案内してください。
- 抑制は取り込み時に適用されます。過去のイベントから作成された既存のイシューのデータは保持され、新しいイベントのみが破棄されます。
- ステータスのみを変更する場合(データは破棄せず、アクティブリストから非表示にするだけの場合)は、抑制ルールよりも
status: "suppressed"を指定したerror-tracking-issues-partial-updateを優先してください。 - スキーマでは、すべてに一致するルールを作成しないようモデルに明示的に警告しています。ユーザーから「拡張機能からのすべてを抑制して」と依頼されても、スタックトレースまたは URL で範囲を絞り込んでください。
filtersを空のままにしないでください。 - 絞り込みすぎた抑制ルールは無害です(多少のノイズが漏れます)。広すぎるルールは実際のデータを気付かれないまま破棄します。狭く設定する方を優先してください。
関連スキル
grouping-noisy-errors— イベントに有用な情報が残っている場合は、破棄するのではなくマージまたは再グループ化しますtriaging-error-issues— ノイズを抑えた後に残るイシューの優先順位を付けます