AIの目で見るバグの世界:デバッグの未来形
![AIの目で見るバグの世界:デバッグの未来形](https://agest.co.jp/wp-content/uploads/2024/06/20240508_column_thumb_01.jpg)
はじめまして、QAエンジニアのT.Tです。
今回は流行りのAIを使って問題発生のログ情報とソースコードを基にデバッグを実施してみました。
その結果についてお伝えします。
目次
AIについて
まず初めに、AIについてご説明します。AIとは、Artificial Intelligence(人工知能)の略で、人間の知能を模倣するコンピュータープログラムを指します。これにより、機械が推論、認識、判断などの人間と同じ知的な処理機能を実行することが可能になります。特に、近年のChatGPTなどでお馴染みの大規模言語モデルは驚異的な進化を遂げており、本日ご紹介するAIによるデバッグもその力を活用しています。
AIによるデバッグの可能性と課題
AIでデバッグをする理由
デバッグは、コード内のバグを特定・除去し、ソフトウェアの品質を向上させ、ユーザーの信頼性や満足度を高める重要なプロセスです。しかし、デバッグ作業は時間やリソースを多く必要とし、開発者にとってストレスの原因となることがあります。
そこで、AIによる効率的かつ品質向上につながるデバッグの可能性を探ることにしました。
AIを利用したデバッグの方法
まずは、デバッグの実施環境について説明します。今回は、OpenAI社が提供する「OpenAI API」を用いてデバッグを行いました。また、「Langchain※1」のAgents機能を使用しました。「Langchain」のAgentsは、目的を遂行するために言語モデルと渡されたツールを適宜呼び出し、その結果をまた言語モデルやツールにインプットします。これを目的を達するまで自律的に行います。今回はこの機能を利用し、問題が発生した際のログ情報、関連ソースコード、そして問題事象の情報を入力できるツールを用意し、AIがこれらを利用してデバッグが可能かどうかを実際に検証しました。
AIを利用したデバッグの課題と解決策
課題:問題発生時の情報の収集
AIを用いたデバッグを実施した際に、AIにインプットするログの収集に課題があることが分かりました。テストを実施し、問題が見つかった場合、その状況を取得するためにログを収集する必要があります。当初、テストケースを実施して問題が発生した際、実施日時を基に必要なログを収集し、AIへインプットしていました。しかし、複数名が同一環境でテストケースを実施する場合、実施日時によるログ抽出だけでは、情報が混在してしまいます。その結果、問題が発生したテストケースとは無関係なログ情報が紛れ込み、正常にデバッグが行えないことが判明しました。
解決策:APMと専用ツール
そこで、問題発生時のテストケースのログ情報の的確に収集できるように、下記の工夫を行いました。
APMを活用したトレース情報・ログの取得
トレースとは任意の処理単位(APIへのリクエストや関数呼び出し)の処理時間や呼び出し順序などを記録するものです。マイクロサービスなどでAPI間の複雑な呼び出し階層を持つものでも、トレースを記録することで「どこからどこにどの順序で呼び出されているのか」を処理時間とともに可視化できます。下図のようなイメージです。
![](https://agest.co.jp/wp-content/uploads/2024/07/image-155-1024x567.png)
今回はテスト時のトレース情報やログ情報を収集するために、APM※2を使用しました。その中でもトレースの共通規格であり、OSSで利用できるOpentelemetryを使用しました。Opentelemetryではトレースに合わせて関連するログ情報も取得でき、取得されたトレース情報を参照すると、特定テストケースに関連するログ情報のみ、収集できていました。Opentelemetryでは、トレースID毎にトレース情報・ログ情報を管理しており、テストケースとトレースIDを紐づけることができれば、個別のテストケースのトレース情報・ログ情報を取得できそうです。
参考記事:分散トレーシングの活用による次世代のテストを考える|Sqripts
テスト開始/終了とトレース開始/終了の連携
次に、テストケースとトレース情報・ログを紐づけるために、テストの開始と終了のタイミングでAPMのトレースを開始・終了する必要があります。そのため、私たちは手軽にトレースを開始・終了できるツールを開発しました。このツールでは、テストを開始する際に、任意のトレースIDが発行され、そのテストで行われた操作・処理のトレースが発行されたIDで記録されるようにします。これによりテストケースとトレースIDを紐づけることが可能となり、テストケースに紐づくトレース情報・ログを確実に取得することができるようになりました。
最終的に、今回AIでデバッグを行う際に用意したデバッグ環境は以下のようになります。
![](https://agest.co.jp/wp-content/uploads/2024/07/image-156.png)
AIによるデバッグ
それでは実際にAIを用いてデバッグを実施してみましょう。
今回デバッグの対象としたのは、Webアプリです。ユーザー登録機能やログイン機能などがあります。
今回調査する問題は、「ユーザー情報の更新失敗」という事象で、AIにこの事象を調査してもらうことにしました。
指示と入力データ
今回は、AIに対して以下のような指示を与えました。実際のプロンプトには利用するツールや調査手順などが含まれますが、わかりにくくなるためここでは省略しています。
エラーが発生したトレースのIDと、調査したい内容が与えられます。この内容を基に、問題が発生しているコードを確認し、原因を調査してください。
トレースID:{trace_id}
調査内容:更新ボタンを押下したところ「更新に失敗しました」と表示されました。理由を調査してください。
また、Agentsに与えるツールとしてPythonで下記の関数を作成しています。Agentsはこのツールを利用してデバッグを進めていきます。
- get_trace_list
- 対象のトレースIDを与えられると、トレース情報を保持しているDBから該当するトレース情報を取得する。テスト実施時のトレース情報を取得するためのツール。
- read_file
- 指定されたファイルを読み込む。調査対象のソースコードを読み込むためのツール。
今回インプットとなる問題発生時のトレース情報には調査対象のテスト開始から終了までのエンドポイントや関数呼び出しの順序情報、関数のパラメータ・戻り値、各所で出力されるログなどが含まれます。事象発生時には例外も発生しており、そのスタックトレースも含まれています。
結果
AIにデバッグを依頼した結果、以下のような回答が返ってきました。具体的なクラス名や関数名、ソースコード等についてはセキュリティ観点から変更しています。
エラーの内容を確認したところ、`SampleController` の `sample` メソッドで例外が発生していることがわかりました。具体的には、メールを送信する際に「An email must have a "To", "Cc", or "Bcc" header.」というエラーが発生しています。これは、メールを送信する際に宛先(To, Cc, Bcc)が指定されていないことを意味します。
エラーが発生しているコードは以下の部分です:
if ($status === 'sample_status') {
Mail::to($sample->email)->send(new SampleMail($sample->login_id, $sample->name, $sample->email));
// ...
}
このコードは、対象のステータスが「sample_status」に変更された場合に、変更されたことを通知するメールを送信しようとしています。しかし、`$sample->email` が空であるか、正しいメールアドレス形式でない場合、上記のエラーが発生します。
解決策としては、メールを送信する前に `$sample->email` が有効なメールアドレスであることを確認する必要があります。以下のようにコードを修正することを提案します:
if ($status === 'sample_status') {
if (filter_var($sample->email, FILTER_VALIDATE_EMAIL)) {
Mail::to($sample->email)->send(new SampleMail($sample->login_id, $sample->name, $sample->email));
} else {
Log::error("Invalid email address: " . $sample->email);
// ここで適切なエラーハンドリングを行う
}
// ...
}
この修正により、メールアドレスが無効な場合はエラーログに記録され、メールの送信はスキップされます。また、適切なエラーハンドリングを追加して、ユーザーにエラーを通知することも考慮する必要があります。
この結果を出力するためにAgentsはおおまかに下記のような動作をしているイメージです。
- プロンプトをllmに渡し必要なアクションを決定⇒トレース情報の取得(get_trace_listの呼び出し)
- get_trace_list(指定されたトレースID)の結果をllmに渡し、次のアクションを決定⇒エラーと関連するソースファイルの読み込み(read_fileの呼び出し)
a. 読み込んだソースコードとトレース情報をllmに渡し、llmが調査完了と判断(原因が判明)するまでアクションを繰り返す - 最終回答を出力
目的を達するまで利用可能なツールを用いて自律的に調査を進めてくれる有能なアシスタントという感じですね。
さて、そんなAIの出力結果をまとめると下記のようなことがわかります。
- エラーの発生箇所
- SampleControllerのsampleメソッドのメール送信部分
- エラーの発生理由(直接原因)
- $sample->emailの値が空かメールアドレスの形式として正しくない
- エラーの回避策
- メール送信前にアドレスチェックを行う
- 考慮点
- エラー発生時にユーザーにエラーを通知する
この結果から$sample->emailの値がおかしいということになり、その取得元であるDBのテーブルを確認したところ、正しくメールアドレスが格納されていないということが判明し、そのデータを修正することでエラーが解消しました。今回はテスト環境での事象だったのですが、その環境を構築する際に正しくデータが作成されていなかったようです。
このように、AIがトレース情報とソースコードを読み取り、トレース情報中のエラーログやパラメータ情報などから、例外発生の要因を解析し、ソースコードの問題発生箇所まで特定してくれました。従来のデバッグであればローカル開発環境で事象を再現しながらステップ実行したり、大量に出ているログから問題のログを見つけ出したりするなどの手間がかかっていたところですが、AIとAPMを利用することでその手間を削減することができました。
まとめ
時間やリソースを多く必要とするデバッグ作業について、AIが例外発生の要因を的確に解析し、ソースコードの問題発生箇所まで特定してくれることが分かりました。また、テストケースごとのトレース情報やログの収集は、APMやツールを活用することで比較的容易になり、テストケースが実行されて問題が発生した際には、迅速に情報を収集し、AIにデバッグを依頼する環境を整備することができました。
正直なところ、AIデバッグがどこまで問題を詳細に分析できるのか不安でしたが、私が想定していた以上に、細部まで分析し、問題点を指摘してくれました。AIに対する命令は比較的シンプルで汎用性があり、他のプログラムのデバッグにも流用可能だと思います。
近年、AIを利用した革新的なサービスが急速に増えています。その中で、AIによるデバッグは開発者たちを支援し、品質の向上に寄与すると感じています。適切な場面でAIを利用することが、より良いデバッグにつながると考えています。
※1 Langchain:大規模言語モデル(LLM)を効率的に実装するためのフレームワーク。開発者がLLMを使用したアプリケーションを簡単に作成できるように設計されており、特にGoogle CloudのLLMであるPaLM 2を操作する基本的な方法を提供している。
※2 APM:「Application Performance Management」の略で、アプリケーション性能管理を意味します。これは、アプリケーションやシステムの性能を監視し、管理するプロセスです。APMツールは、アプリケーションの応答時間や、構成要素のパフォーマンスを調査し、アプリケーション全体の稼働状況を把握するために使用されます。