本番LLM障害の62%は、HTTPモニタリングで48時間以上検出されません。200 OKステータスコードはサーバーが応答したことを意味します——回答が正しかったこと、取得コンテキストが最新だったこと、エージェントが47回の冗長なツール呼び出しでループしなかったことではありません。ダッシュボードは緑なのに、幻覚が有料顧客に届き、プロンプトテンプレートの回帰が火曜日のデプロイ以降、すべての応答を汚染しています。
このガイドは3層の可観測性スタック——ベースOTel、GenAIセマンティック規約、OpenInferenceスパン種類——を構築し、すべてのユーザーリクエストをフォレンジックトレースツリーに変えます。1回の関数呼び出しで登録。テールベースサンプリングがストレージ予算を吹き飛ばさずにすべての障害トレースを保持します。
なぜあなたの監視ダッシュボードはLLM障害に盲目なのか
標準APMがLLMアプリケーションで失敗する理由
HTTP 200は「正しい回答」を意味しません。サーバーが応答したことを意味します。OpenTelemetryプロジェクトはワイヤーフォーマットとコレクターインフラを提供します——しかしLLMアプリケーションには、その基盤の上にセマンティック規約が必要です。標準APMは、LLMアプリケーションがHTTPステータスコードで表現できない方法で失敗するため機能しません:
- 幻覚。 モデルが自信満々で整った回答を返しました。中のすべての事実が間違っています。HTTPステータス:200。
- サイレント拒否。 モデルが答えるべきでした。拒否しました——丁寧に、完璧なJSONで。HTTPステータス:200。
- コスト急騰。 単純な分類タスクに推論強度が「high」に設定されたため、1つのリクエストが32,000思考トークンを生成。HTTPステータス:200。どのダッシュボードも思考トークン数を表示しません。
「リクエストが成功した」を見る必要はありません。「取得コンテキストの関連性が0.3で、それが生成忠実度0.4を引き起こし、つまりユーザーはすべてが緑に見えるにもかかわらず間違った回答を得た」を見る必要があります。検索品質が低下したとき、チャット完了と並行してエンベディング呼び出しをトレースすることは不可欠です——両方のエンドポイントを1つのトレースで計測すると全体像が明らかになります。
3層アーキテクチャ
これらは3つの選択肢ではありません。3つすべてが必要です。
層1:ベースOpenTelemetry。 ワイヤーフォーマット(OTLP)、コンテキスト伝搬(W3C trace context)、コレクターパイプライン。これが基盤です——すべての可観測性バックエンドがOTLPを話します。すべてのマイクロサービスがOTelスパンを出力します。この層がないと、ベンダーの独自形式に縛られます。あれば、1行も再計測せずにバックエンドを切り替えられます。
層2:OTel-GenAIセマンティック規約。 LLM操作の標準化されたスパン属性:gen_ai.system(どのプロバイダー)、gen_ai.request.model(どのモデルバージョン)、gen_ai.usage.input_tokensとgen_ai.usage.output_tokens(トークン消費)、gen_ai.operation.name(チャット vs エンベディング vs ツール実行)。この層がないと、すべてのLLMスパンが同一に見えます——チャット完了とエンベディング呼び出しを区別できません。
層3:OpenInferenceスパン種類。 GenAI規約がまだ列挙しない14のLLM認識スパンタイプ:LLM、CHAIN、RETRIEVER、TOOL、EMBEDDING、AGENT、RERANKER、GUARDRAIL、EVALUATOR、CONVERSATION、VECTOR_DBなど。この層がないと、RAGパイプラインのトレースはHTTP呼び出しのフラットなリストです。あれば、EMBEDDING —RETRIEVER —RERANKER —LLMを別々のステージとして見て——800msのレイテンシスパイクをどのステージが追加したか正確にわかります。
トレースツリー:理解の最小単位
孤立したログ行ではLLM問題を診断できません。問いは決して「この1つのAPI呼び出しが何を返したか」ではありません。「完全な因果連鎖は何だったか:ユーザークエリ——意図分類——取得チャンク——リランカースコア——最終プロンプト——LLM応答——評価スコア?」トレースツリーがその連鎖を捉えます。1つのトレース=1つのユーザーインタラクションの完全なフォレンジック記録。
可観測性が必須である理由
可視性のないコスト
監視されていないエージェントループは、私が調査したあるデプロイで週末に$5,000を燃やしました。エージェントが金曜夜にツール呼び出しループに陥りました——search_kb("return policy")が「結果なし」を返したので、search_kb("return policy EU")、次にsearch_kb("return policy Europe")、さらに44のバリエーション——それぞれがコンテキスト付きの完全なLLM API呼び出し。月曜の請求アラートまで誰も気づきませんでした。
スパンごとのコスト帰属——gen_ai.cost.input、gen_ai.cost.output、gen_ai.cost.totalをすべてのLLMスパンに付与——で数分で捕捉、数日ではなく。アラートを設定:単一トレースの累積APIコストが$2.00を超えたら通知をトリガー。アラートインフラのコストは週末の1インシデントより安いです。
コスト帰属は検出層です。防止層——キャッシュ戦略、モデル階層選択、バッチ処理——はコスト最適化戦略ガイドをご覧ください。
可視性のない品質
GPT-4oからGPT-5.5へのモデル移行はHTTPダッシュボードではクリーンに見えました。レイテンシは15%改善。エラー率は不変。ダッシュボードが示さなかったもの:新しいモデルが構造化出力をわずかに異なる扱いをした——これまでnullにならなかった3つのフィールドにnullが出現。形式は有効なJSON。それを消費するビジネスロジックが黙って壊れました。
スパンに付加した評価スコアがこれを5分で捕捉。評価ルーブリックが本番トレースに対して継続的に実行。忠実度、コンテキスト順守、形式準拠の低下がアラートをトリガー——ユーザーが気づく前に、サポートチケットがたまる前に、四半期の品質指標が打撃を受ける前に。デプロイ前にこれらの評価を実行するCI/CDパイプラインは、テストと評価ガイドをご覧ください。
可視性のないコンプライアンス
SOC 2 Type II監査人は尋ねます:「日付YのユーザーXの完全なAPI呼び出し記録を見せてください——何のデータが送られたか、どのモデルが処理したか、何が返されたか?」LLM API呼び出しが適切な保持ポリシー付きの構造化トレースを生成しないなら、答えは:「できません。」それは指摘事項ではありません。限定事項——監査レポートでははるかに高価な言葉です。
構造化トレースは監査証跡要件を満たします。SOC 2準備を完成させるアクセス制御とデータ処理管理——構造化アクセスログとコンプライアンスフレームワークに整合した保持ポリシー——がギャップを閉じます。
LLM可観測性のセットアップ方法
ステップ1:ワンコール登録
起動モジュールでの1回の関数呼び出し。それだけです。
from fi_instrumentation import register, ProjectType, SemanticConvention
trace_provider = register(
project_name="checkout_assistant",
project_type=ProjectType.OBSERVE,
semantic_convention=SemanticConvention.OPENINFERENCE,
metadata={"git_sha": "abc123", "environment": "production"},
batch=True,
)
from openinference.instrumentation.openai import OpenAIInstrumentor
from openinference.instrumentation.langchain import LangChainInstrumentor
OpenAIInstrumentor().instrument(tracer_provider=trace_provider)
LangChainInstrumentor().instrument(tracer_provider=trace_provider)
semantic_conventionパラメータがここでの重要なアーキテクチャ決定です。OPENINFERENCE、OTEL_GENAI、OPENLLMETRYのいずれかに設定——計測コードは変わりません。発行されるスパンの属性命名だけが変わります。これは可観測性バックエンドを切り替えるときに重要です:Datadogは1つの規約を期待し、Langfuseは別の、SigNozは3番目。1つの設定スイッチ。コード変更なし。
カバレッジ:50以上のPythonフレームワーク、39のTypeScriptパッケージ、24のJavaモジュール、C#。OpenAI、Anthropic、LangChain、LlamaIndex、Haystack、DSPy——すべて自動計測。
ステップ2:スパン拡張
user_id、session_id、prompt_versionのないスパンは孤児です。何が起きたかは見えますが、誰にまたはどの設定では見えません。
from contextlib import contextmanager
@contextmanager
def using_attributes(**kwargs):
# Attach attributes to the current span; all child spans inherit them
with tracer.start_as_current_span("user-interaction") as span:
for key, value in kwargs.items():
span.set_attribute(key, value)
yield span
with using_attributes(
session_id="sess_a1b2c3",
user_id="user_42",
metadata={
"prompt_template": "checkout_v3.2",
"ab_bucket": "treatment",
"feature_flag": "new_upsell_logic"
}
):
response = client.chat.completions.create(...)
すべてのトレースの最小属性セット:session.id、user.id、prompt.version、feature.id、tenant.id。これらがないと、トレースデータは「checkout_v3.2プロンプトが回帰の原因か、モデルバージョンの変更が原因か」に答えられません——インシデント中に最初に聞く質問です。
ステップ3:Eval-as-Span属性
別のデータベースにあり、トレースIDとの手動ジョインが必要な評価スコアは、誰も見ない評価スコアです。EvalTagがこれを修正:登録時に評価者を宣言し、そのスコアが元のスパンにgen_ai.evaluation.<rubric>.score属性として直接書き込まれます——追加リクエストレイテンシゼロ。
register(
project_name="checkout_assistant",
evaluators=[
"GROUNDEDNESS", # Are claims supported by retrieved context?
"CONTEXT_ADHERENCE", # Is the answer using the provided context?
"PROMPT_INJECTION", # Is there an injection attempt in the input?
"TASK_COMPLETION", # Did the model complete the requested task?
],
)
評価者は非同期で実行——ユーザーはスコアリングを待たずに応答を受け取ります。スコアは数秒以内にスパンに現れます。ダッシュボードが更新されます。5分間のウィンドウでGROUNDEDNESSが0.7を下回れば、アラートが発火。別の評価パイプラインなし。手動相関なし。1つのトレースツリー、1つの唯一の情報源。
ステップ4:テールベースサンプリング
ヘッドベースサンプリング——「すべてのトレースの10%をランダムに保持」——はほとんどのAPMセットアップのデフォルトです。LLMアプリケーションには壊滅的に間違っています。障害は稀。コスト外れ値は稀。低品質出力は稀。均一な10%ランダムサンプルは、実際に重要なトレースの90%を捨てます。
テールベースサンプリングはこれを反転:コレクターが保持するか決定する前に完全なトレースを見ます。保持ルール:
- 100%保持——エラー付きトレース(5xx、タイムアウト、レート制限)
- 100%保持——評価スコアが閾値未満のトレース
- 100%保持——コストがp95超のトレース
- 1〜10%保持——クリーンで高速で正しいトレース
ストレージコストは抑制されたまま。デバッグに必要なトレースは利用可能なまま。
ステップ5:3層保持
年に1回アクセスする規制コンプライアンスデータにClickHouse価格を払わない。
| 層 | ストレージ | 保持期間 | 内容 |
|---|---|---|---|
| ホット | ClickHouse / InfluxDB | 14-30 days | 全保持トレース —ライブダッシュボードとアラート |
| ウォーム | Columnar (S3/Parquet) | 90 days | 全トレース —コンプライアンスと遡及的デバッグ |
| コールド | オブジェクトストレージ(S3 Glacier) | 1-7 years | 圧縮トレース —規制上の保持 |
ホット層は運用用。ウォーム層は先四半期のインシデントのデバッグ用。コールド層は監査人用。各層は上の層よりおおよそ1桁安いです。
特定ワークロードの本番トレースパターン
RAGトレーストポロジ
RAGパイプラインのフラットなトレースは役に立ちません。各ステージを別個のスパンとして見る必要があります:
EMBEDDING span [model: text-embedding-3-small, tokens: 450, latency: 32ms]
→ RETRIEVER span [vector_db: pgvector, top_k: 20, index: hnsw, latency: 8ms]
→ RERANKER span [model: bge-reranker-large, candidates: 20→5, latency: 45ms]
→ LLM span [model: gpt-4o, input_tokens: 2840, output_tokens: 380, latency: 1.2s]
検索品質が低下したら、RETRIEVERスパンを見ます——類似度スコアが低いか? エンベディングモデルがドリフトしていないか確認。生成品質が低下したが検索は正常に見えるなら、LLMスパンを見ます——取得チャンクが正しい順序で供給されているか? システムプロンプトは無傷か? トポロジはどこを見るべきかを教えます——何かが間違っていることだけではありません。このトレースモデルの背後にある完全なRAGパイプラインアーキテクチャは、RAGプロダクションガイドをご覧ください。
エージェントトレーストポロジ
6ノードのLangGraphエージェントをフラットにトレースするとデバッグ悪夢です。100のスパンが見えます。どのノードがどのツールをトリガーしたか、どのツールが失敗したか、ループがどこで始まったかわかりません。
正しいトポロジ:
Root: AGENT span [session_id, user_id, task]
—Reasoning span: "plan to answer user's question about order status"
—TOOL span: lookup_order(order_id="ORD-12345") [latency: 180ms, status: success]
—Reasoning span: "order found, now check shipping"
—TOOL span: track_shipment(tracking_id="ZYX-987") [latency: 340ms, status: success]
—LLM span: synthesis [model: claude-sonnet-4, input_tokens: 1520, output_tokens: 210]
LangGraphには特に、すべてのスパンにlanggraph.node.name、langgraph.node.type、条件付きエッジイベントを追加します。これらがないと、6ノードエージェントがループに陥ったとき、どのノードが問題かわかりません。あれば、トレースがトポロジグラフとして描画され——ループ中のノードが視覚的に明らかです。これらのトレースを生成するマルチエージェントオーケストレーションパターンは、マルチエージェントアーキテクチャガイドをご覧ください。
スパンごとのコスト帰属
すべてのLLMスパンはgen_ai.cost.input、gen_ai.cost.output、gen_ai.cost.cache_read、gen_ai.cost.totalを持ちます。ゲートウェイレベルで階層予算を維持:組織——チーム——ユーザー——セッション。チーム別、モデル別、ユースケース別の月次コスト内訳を自動生成——トレースデータから。手動請求照合なし。「AIの行項目はブラックボックス」なし。暴走エージェントループが予算を吹き飛ばすのを防ぐユーザー別・エンドポイント別のリクエストスロットリング設定は、レート制限ドキュメントをご覧ください。
本番で高くつく可観測性のミス
ベンダーSDKのみの計測
DatadogのネイティブSDKで計測したのは、ダッシュボードへの最速ルートだったから。6か月後、チームはLLM固有トレーシングにLangfuseを評価したい。すべてのコールサイトを再計測する必要があります。
修正: OTelで計測。それが抽象化層です。エクスポーター設定を変えてバックエンドを切り替え——計測コードではなく。ベンダーSDKは出力ターゲットであり、計測フレームワークではありません。
均一ランダムサンプリング
サンプリング率10%。トレースの90%をランダムに捨てています——ユーザーがエージェントループで二重課金されたもの、プロンプトインジェクション試行がほぼ成功したもの、単一リクエストが$18の思考トークンを消費したものも含めて。
修正: テールベースサンプリング。コレクターが完全なトレースを見てから決定。障害、コスト外れ値、低品質出力:100%保持。クリーントレース:ベースライン比較用に小割合保持。
エージェントトレースにLangGraphトポロジなし
マルチノードエージェントをデプロイ。トレースはユーザーリクエストごとに87スパンをフラットリストで表示。先週の火曜日、エージェントがループに陥りました。犯人ノードの特定に3時間——「87のフラットスパン」は実行グラフを教えてくれないから。
修正: すべてのスパンにlanggraph.node.nameとlanggraph.node.type。条件付きエッジイベント。トレースビューアはエージェントをグラフとして描画——リストではなく。
ゲートウェイ発行スパンのスキップ
アプリケーションコードは念入りにトレース。しかしLLMには統合APIプラットフォーム経由でアクセス——ゲートウェイスパン(プロバイダー側レイテンシ、ルーティング決定、キャッシュヒット/ミス、フォールバックトリガー)はアプリケーショントレーサーには見えません。レイテンシが急騰したとき、自分のコードか、ゲートウェイか、プロバイダーか区別できません。
修正: ゲートウェイスパンはトレースの一部。APIプラットフォームがOTelスパンを出力するなら、コレクターに取り込むよう設定。統合APIエンドポイントはゲートウェイ可観測性の1つの統合ポイントを意味します——一度設定すれば、すべてのモデル呼び出しがカバーされます。
可観測性をフォールバックチェーン、リトライロジック、モデル横断のコストモニタリングと組み合わせるデプロイパターンは、プロダクション最適化ガイドをご覧ください。
FAQ
3層すべて(ベースOTel+GenAI+OpenInference)が必要ですか?
はい。ベースOTelはベンダーロックインを防ぎます。GenAIセマンティック規約はモデル固有属性(トークン数、モデル同一性)を標準化し、プロバイダーを切り替えてもダッシュボードが壊れないようにします。OpenInferenceスパン種類はLLM認識トポロジを与えます——なければ、すべてのスパンが「API呼び出し」で、検索と生成とツール実行を区別できません。
パフォーマンスオーバーヘッドは?
スパン作成と属性設定:レイテンシ影響1%未満。評価者(EvalTag):ユーザー向けレイテンシにゼロ影響——応答送信後に非同期実行。テールベースサンプリング:アプリケーションプロセスではなくコレクターで実行。総オーバーヘッドは、LLM API呼び出し自体の200ms〜10秒レイテンシに比べ無視できます。繰り返しトレースの入力コスト削減には、プロンプトキャッシュ戦略がスパン単位コスト帰属と自然に組み合わさります。
可観測性はセルフホストかSaaSか?
セルフホスト:SigNoz(OTelネイティブ、GenAIダッシュボード)+ClickHouse+Grafana。すでにOTelインフラを運用しているなら良い。SaaS:Langfuse Cloud(トレース優先、チューニング済みClickHouse)、Datadog LLM Observability。10分でダッシュボードが欲しいなら良い。OTel抽象化により、SaaSから始めて再計測なしでセルフホストに移行できます。
LLMトレースからPIIをどう削除するか?
コレクターで削除——アプリケーションコードではなく。クレジットカード番号、SSN、メールアドレスの正規表現パターン。名前と住所のNER分類器。APIキーとアクセストークンのカスタムルール。原則:生の秘密は決してネットワーク境界を越えない。外部バックエンドにエクスポートする前にコレクタープロセッサで剥がれます。
統合LLM可観測性への最も単純な道は?
1つの統合ポイント。すべてのモデル呼び出し——GPT、Claude、Gemini、DeepSeek——が1つのAPIエンドポイントを通れば、OTelエクスポートを一度設定。ゲートウェイ発行スパン(プロバイダー側レイテンシ、ルーティング決定、キャッシュヒット率、フォールバックトリガー)がアプリケーションスパンと一緒に整形済みで到着。3つの異なるプロバイダーSDKのトレースを縫い合わせる必要なし。レイテンシ急騰が自分のコードか、ゲートウェイか、プロバイダーか疑問に思う必要もなし——3つすべてが同じトレースツリーにあるから。すべてのモデルに1つのAPIキーから始めて、TokSpanプラットフォームで統合トレースを見ましょう。
LLMアプリケーションの可観測性は「成熟した組織」の関心事ではありません。「最初の本番デプロイ」の関心事です。ないことのコストは週末のインシデント、静かな品質回帰、監査限定事項——どれもここで説明した3層のセットアップより高いです。
registerパターンは1回の関数呼び出し。eval-as-span付加は追加レイテンシゼロ。テールベースサンプリングはストレージコストを抑えつつ、重要なすべてのトレースを保持。1つのサービスで1つのモデルから始めましょう。計測して、1日トレースツリーを見る。知らなかったことが起きているのを見つけるでしょう——誰もが本物の可観測性の初日にそうします。