;

Ichizokuは日本唯一のSentry公認販売業者です。
日本語のドキュメント、動画、サポート窓口で日本のお客様のSentry活用を支援します。

本番データを活用してバグを予測するコードレビューシステムの構築

Article by: Giovanni GuidiniKush DubeySuejung Shin

 
 

この投稿では、Sentry の AI Code Review が実際にどのように動作するのかを、より詳しく見ていきます。

Seer(Sentry の AI デバッガー)の一部として、Sentry のコンテキストを使用し、バグを正確に予測します。自動またはオンデマンドで実行され、出荷前に問題点を指摘し、修正案を提案します。

AI ツールはノイズが多くなり得ることを私たちは理解しています。そのためこのシステムは、誤検知や役に立たないスタイル上の指摘で埋め尽くすのではなく、実際の変更内容に含まれる本物のバグを見つけることに焦点を当てています。AI とアプリの Sentry データ(実行状況や、これまでどこで壊れてきたか)を組み合わせることで、将来新しいバグを出荷してしまうことを避けられるようにします。

 

 

高レベルアーキテクチャ

このコードレビューシステムは、コード分析と Sentry データの両方を用いてバグを検出し、PR に対して提案を提示します。

以下は AI Code Review のアーキテクチャの概要です。

PR によってトリガーされるバグ予測パイプラインを示すフローチャート: エラーが発生しやすいファイルがフィルタリングされ、バグ仮説が並行して作成および検証され、検証されたバグがフォーマットされ、マージされ、品質と類似性によってフィルタリングされ、GitHub PR に公開され、レビュー完了としてマークされます。
 
 

バグ予測パイプライン

できる限り高い精度でバグを予測するために、仮説と検証に基づくマルチステップのパイプラインを採用しています。

  • フィルタリング:このステップでは PR の情報を収集し、PR 内のファイルを、最もエラーが発生しやすいものへ絞り込みます。特に大規模な PR では重要です。
  • 予測:肝となる部分です。ここでは複数のエージェントを実行し、バグの仮説を作成して検証します。
  • パッケージングと出荷:提案を集約し、フィルタリングと解析を行ってコメントに整形したうえで、PR に送信します。

 

このあと、パイプラインが実際に動いている様子を示す例として、getsentry/sentry リポジトリのトレースをいくつか見ていきます。

 

フィルタリング

変更が少ない PR の場合は、すべてのファイルをエージェントのコンテキストに追加します。ただし、大きな変更によってエージェントが圧倒されないように、変更対象が 5 ファイルを超える場合は、最もエラーが発生しやすいファイルに絞り込みます。

これは LLM に対して、テストファイルやドキュメントの変更、そして見た目上エラーが起きにくそうなファイルを除外するよう指示して行います。とはいえ、テストファイルは、下のステップで説明する draft(仮説作成)エージェントと verify(検証)エージェントの両方の実行中に検索されます。

 
予測

コンテキストこそが重要なので、すべてのエージェントは、分析対象のコードを理解するためのリッチなコンテキストを提供するさまざまなツールにアクセスできます。

予測は最終的に、以下に基づいて行われます。

  • 実際のコード変更
  • PR の説明
  • コミットメッセージ
  • このリポジトリの Sentry の過去データ(詳細は「How Sentry context is used」を参照)
  • リポジトリ内のコード(コード検索ツール経由)
  • Web 上の情報(Web 検索ツール経由)
  • リポジトリについて PR を横断して収集された「メモリー」。これはシステムが各 PR を分析するたびに、時間をかけて学習していく、そのリポジトリ固有の情報です。解析済みの新しい PR が増えるたびに更新される、最新で関連性の高い断片情報のリストを保持しています。たとえば「このリポジトリのテストは pytest の assertions を使う」や「tasks.py の root_task には 15 分(900 秒)のハードタイムリミットがある」といった内容です。

 

このエージェントのワークフローは仮説を生成し、それぞれの仮説の検証を試みます。

  1. 仮説のドラフト作成:ドラフティング用のエージェントが、潜在的なバグに関する初期分析を含むレポートを作成します。このレポートは最大 3 つのバグ仮説に分割されます。
  2. 仮説の検証:並行して、各仮説は専用のエージェントによって分析されます。各 verify エージェントは、Sentry の issue やイベントの詳細を取得するためのツールにアクセスできます。詳細は「How Sentry context is used」を参照してください。
  3. 結果の収集:最後のエージェントがすべての結果を集め、検証済みのバグ予測のリストとして集約します。

 

検証エージェントを単一の仮説に集中させることで、深掘りができ、その仮説が本当に有効なバグかどうかをより正確に判断できます。

これが、バグ予測におけるシグナル・ノイズ比を高く保つ方法です。

 

getsentry/sentry のこの PR について、別のトレース例を見ていきます。具体的には、コミット 596e046c05cb6ec43ebf924dbc40fd1e3f40db26 を対象とします。

 


 
ファイルフィルタリング
 

 

 

ドラフト仮説

ここまででコード変更について包括的に理解できました。潜在的な問題点を分析します。

 
分析
この変更は、analytics.record() の呼び出しを、文字列ベースのイベント名からクラスベースのイベントオブジェクトへ置き換えるリファクタリングです。リポジトリのコンテキストには、analytics.record() は非クリティカルな処理と見なされているため、記録処理の失敗が伝播しないように try/except でラップすべきだと書かれています。

変更内容を見ると

  1. 多くの変更にエラーハンドリングがない
    src/sentry/integrations/slack/webhooks/event.py、src/sentry/integrations/discord/webhooks/message_component.py、src/sentry/integrations/discord/webhooks/base.py、src/sentry/sentry_apps/installations.py などのファイルでは、リファクタリングにより analytics.record() の呼び出しは変更されていますが、try/except によるエラーハンドリングが追加されていません。

  2. 1 つのファイルだけ適切なエラーハンドリングが追加されている
    src/sentry/rules/actions/integrations/base.py では、新しい analytics.record() 呼び出しが try/except で適切にラップされており、sentry_sdk.capture_exception(e) も実行しています。

  3. import の不足
    新しいイベントクラスが import されていますが、インスタンス生成時に失敗する可能性があるかどうかを確認する必要があります。
 
潜在的なバグ

分析に基づき、特定した潜在的なバグは以下の通りです。

1. analytics.record() 呼び出しにエラーハンドリングがない。

 

位置

説明リポジトリのコンテキストには、analytics.record() の呼び出しは、失敗が伝播してユーザー向けのエラーを引き起こさないよう、try/except でラップすべきだと明記されています。しかし、この変更でリファクタリングされた analytics.record() の呼び出しの大半には、このエラーハンドリングが含まれていません。しかも、文字列ベースの記録からクラスベースのイベント記録へ変更しています。

新しいクラスベースの方式では、古い文字列ベースの方式には存在しなかった新しい失敗要因が入り得ます。たとえば、イベントクラスのコンストラクタが入力パラメータのバリデーションを行う場合や、クラス登録に問題がある場合、例外が発生し得ます。そうすると、その例外がコールスタック上へ伝播し、リクエストがクラッシュする可能性があります。

追加で調査すべき重要な点

  • 新しいイベントクラスがインスタンス生成時に例外を投げ得るバリデーションを行っているか
  • 古い文字列ベースの analytics.record() 呼び出しに、暗黙的なエラーハンドリングがあり、それが失われていないか
  • これらの analytics 呼び出しが、例外発生時にユーザー向けエラーにつながるクリティカルなリクエストパス上にある

 

2. リファクタリングされた analytics 呼び出しにおけるフィールド不一致の可能性

位置src/sentry/integrations/slack/webhooks/event.py:205~211

説明元の analytics 呼び出しでは user_id フィールドが暗黙的に含まれていましたが、新しい IntegrationSlackChartUnfurl クラスでは user_id: int | None = None がオプションのフィールドとして定義されています。リファクタリング後のコードでは user_id を渡していないため、デフォルトの None になります。これが意図的なものか、あるいはリクエストコンテキストから user_id を渡すべきなのかを確認する必要があります。

追加で調査すべき重要な点

  • 元の呼び出しが user_id パラメータを含める想定だったか
  • user_id が欠落すると、分析データの収集に意味のある影響が出るか

 

リポジトリのコンテキストが analytics.record() を try/except でラップすることを強調していること、そしてこの PR の変更の大半にその保護が入っていないことを踏まえると、エラーハンドリングの欠落が、本番環境で予期しないクラッシュを引き起こし得る主要な潜在バグだと考えます。

 


 

仮説 1 となった箇所で、エージェントが「リポジトリのコンテキストには、analytics.record() の呼び出しは try/except でラップして、失敗が伝播してユーザー向けのエラーを引き起こさないようにすべきだと明記されている」と述べている点にお気づきでしょう。これはこのリポジトリ向けに生成した「メモリー」に由来するものです。

 


 

メモリのコンテキスト

エージェントに渡されたメモリの該当箇所(原文):

API エンドポイントやその他のクリティカルなリクエストパスで analytics.record() を呼び出す場合は、try…except Exception as e: sentry_sdk.capture_exception(e) で呼び出しをラップします。これにより、分析イベントの記録における失敗(例:無効なイベントデータ、あるいは内部の分析システムの問題など)が伝播し、ユーザー向けのエラーを引き起こしたり、メインのリクエストフローをブロックしたりすることを防げます。分析の記録は、主要なユーザー体験にとっては非クリティカルであると見なされています。

 


 

仮説1の分析

バグガイドラインに照らして評価する前のこのバグに関する初期分析。

<initial_followup>

コードベースを徹底的に調査した結果、私はこの仮説と証拠を明確に理解できました。これを体系的に分析します。

 
証拠分析
 

1. リポジトリコンテキストの検証

リポジトリのコンテキストには、analytics.record() の呼び出しは try/except でラップすべきだと正しく書かれています。しかし私の調査では、このガイダンスはコードベース全体で一貫して守られていないことが分かりました。

2. 既存のエラーハンドリングのパターン

実際の実装を確認します。

適切なエラーハンドリングがある例

  • src/sentry/middleware/devtoolbar.py:analytics.record() を try/except でラップし、sentry_sdk.capture_exception(e) を呼び出しています。
  • src/sentry/rules/actions/integrations/base.py:今回のコード変更自体に、analytics.record() 呼び出しの適切なエラーハンドリングが含まれています。
  • src/sentry/api/endpoints/organization_events_stats.py:エージェント監視クエリ向けに、analytics.record() が try/except と sentry_sdk.capture_exception(e) でラップされています。

 

エラーハンドリングがない例

検索結果から、try/except による保護がない analytics.record() の呼び出しがコードベース全体に数百件あることが分かりました。これは孤立した問題ではなく、広く見られるパターンであることを示唆しています。

 

3. Sentry Issue の証拠

私が調査した Sentry Issue から分かったことは次のとおりです。

  • Issue 6871320642:分析イベントのシリアライズ中に KeyError が発生(具体的には SentryAppSchemaValidationError.serialize() 内)。analytics.record() が実行時例外で失敗し得ることを示しています。

  • Issue 6847278399:TrialUsageEndNotification に必須属性が欠けていたため、分析イベントのバリデーションが失敗し ValueError が発生。分析イベントが別の経路でも例外を投げ得ることを示しています。

 

これら 2 件はいずれも、分析システムがさまざまな形で失敗し得ることを示しており、analytics.record() の呼び出しが例外を投げる可能性がある、という仮説を裏付けています。

 

4. クラスベースのイベントに変更したことによるリスク評価

コード変更を見ると、このリファクタリングは文字列ベースのイベントからクラスベースのイベントへ移行しています。

旧方式

新方式

新方式ではイベントクラスのインスタンス生成が導入されており、次のタイミングで失敗する可能性があります。

  1. クラスコンストラクタでのバリデーション
  2. フィールドのバリデーション
  3. データクラス変換(Sentry issue で示されているとおり)

 

5. クリティカルなリクエストパスの分析

変更されているファイルには次が含まれます。


これらは、未処理の例外が発生するとユーザー向けのエラーにつながるクリティカルなリクエストパスです。

 
ボトムアップ評価
 

仮説を裏付ける証拠

  1. ✅ リポジトリのコンテキストで、analytics.record() は try/catch でラップすべきだと明示されている
  2. ✅ 実際の Sentry Issue から、analytics.record() がさまざまな例外で失敗し得ることが分かる
  3. ✅ 変更されたファイルのうち、適切なエラーハンドリングがあるのは 1 つだけ(src/sentry/rules/actions/integrations/base.py)
  4. ✅ 他のファイルは、クリティカルなリクエストパス上にあるにもかかわらずエラーハンドリングがない
  5. ✅ クラスベースの方式は、新たな失敗要因を持ち込む可能性がある
  6. ✅ コードベースの他の箇所では、analytics.record() に try/catch を入れる同様のパターンがすでに存在する

 

確認できなかった点

  • 新しいイベントクラスがインスタンス生成時に失敗する確率の正確な見積もり
  • このコード変更で使われている特定のイベントクラスに、既知のバリデーション問題があるかどうか

 

結論

この仮説は、実在するバグとして 妥当 です。以下の点について、証拠は強く支持しています。

  1. リポジトリでは analytics.record() を try/except でラップすることが明確に求められている
  2. 本番環境での実例として、analytics.record() は実際にさまざまな例外で失敗し得ることが示されている
  3. 今回のコード変更は、複数のクリティカルなリクエストパスでこのガイドラインに違反している
  4. クラスベースの方式は、旧来の文字列ベースの方式と比べて追加の失敗要因を導入し得る

 

これは分析イベントの記録に失敗したときに、本番環境で予期しないクラッシュを引き起こし得る実際のバグです。変更されたファイルのうち、適切なエラーハンドリングがあるのが 1 つ(src/sentry/rules/actions/integrations/base.py)だけで、他はそうなっていないという事実は、確立されたパターンに対する明確な違反であり、重要なインテグレーションのワークフローでユーザー向けエラーにつながる可能性があります。
</initial_followup>

バグガイドラインを適用した後の修正版フォローアップ所見
<revised_followup>

欠落しているエラーハンドリングに関する具体的なフィルタリングガイドラインに照らして、私の分析を確認します。

欠落しているエラーハンドリングのガイドラインによるフィルタリング
 

1. 当該ブロックがエラーを投げ得る証拠:✅ 強い証拠

  • 2 つの具体的な Sentry Issue(6871320642、6847278399)が、KeyError と ValueError による analytics.record() の失敗を示している
  • リポジトリのコンテキストで、analytics の呼び出しは try/except でラップすべきだと明示されている
  • コードベース内に、analytics.record() を try/except でラップしている既存例が複数ある

 

2. グレースフルに処理するのが正しい:✅ 確認済み

  • リポジトリのコンテキストで、analytics の記録は「主要なユーザー体験にとって非クリティカル」であると明記されている
  • 失敗は伝播してユーザー向けエラーにつながるべきではない
  • analytics は明らかにノンブロッキングであることが意図されている

 

3. 実行コンテキスト(エンドユーザー向けかバックエンドか):✅ ユーザー向けコード


  • ユーザーから見える webhook の失敗を引き起こす
  • インテグレーションの機能を破壊する
  • 外部サービス(Slack、Discord)へエラーレスポンスを返す

 

4. 実行経路をスタックの最下層まで追跡:✅ 確認済み

  • webhook の失敗は外部サービスへ伝播する
  • インストールの失敗は UI 上でユーザーに見える
  • これらの analytics 呼び出しをラップする上位レベルのエラーハンドリングは存在しない
 
修正版の分析
 

この仮説は実在するバグとして妥当です。欠落しているエラーハンドリングの基準をすべて満たしています。

  1. 失敗し得ることの強い証拠:本番環境の実例として、analytics.record() が失敗し得ることが Sentry issue により示されている
  2. ユーザー向けのコードパス:これらは、失敗がユーザーに直接影響するインテグレーションのエンドポイントである
  3. リポジトリのガイドライン違反:analytics.record() をラップするという明示的な指針が守られていない
  4. グレースフルデグレードが必要:analytics の失敗で中核機能が壊れるべきではない

 

このバグが引き起こし得ること

  • Slack/Discord 利用者における webhook インテグレーションの失敗
  • Sentry App のインストール失敗
  • インテグレーションのワークフロー破綻

 

これはクリティカルなユーザー向けコードパスにおける、エラーハンドリング欠落の実際のバグです。
</revised_followup>

 


 

仮説 1 を検証するためにエージェントが収集した証拠の一部として、コードベース内の過去の Sentry issue を参照している点に気づくでしょう。これらは、エージェントが分析していたものと同様のコードパターンに由来するものです。

 


 

仮説2の分析

バグガイドラインに照らして評価する前のこのバグに関する初期分析
<initial_followup>

私の分析に基づき、ここではこの仮説についての確定的な評価を提示できます。証拠を確認します。

 
仮説の分析
 

この仮説は次の内容を述べています。

「IntegrationSlackChartUnfurl に対するリファクタリング後の analytics 呼び出しでは user_id が渡されておらず、その結果デフォルトで None になる。元の文字列ベースの呼び出しでは、このフィールドが暗黙的に含まれていた可能性があるため、新しいクラスベースの呼び出しで省略されると、重要な分析データが失われる可能性がある。」

 
コードからの証拠

src/sentry/integrations/slack/webhooks/event.py における該当のコード変更を正確に見ると次のとおりです。

 

元のコード

新しいコード

主な所見

  1. 元の呼び出しに user_id は含まれていなかった:元の analytics.record() 呼び出しで渡していたのは organization_id と unfurls_count=0 だけで、user_id パラメータは存在しませんでした。
  2. IntegrationSlackChartUnfurl のクラス定義(src/sentry/integrations/slack/analytics.py より)

 

  1. user_id を利用できるコンテキスト:この analytics 呼び出しが行われている on_link_shared メソッドでは、slack_request.user_id と request.user にアクセスできます。ファイル全体を通して、slack_request.user_id はログ出力やその他の用途で広く使われています。
  2. 別ファイルでの異なる使い方:src/sentry/integrations/slack/unfurl/discover.py では、同じ IntegrationSlackChartUnfurl クラスが user_id を指定して使われています。

 

 
結論
 
この仮説は不適切(INVALID)です。

理由は次のとおりです。

  1. 元の呼び出しで user_id が暗黙的に入っていたわけではない:仮説の前提(元の文字列ベースの呼び出しが user_id を「暗黙的に含んでいた可能性」)は事実と一致しません。元の呼び出しは、明示的に user_id を一切含んでいませんでした。
  2. 挙動が一貫している:旧実装も新実装も user_id を省略しているため、挙動は変わっていません。新しい呼び出しで user_id が None にデフォルトされるのは、元の呼び出しが user_id を渡していなかった場合と同じ結果です。
  3. データ損失ではない:元の呼び出しは user_id を取得していなかったため、仮説が述べるような「重要な分析データの損失」は起きていません。分析側にはもともとこの情報が欠けていました。

 

リファクタリング後のコードは、文脈上 user_id(slack_request.user_id が利用可能)を含めることもできたはず、という点は確かです。しかし、このフィールドがないことは、リファクタリングによって導入されたバグではなく、既存の挙動を維持しているだけです。

これはサーバークラッシュや重大なロジック不具合、パフォーマンス問題を引き起こすバグではありません。最大でも、分析の強化という観点での改善余地(エンハンス要望)に留まり、このリファクタリングにより持ち込まれたバグではありません。
</initial_followup>

バグガイドラインを適用した後の修正されたフォローアップ調査結果
フォローアップ分析で予測されたバグは有効ではないと結論付けたため、指示どおりにこのフィルタリング手順をスキップします。
<revised_followup>

元の分析呼び出しにパラメータが含まれていなかったため、この仮説は無効でした。そのため、同じ動作を維持するリファクタリングされた呼び出し(デフォルトは)はバグではなく、データ損失なしで既存の機能を保持しています。user_iduser_idNone
</revised_followup>

 


 

最終的に、仮説 1 は潜在的なバグとして扱われ、ここでユーザーに提示されます。そこには、仮説の検証に使われた Sentry issue のうち 1 件への参照が含まれています。

 
 

Sentry のコンテキストの使われ方

verify エージェントには、issue を分析するために「クリックして掘り下げる」フローを採用するよう指示されています。まず、多数の issue を検索し、それぞれの短い要約を受け取ります。次に、特定の issue がコード変更と関連するとエージェントが判断した場合、その issue の詳細を取得します。このフローにより、エージェントはバグを分析するために実行時の知識が必要かどうかを自分で判断でき、コンテキストを絞り込んだままにできます。エージェントが呼び出し得る検索ツールは以下のとおりです。

  • キーワードで過去の Sentry Issue を取得する。このツールは、Sentry UI の Issue Feed を検索する機能をエージェントに与えるのに近いものです。
  • エラー種別で過去の Sentry Issue を取得する。エージェントがバグの具体的なエラー種別(例:KeyError)を推測でき、過去に類似のバグが起きているかを見たい場合に有用です。たとえば、コードがデータにアクセスしようとしていて、(本番環境でそのオブジェクトを確認すると)キーや属性が欠けている場合はないか、などです。
  • ファイル名と関数名で過去の Sentry Issue を取得する。このツールは、スタックトレースが特定の関数と重なっているエラーを含む Issue を返します。エージェントには、本番環境での変数値を確認するため、または特定の関数がエラーが起きやすい経路の一部として知られているかを判断するために、このツールを使うよう指示されています。

 

これらの検索は、マッチした各 Issue について、Issue ID、タイトル、メッセージ、コード上の位置、そして(存在する場合)Seer による Issue の要約を返します。この要約は、エラーイベントの詳細と breadcrumbs に基づいています。これらの情報により、エージェントは返ってきた Issue のうち、より詳しく見るべきものがあるかどうかを判断できます。詳しく見る価値があると判断した場合、エージェントはイベントの詳細を取得するツールを呼び出せます。イベントの詳細には、その Issue のスタックトレースと変数値が含まれます。また(存在する場合)Seer の根本原因分析も返されます。この段階で、エージェントは本番環境や実行時のコンテキストを分析に取り込む場合があります。取り込んだ場合、バグ予測のコメントには、関連する Sentry Issue へのリンクが含まれます。

 

 

質の高い予測を維持する

すべての提案を集約した後、それらは追加のフィルタリング段階を通り、あなたにとって関連性のある提案だけが届くようにします。複数の基準でフィルタリングしますが、主なものは以下です。

  • 信頼性と重大度
    提案を生成するエージェントは、その問題に対応すべきだという確信度の見積もりと、重大度の評価もあわせて提示します。スケールは 0.000〜1.000 で、1.000 は本番環境で確実にクラッシュすることを意味します。確信度が低い、または重大度が低い提案は破棄されます。

  • 過去の提案との類似度
    提案の類似度では、リポジトリに対する過去の提案と、それに対してそのチームがどう反応したか(コメント内の 👍/👎 のリアクションを追跡)を見ます。embeddings と cosine similarity(いわゆるベクター検索)を使い、過去に低評価(👎)された提案と類似しすぎている提案を除外します。これにより、チームはレビューからどの種の提案を受け取りたいかを選べるようになります。

 

 

エージェントの評価

システムの性能を検証するために、私たちは既知の「バグがある PR」と「安全な PR」のセットを、定期的にバグ予測器に通しています。これは性能とコスト、プロンプト変更、モデル変更、新しいコンテキスト、そしてアーキテクチャ変更を評価するために行っています。各実行のたびに、precision(適合率)、recall(再現率)、accuracy(正解率)の数値が得られ、これらは時間とともに一貫して改善してきました。さらに、システムにリグレッションを導入しそうな場合の早期シグナルにもなります。とはいえ、これらの指標が有用な方向性のシグナルを与えてくれる一方で、私たちはその限界も認識しており、過度に依存しないようにしています。この制御された一貫性のある評価は、システムが進化していく中でも信頼感を維持するうえで重要でした。そして、この評価パイプラインの構築には初期コストがかかりましたが、現在プロダクトが得ている信頼性と信頼という面で、それを上回るだけの成果がありました。

 

 

データセット収集

すべてのデータセットは Langfuse に保存されています。各データセット項目は、既存の PR と、期待されるバグ(複数の場合もあります。バグなしの場合もあります)を指定します。現在、評価で使用しているデータセットはいくつかあります。

  • bug-prediction:基準となるテストの巨大なセットです。AI エージェントの構築を始めた当初、チームが手作業でキュレーションしました。現在は約70件の項目が含まれています。通常、スコア(precision、recall、accuracy)を報告するためにこれを使用します。
  • bug-prediction-performance-issues:パフォーマンス問題に特化したデータセットです。エージェントがパフォーマンスバグを予測できるよう改善する取り組みの一環として、パフォーマンス問題を含む PR のセットを追加しました。

 

コンテキストのモック

バグ予測エージェントの中核機能の一つは、Sentry のコンテキストを分析できることです。そのため、エージェント評価では、この機能の品質も評価することが重要になります。

最も単純な方法は、本番システムと同様にライブの Sentry API から Sentry コンテキストを直接取得することです。しかし、評価の文脈では、そうすると次の3つの大きな問題が生じます。

  • 複数回の実行の間で結果が一貫しない:新しい Sentry コンテキスト(例:新しい Sentry Issue が作られる)が追加されたり、既存の Sentry コンテキストが更新されたりする可能性があり、1 回目と 2 回目で取得結果が変わり得ます。
  • データセット項目(評価対象の PR)と評価を実行したタイミングによっては、リーク問題が起きる可能性がある:本来このテストで利用できるべきではない情報が利用可能になってしまう、という問題です。例として、テスト対象の PR が、その PR によって生成された Sentry Issue を取得できてしまうケースがあります。本番では、エージェントが実行される時点では PR の変更はまだシステムに反映されていないため問題になりません。しかし評価データセットでは、選定した PR がすでにマージ済みである可能性があります。
  • ライブ API へのクエリはパフォーマンスが良くない:現在の評価は、予測の品質を理解することが目的で、パフォーマンス面のテストは別に行っています(パフォーマンステストは評価とは分離しています)。

 

上記の問題それぞれに対処するため、私たちは「コンテキストのモック」という解決策を採用しました。これは、Sentry コンテキストをスナップショットし、キャッシュし、評価実行時にローカルから取得する方式です。

  1. 既存の Sentry コンテキスト DB をスナップショットするために、新しい PR のデータセットを作成する際にツールを実行します。このツールは、PR のタイムスタンプまでの Sentry コンテキストをすべて取得し、それらの PR が作成された後のタイムスタンプからは何も取得しないことを保証します。
  2. データはすべてサニタイズされ、インデックス化された小さな SQLite ファイルにまとめられます。このファイルはクラウドストレージへアップロードされ、各評価実行の開始時にダウンロードされます。
  3. 評価モードでエージェントを実行する際は、ライブの Sentry API から取得する代わりに、これらのツール呼び出しをモックし、ローカルの SQLite DB から Sentry コンテキストを直接取得するモックツール群へ切り替えます。

 

 

AI Code Review の今後の方向性

どのソフトウェアでもそうですが、私たちは AI Code Review をより良く、より役に立つものにするための改善を継続しています。評価の実施、新たに追加すべきコンテキストの検討、プロンプトの変更など、さまざまな取り組みを通じて改善を進めています。最も効果の大きいコンテキストを見つけるために、より多くのコンテキストソースを探っており、また、レビューが問題を指摘するのと同じくらい簡単に修正できるよう、予測結果をより実行可能な形にしていくことにも取り組んでいます。

ぜひ試してみて、使い心地を教えてください

 

 

Original Page: Building a Code Review system that uses prod data to predict bugs

 

 




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

 

シェアする

Recent Posts