8.4.4 ログと監視
- ログ、指標、追跡がそれぞれ何の問題を解決するのか理解する
- 構造化ログのフィールド設計を学ぶ
- LLM システムで特に監視すべき指標を理解する
- 最小限のログ + 監視の例を読めるようになる
初学者向けの用語ブリッジ
Section titled “初学者向けの用語ブリッジ”可観測性は、次の言葉を分けて考えると理解しやすくなります。
| 用語 | 何に答えるか | LLM アプリでの例 |
|---|---|---|
log | ある瞬間に何が起きたか | 検索開始、モデル呼び出し失敗、エクスポート完了 |
metric | 全体の傾向はどうか | エラー率、P95 レイテンシ、平均 token コスト |
trace | 1件のリクエストはどの経路を通ったか | API -> 検索 -> モデル -> テンプレート描画 -> 返却 |
P95 / P99 | 遅い 5% または 1% のリクエストはどれくらい遅いか | 平均は悪くないのに、たまに遅いと感じる原因を見る |
observability | 外側からシステムの状態を理解できるか | ログ、指標、トレース、ダッシュボード、アラートの組み合わせ |
まずはこう覚えると十分です。ログは個別イベント、指標は集計値、トレースは1件のリクエストの複数ステップをつなぐものです。
まずは全体像をつかもう
Section titled “まずは全体像をつかもう”ログと監視は、「何が起きたか -> 全体の様子はどうか -> 1件のリクエストは何を通ったか」という順で理解すると分かりやすいです。
flowchart LR A["ログ"] --> B["単発イベントを記録する"] B --> C["指標"] C --> D["全体の傾向を見る"] D --> E["トレース"] E --> F["1件のリクエストの流れを再現する"]この節で本当に解決したいのは次のことです。
- 問題が起きたとき、まずどの層を見るべきか
- なぜログ、指標、トレース のどれかひとつでも欠けると、原因調査が難しくなるのか
なぜこの話がとても重要なのか?
Section titled “なぜこの話がとても重要なのか?”LLM システムの障害は、普通の API より見えにくい
Section titled “LLM システムの障害は、普通の API より見えにくい”普通の API のエラーは、たいてい分かりやすいです。
- 500
- タイムアウト
- パラメータの間違い
でも LLM システムには、次のような“やわらかい障害”があります。
- 回答の質が下がる
- 検索結果がずれる
- token コストが急増する
- 特定の場面でだけ失敗する
だから観測できる仕組みがないと、システムはよくこうなります。
まだ動いているように見えるのに、実はもう半分壊れている。
ログと監視は、何を解決するのか?
Section titled “ログと監視は、何を解決するのか?”ざっくり 3 層に分けて考えられます。
- ログ:何が起きたか
- 指標:どれくらい起きているか、どれくらい速いか、どれくらい高いか
- 追跡:1件のリクエストがどの手順を通ったか
初心者向けのたとえ
Section titled “初心者向けのたとえ”可観測性は、次のように考えるとイメージしやすいです。
- システムにメーターパネル、ドライブレコーダー、整備記録を付ける
これがないと、システムが壊れても言えるのはせいぜいこうです。
- なんとなく変だ
でも、これがあれば分かるようになります。
- どこから異常が始まったか
- それは一時的か、ずっと続いているか
- 1件だけの問題か、システム全体の問題か
まずログを見る:いちばん基本で、いちばん壊されやすい
Section titled “まずログを見る:いちばん基本で、いちばん壊されやすい”「構造化ログ」とは?
Section titled “「構造化ログ」とは?”ただ1行の文字列を出すよりも、たとえばこういう出力です。
print("request received")それより価値が高いのは、次のような構造化されたフィールドを記録することです。
- request_id
- user_id
- stage
- レイテンシ_ms
- model_name
最小の構造化ログの例
Section titled “最小の構造化ログの例”log = { "trace_id": "trace_001", "stage": "retrieval", "query": "返金ポリシーは何ですか", "latency_ms": 120, "top_k": 3}
print(log)想定出力:
{'trace_id': 'trace_001', 'stage': 'retrieval', 'query': '返金ポリシーは何ですか', 'latency_ms': 120, 'top_k': 3}このログのいちばん大きな利点は、
あとからフィールドごとに検索したり、集計したりできることです。文字列を人間が目で読むだけではありません。
指標:システム全体の体温計
Section titled “指標:システム全体の体温計”監視すべき指標の代表例
Section titled “監視すべき指標の代表例”LLM システムでよく見る指標には、次のようなものがあります。
- リクエスト数
- エラー率
- 平均レイテンシ
- P95 / P99 レイテンシ
- token 使用量
- ツール呼び出し回数
- 検索ヒット率
最小の指標集計の例
Section titled “最小の指標集計の例”requests = [ {"latency_ms": 800, "tokens": 600, "ok": True}, {"latency_ms": 1200, "tokens": 750, "ok": True}, {"latency_ms": 3000, "tokens": 900, "ok": False}]
avg_latency = sum(r["latency_ms"] for r in requests) / len(requests)error_rate = sum(not r["ok"] for r in requests) / len(requests)avg_tokens = sum(r["tokens"] for r in requests) / len(requests)
print("avg_latency_ms =", avg_latency)print("error_rate =", error_rate)print("avg_tokens =", avg_tokens)想定出力:
avg_latency_ms = 1666.6666666666667error_rate = 0.3333333333333333avg_tokens = 750.0これが、監視ダッシュボードの最小の形です。
初学者がまず覚えるとよい指標表
Section titled “初学者がまず覚えるとよい指標表”| 指標 | 何に答えているか |
|---|---|
| リクエスト数 | システムは忙しいか |
| エラー率 | システムはよく失敗しているか |
| 平均 / P95 レイテンシ | ユーザーは待たされすぎていないか |
| token 使用量 | コストが異常ではないか |
| 検索ヒット率 | RAG の流れが悪くなっていないか |
| ツール呼び出し成功率 | Agent の実行層は安定しているか |
この表は、初心者にとても向いています。
「指標はたくさんある」という話を、理解しやすい問いに戻してくれるからです。

追跡(トレース):1件のリクエストは、何をたどったのか?
Section titled “追跡(トレース):1件のリクエストは、何をたどったのか?”なぜ LLM システムでは トレース が特に重要なのか?
Section titled “なぜ LLM システムでは トレース が特に重要なのか?”1件のリクエストが、1つのモジュールだけを通るとは限らないからです。たとえば次のような流れがあります。
- API 受付
- 検索
- ツール呼び出し
- モデル生成
- 後処理
もし最終的な回答が間違っていたら、知りたいのは次の点です。
- 検索が間違っていたのか
- モデル生成が間違っていたのか
- それともツール層が落ちたのか
最小の トレース の例
Section titled “最小の トレース の例”trace = [ {"trace_id": "trace_001", "stage": "api_in", "latency_ms": 20}, {"trace_id": "trace_001", "stage": "retrieval", "latency_ms": 120}, {"trace_id": "trace_001", "stage": "llm_generate", "latency_ms": 850}, {"trace_id": "trace_001", "stage": "response_out", "latency_ms": 15}]
for item in trace: print(item)想定出力では、同じ trace_id で各 stage の latency が並びます。
| stage | latency_ms |
|---|---|
api_in | 20 |
retrieval | 120 |
llm_generate | 850 |
response_out | 15 |
trace の核心は、
同じリクエストの「完全な旅の記録」を見られることです。
はじめて本番障害を調べるときの、いちばん安全な順番
Section titled “はじめて本番障害を調べるときの、いちばん安全な順番”通常は、次の順で見るのが安定しています。
- まず指標に全体的な異常があるかを見る
- 次にログで、どの種類のリクエストが失敗しているかを見る
- 最後に トレース をたどって、全体の流れを確認する
この順番のほうが、いきなり大量のログを読むよりずっと原因を見つけやすいです。
実際に近い、最小の観測ループ
Section titled “実際に近い、最小の観測ループ”import time
def timed_stage(name, fn, *args, **kwargs): start = time.time() result = fn(*args, **kwargs) latency_ms = int((time.time() - start) * 1000) log = { "trace_id": "trace_demo_001", "stage": name, "latency_ms": latency_ms } print(log) return result
def fake_retrieve(query): time.sleep(0.1) return ["返金ポリシー"]
def fake_llm(docs): time.sleep(0.2) return f"{docs} に基づいて回答を生成する"
docs = timed_stage("retrieval", fake_retrieve, "返金ポリシーは何ですか")answer = timed_stage("llm_generate", fake_llm, docs)print(answer)出力例です。実際の latency_ms は少し変わることがあります。
{'trace_id': 'trace_demo_001', 'stage': 'retrieval', 'latency_ms': 100}{'trace_id': 'trace_demo_001', 'stage': 'llm_generate', 'latency_ms': 200}['返金ポリシー'] に基づいて回答を生成するこの例は小さいですが、すでに次の重要な項目が入っています。
- トレース_id
- stage
- レイテンシ
LLM システムで、追加で特に監視すべきもの
Section titled “LLM システムで、追加で特に監視すべきもの”普通の API と比べて、LLM システムでは次の項目もよく監視します。
token コスト
Section titled “token コスト”これは、次のことに直結するからです。
- いくらお金がかかっているか
- prompt がどんどん長くなっていないか
たとえば次のようなものです。
- top-1 が当たっているか
- 検索結果が空の割合
ツール呼び出しの品質
Section titled “ツール呼び出しの品質”たとえば次のようなものです。
- ツール呼び出し成功率
- パラメータ検証の失敗率
- リトライ率
回答品質のシグナル
Section titled “回答品質のシグナル”たとえば次のようなものです。
- ユーザーの追加質問率
- ユーザーの修正率
- 低評価率
こうした指標はオフライン評価の代わりにはなりませんが、とても重要です。
なぜアラートは「サービスが落ちたか」だけを見てはいけないのか?
Section titled “なぜアラートは「サービスが落ちたか」だけを見てはいけないのか?”LLM システムの多くの問題は、直接 500 にはならない
Section titled “LLM システムの多くの問題は、直接 500 にはならない”たとえば次のような問題があります。
- 回答品質が落ち続ける
- token 使用量が急に2倍になる
- 検索ヒット率が大きく落ちる
こうした問題では、システムはまだ「動いている」かもしれません。
でも、業務としてはもう明らかに悪化しています。
だからアラートは 2 層に分けるのがよい
Section titled “だからアラートは 2 層に分けるのがよい”-
基本可用性アラート
- エラー率
- タイムアウト率
-
業務品質アラート
- 検索ヒット率の低下
- 平均 token 数の異常増加
- ユーザーのネガティブ反応の増加
初学者がまず覚えるとよいアラートの分け方
Section titled “初学者がまず覚えるとよいアラートの分け方”| アラートの種類 | 典型例 |
|---|---|
| 可用性アラート | エラー率が高い、タイムアウト率が高い |
| コストアラート | token が急増する、呼び出し回数が異常 |
| 品質アラート | 検索ヒット率が下がる、ユーザーの追加質問率が上がる |
この表は、LLM システムの「壊れ方」は1種類ではない、と教えてくれます。
「ナレッジベース駆動の SOP 文書アシスタント」なら、最初に何を監視すべき?
Section titled “「ナレッジベース駆動の SOP 文書アシスタント」なら、最初に何を監視すべき?”この種のシステムは、普通の質問応答よりも「見た目は大丈夫そうなのに、実はずれている」問題が起きやすいです。
最初に作るときは、特に次のフィールドを追うとよいです。
| 監視ポイント | 何を見ているか |
|---|---|
retrieved_count | ポリシー、ケース、チェックリスト根拠を取得できたか |
case_count | 処理済みケースを添付できたか |
policy_coverage | 必要なポリシーセクションが揃っているか |
export_success | Word の出力に成功したか |
schema_valid | 構造化結果が SOP テンプレート要件を満たしているか |
最小のログオブジェクトは、たとえばこう書けます。
log = { "trace_id": "trace_001", "topic": "返金エスカレーション SOP", "retrieved_count": 5, "case_count": 2, "policy_coverage": "complete", "schema_valid": True, "export_success": True,}
print(log)想定出力:
{'trace_id': 'trace_001', 'topic': '返金エスカレーション SOP', 'retrieved_count': 5, 'case_count': 2, 'policy_coverage': 'complete', 'schema_valid': True, 'export_success': True}この例は初心者にとても向いています。
なぜなら、この種のプロジェクトの監視ポイントが、
- モデルが速いかどうか
- だけではなく、
- ちゃんと根拠を取れているか
- SOP セクションが形になっているか
- 文書を書き出せているか
まで含むと分かるからです。
とても実用的なログフィールドの一覧
Section titled “とても実用的なログフィールドの一覧”LLM サービスを作るなら、実用的なフィールドはだいたい次のとおりです。
| フィールド | 役割 |
|---|---|
| トレース_id | 全体の流れをつなぐ |
| user_id / session_id | ユーザーや会話を特定する |
| stage | 今どの工程にいるか |
| レイテンシ_ms | その工程にどれくらいかかったか |
| model_name | どのモデルを使ったか |
| prompt_tokens / completion_tokens | コスト分析 |
| tool_name | どのツールを呼んだか |
| retrieval_topk | 検索設定 |
| error_code | 失敗の種類 |
すべてのログに全部入れる必要はありませんが、設計の出発点としてはとても使いやすい一覧です。
初学者がよくやるミス
Section titled “初学者がよくやるミス”文字列だけを記録して、フィールドを記録しない
Section titled “文字列だけを記録して、フィールドを記録しない”あとで集計しづらくなります。
成功だけを記録して、失敗を記録しない
Section titled “成功だけを記録して、失敗を記録しない”これだと、問題の切り分けがとてもつらくなります。
トレース_id がない
Section titled “トレース_id がない”問題が起きても、1本の流れを最後まで追えません。
システム可用性だけを監視して、業務品質を監視しない
Section titled “システム可用性だけを監視して、業務品質を監視しない”LLM プロジェクトでは、これは特に起こりやすい落とし穴です。
このページを終えたら、この証拠カードを残します。
- サービス契約
- エンドポイント、入力スキーマ、出力スキーマ、エラースキーマ
- 実行シグナル
- レイテンシ、スループット、ログ、ヘルスチェック、またはコンテナ状態
- 可観測性
- request id、trace id、構造化ログ、または metric
- 失敗確認
- タイムアウト、リトライの連鎖、ログ不足、デプロイ不一致
- 運用アクション
- バックオフ、キュー、アラート、段階展開、またはロールバック
この節でいちばん大事なのは、「ログの出し方を覚えること」ではなく、次を理解することです。
ログ、指標、トレース が一緒になって、システムの可観測性を作る。これが、本番に出した LLM サービスを本当に運用できるかどうかを決める。
観測できなければ、多くの障害は推測するしかありません。
観測できれば、システムは初めて保守可能になります。
これをプロジェクトやシステム設計として見せるなら、何を見せるべきか
Section titled “これをプロジェクトやシステム設計として見せるなら、何を見せるべきか”見せる価値が高いのは、たいてい次のようなものです。
- 「ログシステムをつないだ」こと
- ではなく、
- 1件のリクエストの トレース
- 主要な指標のセット
- 典型的なエラーをどう特定したか
- 品質アラートと可用性アラートをどう分けたか
こうすると、見る人には次のことが伝わりやすくなります。
- あなたが理解しているのは、可観測性の閉ループである
- 単にログを print できるだけではない
- 本節の
timed_stage()にerror_codeフィールドを追加してみましょう。 - 検索フェーズ専用の、自分のログ構造を設計してみましょう。
- 考えてみましょう。サービスのエラー率は変わっていないのに、ユーザーの追加質問率が急に上がったら、普通は何を意味するでしょうか?
- 自分の言葉で説明しましょう。なぜ LLM システムのアラートは、500 とタイムアウトだけを見ていてはいけないのでしょうか。
参考実装と解説
error_codeがあると、生のメッセージ文字列ではなく失敗タイプごとに集計できます。- 検索ログには
trace_id、query、rewritten query、filters、top_k、候補 ID、score、選ばれた citations、latency、user role/permission 結果を含めます。 - 追加質問率の上昇は、回答が不明確、引用不足、信頼度不足、またはタスク未完了を示すことがあります。システムエラーでなくても品質問題です。
- LLM の失敗には、検索不良、hallucination、policy ミス、tool 誤用、高コスト、満足度低下もあります。500 と timeout だけでは見逃します。