62% 的生產 LLM 故障,HTTP 監控超過 48 小時偵測不到。200 OK 狀態碼只代表伺服器回應了——不代表答案正確、取回脈絡新鮮、或 Agent 沒有在 47 次冗餘工具呼叫中迴圈。你的儀表板是綠的,幻覺卻送到付費客戶手上,提示詞範本回歸毒害著自星期二部署以來的每一個回應。
這份指南建立三層可觀測性技術棧——基礎 OTel、GenAI 語意慣例、OpenInference span 種類——把每個使用者請求變成一份鑑識追蹤樹。一個函式呼叫就完成註冊。尾部取樣在燒不掉儲存預算的前提下,保留每一次失敗追蹤。
為什麼你的監控儀表板對 LLM 故障是盲的
標準 APM 為什麼在 LLM 應用上失敗
HTTP 200 不表示「正確答案」。它表示伺服器回應了。OpenTelemetry 專案提供線路格式與收集器基礎設施——但 LLM 應用需要在這個地基之上有語意慣例。標準 APM 失敗,是因為 LLM 應用以 HTTP 狀態碼無法表達的方式失敗:
- 幻覺。 模型回傳一個自信、格式良好的答案。裡面的每個事實都錯。HTTP 狀態:200。
- 沉默拒絕。 模型本來該回答。它拒絕了——很客氣、完美的 JSON。HTTP 狀態:200。
- 成本飆升。 一個請求生成 32,000 個思考 Token,因為一個簡單分類任務的推理強度被設成「high」。HTTP 狀態:200。沒有儀表板顯示思考 Token 數。
你不需要看「請求成功了」。你要看「取回脈絡的相關性是 0.3,導致生成忠實度 0.4,代表使用者得到錯誤答案、儘管一切看起來是綠的」。檢索品質下降時,把嵌入呼叫跟聊天完成一起追蹤是必要的——把兩個端點都打點進同一條追蹤,才能看到全貌。
三層架構
這不是三個選項。三個你都要。
第 1 層:基礎 OpenTelemetry。 線路格式(OTLP)、脈絡傳播(W3C trace context)、收集器管線。這是基底——每個可觀測性後端都講 OTLP。每個微服務都發 OTel span。沒有這層,你被綁死在某家廠商的專屬格式。有它,你不用重新打點任何一行就能換後端。
第 2 層:OTel-GenAI 語意慣例。 LLM 操作的標準化 span 屬性:gen_ai.system(哪家供應商)、gen_ai.request.model(哪個模型版本)、gen_ai.usage.input_tokens 與 gen_ai.usage.output_tokens(Token 消耗)、gen_ai.operation.name(聊天 vs 嵌入 vs 工具執行)。沒有這層,你所有 LLM span 看起來都一樣——分不出聊天完成和嵌入呼叫。
第 3 層:OpenInference span 種類。 十四種 LLM 感知 span 類型,GenAI 慣例還沒列完:LLM、CHAIN、RETRIEVER、TOOL、EMBEDDING、AGENT、RERANKER、GUARDRAIL、EVALUATOR、CONVERSATION、VECTOR_DB 等等。沒有這層,你的 RAG 管線追蹤只是一串扁平的 HTTP 呼叫。有它,你看到 EMBEDDING —RETRIEVER —RERANKER —LLM 是不同階段——而且精確知道哪個階段加了那 800ms 的延遲尖峰。
追蹤樹:理解的最小單位
一行孤立的日誌無法診斷 LLM 問題。問題從來不是「這一個 API 呼叫回了什麼?」而是「完整的因果鏈是什麼:使用者查詢——意圖分類——取回切塊——重排分數——最終提示詞——LLM 回應——評估分數?」追蹤樹捕捉這條鏈。一條追蹤=一個使用者互動的完整鑑識記錄。
為什麼可觀測性不可妥協
沒有可見性的成本
我調查過的一個部署,一個沒被監控的 Agent 迴圈在週末燒掉 $5,000。Agent 週五晚上撞進工具呼叫迴圈——search_kb("return policy") 回「沒有結果」、所以 Agent 呼叫 search_kb("return policy EU")、再呼叫 search_kb("return policy Europe")、再 44 個變體——每個都是帶脈絡的完整 LLM API 呼叫。直到星期一的帳單警示才有人注意到。
每 span 成本歸屬——gen_ai.cost.input、gen_ai.cost.output、gen_ai.cost.total 掛到每個 LLM span——幾分鐘就抓住,不是好幾天。設警示:任何單一追蹤的累積 API 成本超過 $2.00,就觸發通知。警示基礎設施的成本,比一個週末事故還低。
成本歸屬是偵測層。預防層——快取策略、模型階層選擇、批次處理——見成本最佳化策略指南。
沒有可見性的品質
從 GPT-4o 遷到 GPT-5.5 在 HTTP 儀表板上看起來很乾淨。延遲改善 15%。錯誤率不變。儀表板沒顯示的:新模型處理結構化輸出的方式略有不同——三個以前從不是 null 的欄位出現了 null。格式是合法 JSON。消費它的商業邏輯默默壞了。
掛在 span 上的評估分數五分鐘就抓住這個。你的評分量表持續對生產追蹤執行。忠實度、脈絡遵循、格式合規的任何下降都觸發警示——在使用者注意到之前、在客服工單堆積之前、在季度品質指標受創之前。在部署前跑這些評估的 CI/CD 管線,見測試與評估指南。
沒有可見性的合規
SOC 2 Type II 稽核員問:「請出示使用者 X 在日期 Y 的完整 API 呼叫記錄——送出了什麼資料、哪個模型處理了、回了什麼?」如果你的 LLM API 呼叫不產生帶正確保留政策的結構化追蹤,答案就是:「我們做不到。」那不是發現事項。那是保留意見——稽核報告裡貴很多的詞。
結構化追蹤滿足稽核軌跡要求。補上存取控制與資料處理控制、讓 SOC 2 準備完成——結構化存取日誌與跟你的合規框架對齊的保留政策——就能補上缺口。
怎麼設定 LLM 可觀測性
步驟 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——你的儀表化程式碼不變。變的只有發出的 span 上的屬性命名。換可觀測性後端時這很重要:Datadog 要一種慣例、Langfuse 要另一種、SigNoz 要第三種。一個設定開關。不改程式碼。
覆蓋範圍:50 多個 Python 框架、39 個 TypeScript 套件、24 個 Java 模組、C#。OpenAI、Anthropic、LangChain、LlamaIndex、Haystack、DSPy——全部自動儀表化。
步驟 2:span 豐富化
沒有 user_id、session_id、prompt_version 的 span 是孤兒。你看得到發生什麼,但看不到發生在誰身上或用了哪個設定。
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 屬性
存在另一個資料庫、要靠手動 join 追蹤 ID 的評估分數,是沒人看的評估分數。EvalTag 修好這個:註冊時宣告評估器,它們的分數直接以 gen_ai.evaluation.<rubric>.score 屬性寫回原始 span——零額外請求延遲。
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?
],
)
評估器非同步執行——使用者不用等打分就收到回應。幾秒內分數就出現在 span 上。你的儀表板更新。如果 5 分鐘視窗內 GROUNDEDNESS 掉到 0.7 以下,警示觸發。不用分開的評估管線。不用手動對應。一條追蹤樹、一個真相來源。
步驟 4:尾部取樣
頭部取樣——「隨機保留 10% 的追蹤」——是多數 APM 設定的預設。對 LLM 應用來說這是災難性的錯。故障是罕見的。成本離群值是罕見的。低品質輸出是罕見的。均勻的 10% 隨機取樣,把真正重要的 90% 追蹤丟掉。
尾部取樣反轉這件事:收集器在決定保留之前先看到完整追蹤。保留規則:
- 保留 100%——帶錯誤的追蹤(5xx、逾時、速率限制)
- 保留 100%——任何評估分數低於門檻的追蹤
- 保留 100%——成本高於 p95 的追蹤
- 保留 1–10%——乾淨、快速、正確的追蹤
儲存成本維持受控。你真正需要除錯的追蹤保持可用。
步驟 5:三層保留
別為一年才存取一次的監管合規資料付 ClickHouse 價。
| 層級 | 儲存 | 保留期間 | 內容 |
|---|---|---|---|
| 熱層 | ClickHouse / InfluxDB | 14-30 days | 保留全部追蹤——即時儀表板與警示 |
| 溫層 | Columnar (S3/Parquet) | 90 days | 完整追蹤——合規與回顧性除錯 |
| 冷層 | 物件儲存(S3 Glacier) | 1-7 years | 壓縮追蹤——法規保留 |
熱層是給營運的。溫層是給除錯上季事故的。冷層是給稽核員的。每層成本大約比上一層少一個數量級。
特定工作負載的生產追蹤模式
RAG 追蹤拓撲
扁平的 RAG 管線追蹤沒用。你需要把每個階段看成獨立 span:
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 span——相似度分數低嗎?檢查嵌入模型有沒有漂移。生成品質下降但檢索看起來正常時,你看 LLM span——取回切塊有沒有用正確順序餵?系統提示詞完整嗎?拓撲告訴你該看哪裡,而不只是「有東西不對」。這個追蹤模型背後的完整 RAG 管線架構,見RAG 生產指南。
Agent 追蹤拓撲
一個 6 節點 LangGraph Agent 被扁平追蹤,是除錯惡夢。你看得到 100 個 span。你不知道哪個節點觸發了哪個工具、哪個工具失敗、迴圈從哪裡開始。
正確拓撲:
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 特別要加:每個 span 上放 langgraph.node.name、langgraph.node.type、條件邊事件。沒有這些,你的 6 節點 Agent 卡進迴圈時,你分不出哪個節點是問題。有它們,追蹤會以拓撲圖呈現——迴圈中的節點一目了然。產生這些追蹤的多 Agent 編排模式,見多 Agent 架構指南。
每 span 成本歸屬
每個 LLM span 都帶 gen_ai.cost.input、gen_ai.cost.output、gen_ai.cost.cache_read、gen_ai.cost.total。在閘道層維持階層預算:組織——團隊——使用者——工作階段。自動產生按團隊、模型、使用情境的月成本拆分——從追蹤資料。不用手動對帳。「AI 那行是黑盒子」不存在。設定使用者別/端點別的請求節流、防止暴走 Agent 迴圈炸掉預算,見速率限制文件。
在生產裡貴得嚇人的可觀測性錯誤
只用廠商 SDK 打點
你用 Datadog 的原生 SDK 打點,因為那是最快到儀表板的路。六個月後,團隊想評估 Langfuse 做 LLM 特定追蹤。每一個呼叫點都要重新打點。
修法: 用 OTel 打點。它才是抽象層。改匯出器設定換後端——不是儀表化程式碼。廠商 SDK 是輸出目標,不是儀表化框架。
均勻隨機取樣
你的取樣率 10%。你在隨機丟掉 90% 的追蹤——包括使用者因為 Agent 迴圈被重複收費那條、提示注入嘗試幾乎成功那條、單一請求吃掉 $18 思考 Token 那條。
修法: 尾部取樣。收集器看到完整追蹤再決定。故障、成本離群、低品質輸出:保留 100%。乾淨追蹤:保留小比例做基準對照。
Agent 追蹤裡沒有 LangGraph 拓撲
你部署了多節點 Agent。追蹤顯示每個使用者請求 87 個 span、扁平成列表。上週二 Agent 卡進迴圈。花了三小時才找出肇事節點——因為「87 個扁平 span」不告訴你執行圖。
修法: 每個 span 上放 langgraph.node.name 和 langgraph.node.type。條件邊事件。你的追蹤檢視器應該把 Agent 畫成圖,不是列表。
跳過閘道發出的 span
你細心追蹤應用程式碼。但你透過統一 API 平台存取 LLM——閘道 span(供應商端延遲、路由決定、快取命中/未命中、備援觸發)對你的應用程式追蹤器是看不見的。延遲飆升時,你分不出是自己的程式、閘道、還是供應商。
修法: 閘道 span 是你追蹤的一部分。如果你的 API 平台發 OTel span,設定收集器接收它們。統一 API 端點代表閘道可觀測性只有一個整合點——設定一次,每個模型呼叫都涵蓋。
把可觀測性和備援鏈、重試邏輯、跨模型成本監控配對的部署模式,見生產最佳化指南。
常見問題
三層都需要嗎(基礎 OTel+GenAI+OpenInference)?
都需要。基礎 OTel 防止廠商鎖定。GenAI 語意慣例標準化模型特定屬性(Token 數、模型身分),換供應商儀表板也不會壞。OpenInference span 種類給你 LLM 感知拓撲——沒有它們,每個 span 都是「一次 API 呼叫」,你分不出檢索、生成、工具執行。
效能開銷多少?
span 建立與屬性設定:延遲影響不到 1%。評估器(EvalTag):對使用者延遲零影響——回應送出後非同步執行。尾部取樣:在收集器裡跑、不在你的應用程式行程。總開銷相對於 LLM API 呼叫本身的 200ms–10 秒延遲,可以忽略。重複追蹤的輸入成本削減,提示詞快取策略與 span 層級成本歸屬天然互補。
可觀測性要自架還是 SaaS?
自架:SigNoz(OTel 原生、GenAI 儀表板)+ClickHouse+Grafana。已經在跑 OTel 基礎設施就選這個。SaaS:Langfuse Cloud(追蹤優先、調好的 ClickHouse)、Datadog LLM Observability。十分鐘就要有儀表板就選這個。OTel 抽象讓你能從 SaaS 開始、不用重新打點就遷到自架。
怎麼從 LLM 追蹤裡清除 PII?
在收集器清除——不要在應用程式碼。信用卡號、SSN、電子郵件地址的正規表達式。姓名與實體地址的 NER 分類器。API 金鑰與存取 Token 的自訂規則。原則:原始機密永遠不跨過你的網路邊界。它們在匯出到任何外部後端之前,在收集器處理器裡就被剝掉。
統一的 LLM 可觀測性最簡單的路徑?
一個整合點。每個模型呼叫——GPT、Claude、Gemini、DeepSeek——都流過一個 API 端點,你就設定一次 OTel 匯出。閘道發出的 span(供應商端延遲、路由決定、快取命中率、備援觸發)以預格式化狀態跟著應用程式 span 一起到。不用把三家供應商 SDK 的追蹤縫在一起。不用猜延遲尖峰是在你的程式、閘道、還是供應商——因為三個都在同一條追蹤樹裡。從「所有模型一把 API key」開始,在TokSpan 平台上看到統一追蹤。
LLM 應用的可觀測性不是「成熟組織」才要擔心的。是「第一次生產部署」就要擔心的。沒有的代價,是週末事故、沉默的品質回歸、稽核保留意見——每一樣都比設定這裡描述的三層貴。
register 模式只要一次函式呼叫。eval-as-span 附屬零額外延遲。尾部取樣把儲存帳單壓在控制內、同時保留每一條重要的追蹤。從一個服務、一款模型開始。打點它。看一天的追蹤樹。你會發現一件你原本不知道在發生的事——每個人在第一次擁有真正可觀測性的那天都會。