FessのAI検索モード(RAG/LLM機能)では、各コンポーネントのログ出力が統一されておらず、運用時のトラブルシューティングやログ分析がしにくい状況でした。今回、ログレベルとプレフィックスを整理して、運用しやすくしました。
変更の背景
AI検索モードでは、チャットリクエストの処理、LLMクライアントの管理、意図検出、検索結果の評価など、複数のコンポーネントが連携して動作します。しかし、これまでのログ出力にはいくつかの問題がありました。
- ログメッセージにプレフィックスが付いていないものがあり、RAG/LLM関連のログをフィルタリングしにくい
- チャット完了時のログがdebugレベルだったため、本番環境でレイテンシやトークン使用量を把握するにはdebugログを有効にする必要があった
- エラーログで
LlmExceptionと予期しない例外が区別されていなかった - LLMクライアントのライフサイクルイベント(初期化・シャットダウン)がログに記録されていなかった
ログプレフィックスの統一
すべてのRAG/LLM関連のログメッセージに、以下のプレフィックスを付けるようにしました。
| プレフィックス | 用途 |
|---|---|
[RAG] | チャット処理全般(リクエスト、レスポンス、エラー) |
[LLM] | LLMクライアントの管理(初期化、シャットダウン、同時実行制御) |
[RAG:INTENT] | 意図検出(ユーザーの質問の意図を判定する処理) |
[RAG:EVAL] | 検索結果の評価(検索結果の関連性を判定する処理) |
これにより、grep '[RAG]'やgrep '[LLM]'でログを簡単にフィルタリングできるようになりました。
ログレベルの見直し
debug → info への昇格
チャット完了時のログをdebugからinfoレベルに変更しました。これにより、本番環境でもレイテンシやソース数などの重要なメトリクスを確認できます。
[RAG] Chat completed. sessionId=xxx, sourcesCount=5, elapsedTime=1234ms
[RAG] Stream chat completed. sessionId=xxx, sourcesCount=3, elapsedTime=2345ms
[RAG] Enhanced chat completed. sessionId=xxx, intent=SEARCH, sourcesCount=5, responseLength=500, elapsedTime=3456ms
意図検出や検索結果評価の完了ログもinfoレベルで出力するようにしました。
[RAG:INTENT] Intent detected. intent=SEARCH, query=xxx, elapsedTime=500ms
[RAG:EVAL] Evaluation completed. hasRelevant=true, relevantCount=3, totalResults=10, elapsedTime=300ms
LLMクライアントのライフサイクルログの追加
LLMクライアントの初期化・シャットダウン時にinfoレベルでログを出力するようにしました。
[LLM] OpenAI initialized. model=gpt-4, timeout=30000ms, maxConcurrent=5
[LLM] OpenAI shutting down.
同時実行制限とリクエスト中断のwarnログ追加
同時実行制限の超過やリクエスト中断時にwarnレベルでログを出力するようにしました。
[LLM] Concurrency limit exceeded. name=OpenAI, maxConcurrent=5, waitTimeout=10000ms
[LLM] Request interrupted while waiting for concurrency permit. name=OpenAI
エラーログの改善
LlmExceptionと予期しない例外を区別してログ出力するようにしました。
LlmException: LLMサービス側の既知のエラー。スタックトレースなしでメッセージのみ出力(warnレベル)- 予期しない例外: プログラムのバグなど。スタックトレース付きで出力(warnレベル)
if (e instanceof LlmException) {
logger.warn("[RAG] LLM error during chat. sessionId={}, error={}", session.getSessionId(), e.getMessage());
} else {
logger.warn("[RAG] Unexpected error during chat. sessionId={}, error={}", session.getSessionId(), e.getMessage(), e);
}
LLMの既知のエラーではスタックトレースを省略することで、ログの可読性が向上します。
まとめ
今回の変更は、ログ出力の整理のみで動作の変更はありません。運用時に以下のメリットがあります。
- プレフィックスベースのフィルタリングで、RAG/LLM関連のログを素早く抽出可能
- debugログを有効にしなくても、チャット処理のレイテンシやソース数などのメトリクスを確認可能
- LLMクライアントのライフサイクルイベントを追跡可能
- エラーの種類に応じた適切なログ出力で、トラブルシューティングが効率化