【Issue グルーピングの改善】より賢く、より速く、誤判定は半分に

Article by: (読了時間:9分)

 
 

Sentry の役割は、アプリケーションで問題が発生した際に、それを開発者へ知らせることです。そのために、個々のエラーを Issue としてグループ化しています。まず、フィンガープリントを使ってエラー構造を字句レベルで照合し、一致しない場合は AI モデルが補完します。AI モデルは新しいエラーのスタックトレースを既存の Issue と比較し、意味的に類似していると判断した場合は同じ Issue として統合します。このたびモデルをアップグレードしたことで、重複 Issue の発生を20%多く防ぐとともに、誤った Issue 統合を半減させました。

AI による Issue グルーピングはデフォルトで有効になっており、すべての Sentry ユーザーに適用されています。

 

グルーピングが難しい理由

AI グルーピングの v1 については、「Transformer ベースのテキスト埋め込みモデルで Sentry アラートを 40% 削減 ー ノイズを突破」で解説しています。

優れたグルーピングアルゴリズムは、アンダーグルーピングオーバーグルーピングの両方を最小化します。アンダーグルーピングを抑えるとは、同じ根本原因の問題に対して Sentry が新しい Issue を次々と生成しないことを意味します。オーバーグルーピングを抑えるとは、アプリが経験している新しいカテゴリのエラーを Sentry が必ず通知することを意味します。このバランスをうまく取るのは難しく、主観的な判断も伴います。

オーバーグルーピングはより深刻な失敗モードと言えます。Sentry がエラーを誤って Issue に統合してしまうと、本来別のワークフローで対処すべき問題が隠されてしまいます。そのエラーは優先度も根本原因も修正方法も異なる可能性があります。

いかに判断を誤りやすいかを示す実例として、Sentry のリポジトリにあるスタックトレースがほぼ同一でありながら、根本原因が異なる 2 つのエラーを紹介します。

どちらのエラーも Seer Autofix 機能からのタイムアウトであり、同じリクエストパスを共有しています。しかし、違いはスタックトレース内のわずか2つのフレームにあります。

1つ目のタイムアウトは get_autofix_state フローで発生したもので、通常のWebサーバー上で実行されるデータベースクエリです。2つ目は _generate_fixability_score フローで発生したもので、GPUサーバー上の別のコネクションプールを介して実行され、タイムアウト時間も2倍に設定されたMLモデルへの呼び出しです。これらのリクエストは、クライアント側・サーバー側ともにそれぞれ独立して改善する必要があります。しかし、AIグルーピング v1 はこれらを1つのIssueとしてまとめていました。一方、v2では正しく別々のIssueとしてグループ化されます。

スタックトレースのグルーピングは繊細なタスクであり、一般的な埋め込みモデルが想定している用途ではありません。たとえば、高性能な gemini-embeddings-2 でさえ、このタスクでは十分な性能を発揮できませんでした。AIグルーピング v1 では、Jina AI のコード埋め込みモデルが精度と効率の両面で優れていたため、既製のモデルを上回る性能を実現できると私たちは確信していました。

私たちは、本番環境から収集された膨大なスタックトレースに加え、チームが2年間かけて蓄積してきた、AIグルーピング v1 の失敗パターンに関する知見を持っています。LLMを活用することで、その知見を数十万件のスタックトレースに対してラベリングアルゴリズムとして適用し、大規模な学習データを作成できました。v2モデルは、このラベル付きデータを用いて学習され、4月からAIグルーピングを支えています。

 

v2 の本番環境での成果

Issue の新規作成が減少

AI グルーピングは全新規 Issue の 70% の発生を防いでおり、4 月 22 日の v2 段階的ロールアウト開始前の 50% から向上しました。大規模な Sentry プロジェクト 3,800 件(1 日あたり少なくとも 100 件の新規 Issue を取り込んでおり、v2 導入前後でエラー量が安定しているプロジェクト)のうち、18% で AI による防止率が v2 以降に倍増しました。

オーバーグルーピングが半減

v1 のオーバーグルーピング率(誤ったマージの割合)は 8% です。この数字は全体で見れば大きくないように見えますが、問題は v1 モデルが特定のプラットフォームのエラーをオーバーグルーピングしやすい傾向を持っていることです。プラットフォームのバイアスは、プロジェクトレベルでの Sentry 体験を大きく損なう可能性があります。小規模ながら集中的な調査で、v1 のオーバーグルーピング率が 30% から 60% に及ぶプロジェクトが見つかりました。そうしたプロジェクトでは、異なる根本原因を持つ多数のエラーが詰め込まれた肥大化した Issue が珍しくありません。

v2 のオーバーグルーピング率は 4% であり、全プラットフォームで低く抑えられています。上記のコホートに含まれるすべてのプロジェクトで、オーバーグルーピング率が 2〜15% に改善されており、v1 のマージ率は維持または向上しています。

v2 は v1 が大幅にオーバーグルーピングしていたすべてのプラットフォームで改善しています。マージ率は新規エラーのうち既存 Issue に統合される割合です。オーバーグルーピング率は、そのマージのうち誤ったものの割合、つまり本来属すべきでない Issue に統合されたエラーの割合です。

 

v2 の訓練方法

訓練パイプライン全体の中で、データのサンプリングとラベリングが圧倒的に重要でした。同意を得た数百の Sentry プロジェクトからスタックトレースをサンプリングし、プロジェクトのマージ率とスタックトレースの長さのバリエーションが広くなるよう選定しました。また、Sentry のプロジェクト構成が JavaScript 多数となっているバイアスを補正するため、プラットフォーム別の層化サンプリングも一部行いました。さらに、v1 モデルの判定境界に近いスタックトレースペアのサンプルウェイトを増やしました。これらのペアこそ後継モデルが最も改善できる部分だという仮説に基づいています。

ラベリングは、思考バジェット 1,024 トークンで Claude Sonnet 4.5 にプロンプトを投げることで行いました。プロンプトは Sentry の Issue グルーピングガイドラインに沿って丁寧に反復改善し、表面的な意味論よりもエラーの根本原因を重視するよう設計しました。プロンプトの精度は、社内 Sentry プロジェクトのエキスパートがラベリングしたスタックトレースペアで測定しました。エキスパートラベラーは Sentry のグルーピング責任者たち、すなわちスタックトレースの類似性について何年も考え続けてきた社員です。私たちは自分たちのラベルにおいてオーバーグルーピングを避ける方向に振り、Claude にも同様の指示を出しました。

その後、これらのラベル付きスタックトレースペアで lightonai/modernbert-embed-large をトレーニングを行いました。トレーニングデータには 10 トークンから 8192 トークンの範囲のスタックトレースペアが数十万組含まれています。ほとんどのトレーニングは改善アイデアの検証で、遊び心から試したものもあります。ユニークな訓練上の選択として、2005 年の損失関数を使用すること、フォワードパスの重複を減らすためにデータローダーのスキャン順をグルーピングすること、そして flash-attn のインストールに午後を丸ごと費やして失敗した後、DDP で少し変わった対処をしたことが挙げられます。改善につながらなかった興味深い実験も含め、すべての知見は grouping-trainer リポジトリに記録されています。

モデルの精度を少しでも高めるために複数の実験を並行して回せるよう、GPU不足による悩みを減らすための小規模な学習インフラも構築しました。L4、A100、H100 GPUを同時に最大20基(私たちのチーム規模としては控えめな台数)まで稼働させることができ、起動を指示してから30分以内にすべて利用可能な状態になります。

トレーニング・オフライン評価・簡易インフラのコードは getsentry/grouping-trainer で公開しています。

評価面では、本番環境でのオーバーグルーピングを計測できるようになりました。オーバーグルーピングはかつて静かに深刻な影響を及ぼしてきた失敗モードです。以前はカスタマーレポートをもとに UI 上の統合済み Issue を手作業で調べる必要がありました。今では SQL クエリから数千件の統合済み Issue を一括ラベリングするパイプラインが稼働しています。

 

v2 推論のモダナイズ

Sentry の超高負荷なエラー取り込みパスにおけるオーバーヘッドを削減するため、v2 モデルの推論環境もアップグレードしました。AI グルーピング v2 は v1 より 6 倍高速で、GPU メモリ使用量も少なく、数百 GB の DB 容量を節約します。

最もインパクトの大きいモダナイズは埋め込みの次元削減です。v2 モデルは Matryoshka Representation Learning で訓練されているため、v2 の埋め込みを 768 次元から 64 次元に削減しても精度の低下はわずか 2% にとどまり、p50 の HNSW 検索時間が 4 倍、p50 の挿入時間が 20 倍、pgvector DB のストレージ使用量が 12 倍改善しました。

また、モデルを bfloat16 で実行し、PyTorch の SDPA を有効にして推論を高速化するとともに、本番環境での CUDA OOM を解消しました。これらの変更は Hugging Face のおかげで 1 行で済みます。

最後に、レイテンシに敏感な純 PyTorch サーバー構成に合わせてモデルをコンパイルし、コンパイルなしの場合と比べて p50 のモデル推論レイテンシをほぼ 3 倍改善しました。同様の構成でロングテールなトークン分布を持つ方のために、この CUDA グラフコンパイル戦略をベンチマークして GitHub で公開しています。

これらの変更はすべて、本番環境を厳密に模したロードテストでオフライン検証しています。テストでは、実際のプロジェクトのスタックトレースを pgvector DB にバックフィルした状態から始め、それらのプロジェクトの実際の新規スタックトレースを同時送信します。

 

シームレスなモデルアップグレードの実現

ステートレスな推論の ML モデルをアップグレードする方法は概念的にはシンプルです。新しいモデルをロードして提供するだけです。しかし AI グルーピングはステートレスとは程遠い仕組みです。Issue 作成に比例したレートで埋め込みを挿入し、最大 90 日間データを保持します。単純に v1 モデルを v2 に入れ替えると、v2 がマッチングすべきデータをデータベースに何も持っていない状態から始まるため、新規 Issue が大量発生します。そのため、カスタマー体験を損なわずに新モデルをリリースし、埋め込みをバックフィルする方法が必要でした。

完全バックフィル(v1 のように数ヶ月かかる)、v2 の埋め込みが蓄積するまで 90 日待ってから切り替え、あるいは v2 を即時本番稼働させて v2 のデータが不足している場合は v1 にフォールバックするという 3 つの選択肢を検討しました。選んだのは第3案です。顧客は初日から v2 の恩恵を受けられ、v2 は v1 の判断を改善するだけで、打ち消すことはありません。

この仕組みは、Seer のグルーピング API に追加した modeltraining_mode という 2 つのパラメーターが鍵です。プロジェクトがフィーチャーフラグで v2 にオプトインすると、Sentry は model=v2 でスタックトレースを Seer に送信します。Seer はまず v2 の埋め込み空間を検索し、見つからなければ v1 にフォールバックします。

ただし、ひとつ細かい点があります。Seer は閾値ゲート付きインデキシングを採用しており、十分に近いマッチがインデックス内に存在しない場合のみ埋め込みを保存します。これにより HNSW グラフをコンパクトに保ち、検索効率を向上させています。真の最近傍ではなく閾値内の任意のマッチで足りるため、エッジ数に上限のある(m=16)疎なグラフで十分です。ただしその結果、v2 のコーパスは本当に新しいイベントからしか増えず、既存グループには v2 の表現が残らないという問題が生じます。

そこで training_mode の出番です。これまで v1 でのみ送信されていたグループハッシュに対して、Sentry は training_mode=true でリクエストを送信します。Seer は v2 の埋め込みを保存しますがグルーピング結果は返さず、これにより重複抑制を意図的にバイパスしてインデックスをバックフィルします。これによって v2 のデータベースをリアルタイムに積み上げられ、別のジョブを走らせることなくライブトラフィックに乗っかれます。

ロールアウトはプロジェクト単位で社内から始め、移行全体に約 6 週間かかりましたが、顧客からの不具合報告はゼロでした。このインフラは再利用可能です。明日 v3 を訓練しても、アップグレードのパスは同じです。カラムを追加し、フラグを切り替え、フォールバックチェーンに移行を任せるだけです。

 

今後の展開

より多くのデータにラベルを付けて、より大規模なモデルをファインチューニングすることは有効です。しかし、私たちがより興味を持っているのは、モデルに与える入力そのものを改善することです。

現在、モデルが利用しているのはエラーのスタックトレースだけです。より高度なモデルであれば、エラーの取り込み時に得られるシグナル(トランザクションや変数の値など)も活用できるはずです。

さらに一歩進めて、Sentryがアプリケーションに関する知識を蓄積し、それに応じた関連コンテキストを動的に付与できるようになったらどうでしょうか。たとえば、あるトランザクションが果たす役割や、あるエラーがダウンストリームのユーザーにどのような影響を与えているのか、といった情報です。私たちは現在、このコンテキストを蓄積・活用する仕組みを、Seerを通じて探求しています。

その間も、v2モデルは着実に稼働し続け、スタックトレースを適切なIssueへと振り分けています。

 

 

Original Page: Better, faster, less wrong: Enhancing issue grouping

 




IchizokuはSentryと提携し、日本でSentry製品の導入支援、テクニカルサポート、ベストプラクティスの共有を行なっています。Ichizokuが提供するSentryの日本語サイトについてはこちらをご覧ください。またご導入についての相談は「お問い合わせ」からお気軽にお問い合わせください。

 

シェアする

Recent Posts

;