跳至主要內容

OpenTelemetry v2

OpenTelemetry v2(OTel v2)是 LiteLLM Proxy 的下一代追蹤。它為您提供每個請求一條乾淨的 trace,涵蓋傳入的 HTTP 呼叫、驗證、防護欄、LLM 呼叫本身,以及內部資料庫/快取工作,全部都嵌套在同一棵樹中。

它遵循標準的 OpenTelemetry GenAI semantic conventions,因此它產生的 traces 可在任何 OTel 後端(Grafana Tempo、Jaeger、Honeycomb、Datadog,…)中讀取,並附帶針對熱門 LLM 可觀測性工具(Arize、Phoenix、Langfuse、Weave、Langtrace、Levo、AgentOps、SigNoz)的現成預設。

選用功能

OTel v2 預設為關閉。在您設定 LITELLM_OTEL_V2=true 之前,它不會執行任何內容。它與現有的 OpenTelemetry integration 分開,因此請擇一使用。如果您是從 v1 遷移,請參閱 Migrating to OpenTelemetry v2。

您將獲得什麼​

對您的 proxy 的單一請求會產生一條 trace,如下所示:

POST /v1/chat/completions                  ← HTTP request (server span)
├── auth /v1/chat/completions ← authentication
│ ├── postgres get_key_object ← DB lookups during auth
│ └── postgres get_team_membership
├── execute_guardrail presidio-pii ← each guardrail that runs
├── chat gpt-5.6-terra ← the LLM call (model, tokens, cost)
└── batch_write_to_db ← spend/usage written to DB

重點:

  • 一條 trace,端到端 — HTTP 請求、驗證、防護欄、LLM 呼叫與 DB 寫入都位於同一條 trace 中,且正確嵌套。
  • 豐富的 GenAI 屬性 — 每個 LLM 呼叫 span 都帶有 gen_ai.* 屬性:模型、提供者、token 使用量、成本、結束原因、請求參數等。
  • 基於標準 — 建置於官方 OpenTelemetry GenAI semantic conventions 之上,因此可與任何相容 OTel 的後端搭配使用。
  • 供應商預設 — 只要一行設定,就能以各工具所預期的格式將 traces 傳送到 Arize、Phoenix、Langfuse、Weave、Langtrace、Levo、AgentOps 或 SigNoz。
  • 預設安全 — 除非您明確選擇啟用,否則不會擷取 prompts 與 responses。雜訊路由(健康檢查、metrics 抓取、UI 資產)會自動排除。
  • 分散式追蹤 — 如果您的用戶端傳送 traceparent 標頭,LiteLLM 的 spans 會巢狀地嵌入您現有的 trace 中。

開始使用​

如需 Auto Router 組態識別、所選模型與已復原的分類器失敗,請參閱 Auto Router OTEL Telemetry。

在 proxy 環境中設定 LITELLM_OTEL_V2=true,然後從下方選擇一個目的地。

1. 將追蹤傳送到任何 OTLP 收集器​

此路徑會透過 OTLP(OpenTelemetry Protocol)將 spans 傳送到您已在下方端點執行的 collector 或後端;如果您尚未有,請先使用 Quickstart 中的 console exporter,直到準備好為止。在 proxy 的環境中設定此功能旗標以及標準的 OTEL_* 環境變數。不需要變更設定。

LITELLM_OTEL_V2=true
OTEL_EXPORTER="otlp_http"
OTEL_ENDPOINT="http://localhost:4318"

透過 OTEL_HEADERS 傳遞後端所需的驗證標頭:

OTEL_HEADERS="api-key=your-key,x-tenant=acme"

然後照常啟動 proxy:

litellm --config config.yaml

提出請求後,您會在後端看到每個請求一條 trace。

2. 將追蹤傳送到特定工具(預設)​

對於 LLM 可觀測性工具,請使用預設。預設知道工具的端點,並以該工具所預期的 schema 發出屬性。若要啟用其中之一,請在設定檔中的 callbacks 新增其名稱,並將該工具的憑證設為環境變數。

config.yaml
litellm_settings:
callbacks: ["arize"]
LITELLM_OTEL_V2=true
ARIZE_SPACE_ID="your-space-id"
ARIZE_API_KEY="your-api-key"
ARIZE_PROJECT_NAME="your-project-name" # recommended: names the project traces land in
同時傳送到多個後端

若要將相同的 traces 傳送到多個供應商,請在 callbacks 中列出每個預設,並設定各自的環境變數。例如,同時使用 Langfuse 與 Arize:

config.yaml
litellm_settings:
callbacks: ["langfuse_otel", "arize"]

每個預設都會新增自己的目的地,因此您的 spans 會平行送達所有目的地,且各自採用該工具的原生格式。

預設參考​

每個預設都會轉換為單一共享 tracer 上的一個 exporter。下表列出每個預設在 callbacks 中填入的回呼名稱、它讀取的憑證、傳送目的地、在標準化 gen_ai.* 鍵值之上新增的屬性詞彙,以及是否支援每個請求(每個團隊/金鑰)憑證。

預設回呼必要環境變數選用環境變數目的地詞彙每請求憑證
Arize AXarizeARIZE_SPACE_ID(ARIZE_SPACE_KEY 已棄用)、ARIZE_API_KEYARIZE_PROJECT_NAME(命名 traces 所屬的專案)、ARIZE_ENDPOINT(gRPC,預設 https://otlp.arize.com/v1)、ARIZE_HTTP_ENDPOINT(HTTP)Arize AX 平台OpenInference是
Arize Phoenixarize_phoenixPHOENIX_API_KEY(僅限 Phoenix Cloud;自架不需要)PHOENIX_COLLECTOR_HTTP_ENDPOINT 或 PHOENIX_COLLECTOR_ENDPOINT(協定由值推斷)、PHOENIX_PROJECT_NAMEPhoenix(自架或 Phoenix Cloud)OpenInference否
Langfuselangfuse_otelLANGFUSE_PUBLIC_KEY、LANGFUSE_SECRET_KEYLANGFUSE_HOST(或 LANGFUSE_OTEL_HOST;預設 https://us.cloud.langfuse.com,EU 為 https://cloud.langfuse.com)、OTEL_IGNORE_CONTEXT_PROPAGATION(設定 true 以捨棄傳入的 traceparent)Langfuse Cloud 或自架Langfuse是
Weave (W&B)weave_otelWANDB_API_KEY、WANDB_PROJECT_ID(<entity>/<project>)WANDB_HOST(預設 https://trace.wandb.ai)Weights & Biases WeaveOpenInference + Weave是
Langtracelangtrace無其自身項目—Langtrace,透過 OpenTelemetry Collector(Langtrace 僅攝取 JSON 格式 OTLP)Langtrace否
LevolevoLEVOAI_API_KEY、LEVOAI_ORG_ID、LEVOAI_WORKSPACE_ID、LEVOAI_COLLECTOR_URL—Levo collector僅標準化 gen_ai.*否
AgentOpsagentopsAGENTOPS_API_KEYAGENTOPS_SERVICE_NAME(預設 agentops)、AGENTOPS_ENVIRONMENT(無預設)AgentOps(https://otlp.agentops.ai/v1/traces)僅標準化 gen_ai.*否
SigNozsignozSIGNOZ_INGESTION_ENDPOINT(OTLP 基底 URL;會附加 /v1/traces)SIGNOZ_INGESTION_KEY(以 signoz-ingestion-key 傳送;自架可省略)SigNoz Cloud 或自架 SigNoz,OTLP HTTP僅標準化 gen_ai.*是

附註:

  • Arize AX 與 Arize Phoenix:完整功能的 AX 平台請使用 arize,Phoenix 本機或自架工作流程請使用 arize_phoenix。它們使用不同的憑證與端點,因此請針對您實際執行的後端選擇對應的回呼。產品特定設定請參閱專用的 Arize AX 與 Arize Phoenix 指南。
  • Langtrace 會在自訂路徑上只接收 JSON 格式的 OTLP,因此 litellm v2(會將 protobuf 傳送至 /v1/traces)無法直接匯出到它。請透過 OpenTelemetry Collector 重新編碼為 JSON;langtrace 預設只會為您的 spans 加上 Langtrace 屬性結構。Collector 設定請參閱上方的 Langtrace 分頁。
  • 詞彙是累加式的:每個預設的 spans 都會始終帶有標準 OpenTelemetry gen_ai.* 屬性;列出的詞彙會疊加其上,因此目的地工具會讀取其原生結構。

查看您的追蹤​

一旦後端以其預設完成設定,每個請求都會在該工具的 UI 中顯示為位於請求根節點下的 chat <model> span。以下每個分頁都涵蓋各供應商特有的注意事項(專案對應、端點變體、中繼資料鍵),這些最容易讓人出錯。

Arize 會呈現什麼​

開啟您的 Arize 專案;trace 會顯示在由 ARIZE_PROJECT_NAME 命名的專案下。openinference 對應器會將 OpenInference 詞彙寫入 LLM 呼叫 span,並同時附上標準 gen_ai.* 鍵,因此 Arize 會讀取其原生結構而不會丟失標準鍵。

由 openinference 對應器新增的屬性​

屬性轉述
openinference.span.kind固定的 LLM
llm.model_name, llm.providermodel, provider
llm.token_count.prompt, completion, totalusage split
llm.invocation_parametersrequest 參數的 JSON blob
llm.input_messages.{idx}.message.role, contentprompt(已開啟內容擷取),有上限
llm.output_messages.{idx}.message.role, contentresponse(已開啟內容擷取),有上限
input.value, output.value每則訊息的 role 與文字之 JSON 陣列(已開啟內容擷取)
llm.tools.{idx}.tool.name, description, json_schematool 定義,有上限

完整且權威的詞彙請參閱完整的 OpenInference 規格。

設定注意事項​

  • ARIZE_SPACE_KEY 是 ARIZE_SPACE_ID 的已棄用名稱;該預設仍為了向後相容而讀取它,但在新設定中請優先使用 ARIZE_SPACE_ID。

LiteLLM 在 Arize 中的 trace

擷取提示與回應​

預設情況下,OTel v2 只記錄中繼資料(模型、token、成本、時間),絕不會將提示或回應文字寫入您的 traces。這是刻意設計,且可將敏感內容排除在您的可觀測性後端之外。

若要擷取訊息內容,請明確選擇啟用:

# no_content (default) — never capture prompts/responses
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT="no_content"

# span_only — write prompts/responses as attributes on spans
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT="span_only"

# event_only — write prompts/responses on log events instead of span attributes
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT="event_only"

# span_and_event — write content to both spans and events
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT="span_and_event"

此閘門會在中央強制執行,因此會同時套用到每一個後端。當擷取功能停用時,使用者請求絕不可能強制將其提示送入您的後端。

Span 屬性​

屬性來自依序加到每個 span 上的一串對應器。標準化的 genai 對應器一律先套用,legacy 相容性對應器預設為啟用,而每個預設都會再加上一個供應商對應器。後面的對應器可以覆寫前面的對應器;因此同一個 span 會帶有數種描述同一請求的詞彙系統。

前兩個表格涵蓋 LLM 請求 span 的標準化詞彙。下方各節列出其他 span 類型,接著說明每個供應商對應器新增的內容。

LLM 呼叫 span,標準 gen_ai.* + litellm.*​

請求端金鑰:

屬性設定時機
gen_ai.operation.name一律(chat、text_completion、embeddings)
gen_ai.provider.name一律
gen_ai.request.model一律(使用者可見的模型群組名稱)
gen_ai.request.temperature, top_p, top_k, max_tokens在請求上設定時
gen_ai.request.frequency_penalty, presence_penalty, seed在設定時
gen_ai.request.stop_sequences在設定時(字串陣列)
gen_ai.tool.{idx}.name, description, parameters每個工具定義各一組,僅供前面的工具使用(原因)
litellm.request.tools.declared當請求宣告 tools 時;完整數量,不論是否有上限
server.address, server.port當已知提供者端點時

工具定義有上限​

只有前面宣告的工具會取得 gen_ai.tool.{idx}.* 屬性。工具定義是一個無上限的屬性家族;每個活躍詞彙系統中,每個工具每個欄位都會有一筆,而 OpenTelemetry 預設將每個 span 上限設為 128 個屬性。若某個代理程式宣告了一百個或更多工具,就會超過該上限,而因為限制會先捨棄最舊的屬性,上方的 gen_ai.* 屬性會成為被丟棄的項目,最後 span 只剩下工具結構描述。無論請求宣告了多少工具,這個上限都能確保模型、token 用量與成本留在 span 上。

這個上限是以整個 span 為單位,而不是按詞彙系統分別計算。工具定義總共最多可占 span 屬性預算的四分之一,而這個配額會在產生它們的各個詞彙系統之間分攤,因此可詳細列出的工具數量取決於有多少個啟用中:在預設的 genai 加 legacy 配對下,每個可有 5 個工具;一旦加入像 openinference 這類供應商詞彙系統後,每個則為 3 個工具。之所以這樣切分,就是為了避免三個詞彙系統把同一組工具各自展開後又總和超過限制。

litellm.request.tools.declared 一律會保留真實總數,因此您可以判斷每個工具的細節是否已被截斷。宣告工具數少於配額的請求會保留完整細節。

聊天訊息有上限​

openinference 對應器的 llm.input_messages.{idx}.* 與 llm.output_messages.{idx}.* 鍵是另一個無界家族:每則訊息兩個屬性,無論是提示詞還是回應皆然。超過幾十輪之後,光是它們就會超出 128 個屬性的預設值,並淘汰先前寫入的 gen_ai.* 模型、用量、成本與結束原因屬性。因此它們會依照 span 剩餘的預算來配置:其 tracer provider 的屬性數量上限(OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT,或注入式或每請求路由 provider 的 SpanLimits)再減去 span 上其他所有屬性,error.* 也包含在內。能放得下的對話會完整建立索引。放不下的則會整則訊息遺失,角色與內容一併移除,先捨棄價值最低者:中間的提示輪次,接著是額外的回應選項,再來是訊息 0 與最新一輪,最後才是第一個選項。保留下來的訊息會維持原始索引,因此即使 OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT 在對話結束前就截斷 input.value blob,訊息 0 與最新幾輪仍可存取。搭配 genai 加上 openinference 與 LITELLM_OTEL_LEGACY_COMPAT=false,一段 60 輪、每輪一個回覆且使用預設上限的對話會索引 llm.input_messages.0、.18 到 .59,以及 llm.output_messages.0;預設的 legacy 對應器也會自行新增鍵,因此啟用時能存活的中間輪次會更少。

這個上限只會影響按索引取用的便利鍵。input.value 與 output.value 仍會列出每則訊息的角色與文字,而標準的 gen_ai.input.messages 與 gen_ai.output.messages blobs 會保留完整的訊息物件(包含 tool calls 與非文字部分),因此整段對話仍會留在 span 上,而 Arize 也會繼續將其渲染。這些 blobs 是單一字串,所以 OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT(預設不受限制)在長對話中可能會將其截斷;此時保留下來的按索引鍵仍會顯示開頭與最新幾輪。Phoenix 在渲染 span 時會將按索引鍵壓縮成密集清單,因此索引中的缺口會在那裡顯示為較短的訊息清單,但順序相同。

回應、用量、成本、身分:

屬性設定時機
gen_ai.response.id, gen_ai.response.model成功時
gen_ai.response.finish_reasons成功時(字串陣列)
gen_ai.usage.input_tokens, gen_ai.usage.output_tokens成功時
gen_ai.input.messages, gen_ai.output.messages啟用內容擷取時
gen_ai.system_instructions啟用內容擷取時,且存在 system prompt 時
litellm.call_id一律
litellm.provider.model一律(實際傳送給提供者的模型字串)
litellm.request.streaming為 true 時
litellm.request.route在 proxy 上(root span 回報為 http.route 的同一路由:FastAPI 路由樣板,例如 /v1/responses/{response_id},或像 /openai/... 這類 passthrough prefix 上的字面路徑;當沒有 server span 時,例如路由在 OTEL_PYTHON_FASTAPI_EXCLUDED_URLS 中,或尚未安裝 FastAPI instrumentation 時,會退回到 proxy 在 auth 時記錄的路由)
litellm.cost.total成功時
litellm.cost.input, output, cache_read, cache_creation, tool_usage來源回報 breakdown 時
litellm.cost.original, discount_amount, discount_percent, margin_fixed_amount, margin_percent, margin_total_amount有回報時

狀態與錯誤:

  • 失敗時: span 會記錄標準的 exception 事件(exception.type、exception.message),將 error.type 設為例外類別,並將其狀態設為 ERROR。
  • 成功時: 狀態會維持 UNSET(semconv 預設值,與 FastAPI server span 相符)。只有真正的錯誤才會將其設為 ERROR,因此不要以 OK 的狀態作為警示條件。

其他 span 類型​

防護欄 span,使用 litellm.guardrail.* 命名空間:name、mode、status、provider、action、response、violation_categories、confidence_score、risk_score、masked_entity_count、duration、id、policy_template、detection_method。status 是 success、guardrail_intervened、guardrail_failed_to_respond 或 not_run 之一;封鎖性的 guardrail_intervened 或 guardrail_failed_to_respond 也會將 span 狀態設為 ERROR。

資料儲存 span(redis、postgres):db.system.name、db.operation.name、litellm.service.name、litellm.service.call_type。

內部服務 span:只有 litellm.service.* 鍵(沒有 db.*)。

MCP tool-call span:gen_ai.operation.name=execute_tool、mcp.method.name、mcp.session.id、gen_ai.tool.name、litellm.mcp.server.name、litellm.call_id、litellm.cost.total。gen_ai.tool.call.arguments 與 gen_ai.tool.call.result 與提示內容共用相同的內容擷取設定閘控。

Root HTTP server span:HTTP semconv 鍵 http.request.method、http.route、http.response.status_code、url.path,由 FastAPI instrumentation 加上標記(不是 LiteLLM 的任何 mapper)。

每個供應商預設設定也會在這些標準鍵之上再組合一個供應商專屬 mapper,因此目的端會以其原生 schema 讀取 trace。那些各供應商表格位於對應的 查看您的 traces 分頁下。

屬性慣例​

LiteLLM 會輸出一組標準的 GenAI 屬性,並透過新增 mapper 在其上疊加其他詞彙;啟用中的集合由 mapper_names 控制,而 genai 永遠優先。legacy mapper 預設為開啟(LITELLM_OTEL_LEGACY_COMPAT=true),並會以舊版 semconv-ai / Traceloop 名稱重新輸出相同資料,因此以那些名稱建立的儀表板在遷移期間仍可正常運作。當您的查詢已改用標準鍵後,可用 LITELLM_OTEL_LEGACY_COMPAT=false 將其關閉。供應商 mapper(openinference、langfuse、weave、langtrace)由其預設設定加入,且永遠不會取代標準鍵。

最常見的鍵在各詞彙中的對應如下:

標準(genai)舊版(Traceloop)OpenInference
gen_ai.usage.input_tokensgen_ai.usage.prompt_tokensllm.token_count.prompt
gen_ai.usage.output_tokensgen_ai.usage.completion_tokensllm.token_count.completion
gen_ai.provider.namegen_ai.systemllm.provider
litellm.request.streamingllm.is_streamingn/a
gen_ai.request.modeln/allm.model_name

每個 span 上的請求識別​

LiteLLM 會在授權邊界將一小組請求身分值寫入標準 OpenTelemetry Baggage。接著自訂的 span processor 會將這些值複製到 trace 中的每個 span,因此可依團隊或金鑰篩選防護欄、資料儲存或服務 span,而不必由 LiteLLM 逐一手動重設。

預設會將以下鍵寫入每個 span:

鍵值
litellm.team.idTeam UUID
litellm.team.aliasTeam 顯示名稱
litellm.team.metadataTeam 的自由格式中繼資料,已過濾至您加入 allowlist 的子鍵
litellm.api_key.hash呼叫者虛擬金鑰的雜湊值
gen_ai.request.model使用者可見的 model group 名稱
litellm.provider.model在提供者上派送的 model

另一組請求中繼資料欄位會寫入 litellm.metadata.* 命名空間下。預設值:

litellm.metadata.user_api_key_org_id、litellm.metadata.user_api_key_user_id、litellm.metadata.user_api_key_alias、litellm.metadata.user_api_key_end_user_id、litellm.metadata.requester_ip_address。

兩個預設值為了隱私而保持保守。終端使用者 id 可提升,但在頂層預設為關閉(它會識別個人);它會出現在 litellm.metadata.user_api_key_end_user_id 底下,而依使用者過濾的呼叫端應該啟用它。團隊的自由格式 metadata 絕不會整包送出;只有您列入 allowlist 的子鍵會離開程序,而 allowlist 預設是空的。

可透過 LITELLM_OTEL_BAGGAGE_PROMOTED_KEYS、LITELLM_OTEL_BAGGAGE_METADATA_KEYS 和 LITELLM_OTEL_BAGGAGE_TEAM_METADATA_KEYS 環境變數(以逗號分隔),或 callback_settings.otel 下對應的 YAML 清單來覆寫這些設定。

指標​

除了 traces 之外,OTel v2 還可以發出 GenAI client metrics:用於呼叫延遲、token 使用量與成本的直方圖,由您的後端在多個請求之間彙總。和 OTel v2 的其他功能一樣,它們在您啟用之前都會保持關閉。

在 proxy 環境中、LITELLM_OTEL_V2 旁邊設定旗標:

LITELLM_OTEL_V2=true
LITELLM_OTEL_INTEGRATION_ENABLE_METRICS=true

指標會透過您已為 traces 設定的 exporter 傳送。OTEL_EXPORTER(console、otlp_http、otlp_grpc)、OTEL_ENDPOINT 和 OTEL_HEADERS 會像處理 spans 一樣決定 metric 串流的去向,因此接收您 traces 的 collector 也會接收這些 metrics。

記錄了什麼​

每次成功的 LLM 呼叫都會記錄標準的 OpenTelemetry GenAI client metrics:

指標單位衡量內容
gen_ai.client.operation.durations整個 LLM 呼叫的牆上時鐘時間
gen_ai.client.token.usage{token}消耗的 tokens,依 gen_ai.token.type 屬性分成輸入與輸出
gen_ai.usage.costUSDLiteLLM 為該呼叫計算出的成本
gen_ai.server.time_to_first_tokens到第一個串流 token 的時間(串流呼叫)
gen_ai.server.time_per_output_tokens每個輸出 token 的平均時間
gen_ai.client.response.durations提供者端生成時間
本次版本已重新命名

gen_ai.usage.cost、gen_ai.server.time_to_first_token 和 gen_ai.server.time_per_output_token 先前是以 gen_ai.client.token.cost、gen_ai.client.response.time_to_first_token 和 gen_ai.client.response.time_per_output_token 發出。舊名稱不屬於 GenAI 語意慣例,且沒有任何廠商儀表板會查詢它們,因此沒有任何預先建置的內容能繪製 LiteLLM 的成本或延遲。如果您曾針對舊名稱手動建立面板或警示,請將它們改指向上方的名稱

每個樣本都帶有與對應 span 相同的身分屬性(operation、provider/system、request model、framework,以及選定的 metadata.* 欄位),因此您可以依 model、provider、key 或 team 分組這些直方圖。這些是 v1 OpenTelemetry 整合 發出的同一組六個 metrics,名稱與單位完全相同,因此為其中一個建立的儀表板也能讀取另一個。

控制 metric 屬性基數​

預設情況下,每個 metric 樣本都會標記完整的身分屬性集合,其中包含每個請求的欄位,例如 hidden_params 和數個 metadata.* 值。這些欄位對每個請求來說幾乎都是唯一的,因此每一個都會倍增您的後端追蹤的 time series 數量(每種不同屬性組合對應一條 series)。在高流量下,這會使 metric cardinality 爆增,而某些後端(例如 Splunk Observability Cloud)會開始節流或丟棄這些 metrics。

v2 讀取的 filter 與 v1 相同,來自您設定中的 callback_settings.otel.attributes。請在其中嵌入一個 attributes 區塊,並使用 include_list(allowlist;只輸出列出的屬性)或 exclude_list(denylist;輸出除列出屬性以外的全部內容)。兩者互斥。此 filter 只套用於 metrics;spans 會保留完整的屬性集合,因此 traces 依然豐富,同時 metric cardinality 仍保持在界限內。

此區塊位於 callback_settings.otel 底下。當設定了 LITELLM_OTEL_V2 時,在 otel 中列出 callbacks 會建立 v2 logger 並讀取此區塊(只有在該旗標關閉時才會建立舊版 v1 logger);當沒有列出 otel callback 時,預設路徑也會讀取此區塊。

不同於 v1,v2 沒有每個執行個體各自的 attributes 欄位,因此這個全域區塊是唯一的來源。v2 也不是在開機時,而是在請求記錄第一個 metric 時才延遲解析 filter,因此不良設定(兩個清單都設了,或使用了被禁止的名稱)會在第一次記錄的請求時才顯現,而編輯清單只有在重新啟動後才會生效。此 filter 只會在預設 OTLP 路徑上讀取(callback 名稱為 otel 或未設定);預設目的地例如 arize、arize_phoenix 和 langfuse_otel 會以完整屬性集合發出其 metrics,與 v1 相同。

config.yaml
callback_settings:
otel:
attributes:
exclude_list:
- hidden_params
- metadata.requester_metadata
- metadata.requester_ip_address
- metadata.spend_logs_metadata
- metadata.mcp_tool_call_metadata
- metadata.vector_store_request_metadata
- metadata.prompt_management_metadata

當您想要最精簡、最可預測的屬性集合時,請使用 include_list 精確列出要保留的屬性。未列出的內容都會從 metrics 中移除:

config.yaml
callback_settings:
otel:
attributes:
include_list:
- gen_ai.operation.name
- gen_ai.system
- gen_ai.request.model
- gen_ai.framework
- metadata.user_api_key_team_id
- metadata.user_api_key_org_id

gen_ai.token.type 絕不會被過濾掉。它是在 filter 執行後標記到 gen_ai.client.token.usage 上,因此輸入/輸出拆分會保留,不受您設定的清單影響,而在 include_list 或 exclude_list 中提及它都會被拒絕。

追蹤哪些路由​

高頻率、非 LLM 路由預設會排除,以免它們淹沒您的 traces:健康檢查(/health*)、Prometheus scrape(/metrics),以及靜態 UI/文件資產(/ui、/docs、/redoc、/_next、/openapi.json、favicon,…)。

若要變更此集合,請使用標準的 OpenTelemetry 環境變數(以逗號分隔的 paths、以子字串比對):

# Trace everything, including health checks
OTEL_PYTHON_FASTAPI_EXCLUDED_URLS=""

# Exclude only your own custom paths
OTEL_PYTHON_FASTAPI_EXCLUDED_URLS="/health,/internal"

每個金鑰 / 每個團隊的憑證(多租戶)​

一個 proxy 可以服務多個租戶:團隊或虛擬 key 會帶有自己的後端憑證,因此它的 traces 會送到該租戶自己的 Langfuse 專案、Arize 空間、Weave 專案、New Relic 帳戶或 SigNoz 帳戶,而不是 proxy 全域的那一個。憑證來自 proxy 在認證時解析出的 key 與 team,絕不來自 request body,因此呼叫端無法選擇其他租戶的後端。

這與 依 Team/Key 的 logging 中說明的相同 key/team callback 機制;v2 只是將其套用到 OTel 預設設定。沒有另外的管理員擁有的「destination」物件,而 /credentials 儲存的是 LLM provider 憑證,不是 logging 憑證。

哪些預設支援每次請求的憑證​

預設設定Callbackkey 或 team 上的欄位每個租戶會變動的內容
Langfuselangfuse_otellangfuse_public_key、langfuse_secret_key、langfuse_hostLangfuse 專案 traces 送達的位置,以及它們傳送到的伺服器
Arize AXarizearize_space_id(或已棄用的 arize_space_key)、arize_api_keyArize 空間
Weave (W&B)weave_otelwandb_api_key、weave_project_idW&B 帳戶與 Weave 專案
New Relicnewrelicnewrelic_api_key、newrelic_region(us 或 eu,預設 us)New Relic 帳戶及其資料中心
SigNozsignozsignoz_ingestion_key、signoz_ingestion_endpointSigNoz 帳戶,以及選用的 SigNoz Cloud 區域或其傳送到的自架 collector

其他所有預設設定(arize_phoenix、langtrace、levo、agentops)以及純粹的 otel OTLP exporter 都沒有每個請求的憑證,因此它們一律會以 proxy 全域設定輸出。對於 Phoenix,請改以專案而不是後端來區分租戶,並在團隊或 key 上設定 phoenix_project_name。若要維持單一後端,但用租戶自己的 service.name 標記其 spans,請改在 key 或 team 的 metadata 中設定 otel_service_name。

在團隊上設定​

請在 team 上註冊 callback;該 team 上的每個 key 之後都會以這些憑證輸出:

curl -X POST 'http://localhost:4000/team/<team-id>/callback' \
-H "Authorization: Bearer $LITELLM_API_KEY" -H 'Content-Type: application/json' \
-d '{
"callback_name": "langfuse_otel",
"callback_type": "success",
"callback_vars": {
"langfuse_public_key": "pk-lf-...",
"langfuse_secret_key": "sk-lf-..."
}
}'

GET /team/<team-id>/callback 會讀回 team 已註冊的內容,DELETE /team/<team-id>/callback/<callback_name> 會移除一個整合,而 POST /team/<team-id>/disable_logging 會移除全部整合。

在金鑰上設定​

一個金鑰可以在 metadata.logging 中攜帶自己的憑證,包括沒有團隊的金鑰:

curl -X POST 'http://localhost:4000/key/generate' \
-H "Authorization: Bearer $LITELLM_API_KEY" -H 'Content-Type: application/json' \
-d '{
"metadata": {
"logging": [{
"callback_name": "arize",
"callback_type": "success",
"callback_vars": {"arize_space_id": "...", "arize_api_key": "..."}
}]
}
}'

既有金鑰在 /key/update 上使用相同的欄位。您也可以在 Admin UI 中,於團隊或金鑰的記錄設定裡填入這兩者。

租戶會收到什麼​

為自己的後端命名的金鑰或團隊,會在單一根節點下收到整個追蹤:HTTP 請求、驗證步驟、帶有 token 與成本的模型呼叫,以及支出寫入。以前,它只會收到一個零散的 span,周圍沒有請求。

您針對同一後端的自有 exporter 將不再收到那些請求。如果某個團隊將 langfuse_otel 指向自己的專案,您的 Langfuse 專案就不會留下該團隊的任何內容;其他後端上的 exporter,例如一般的 otel collector,仍然會收到全部內容。

該租戶的副本會移除您這一側的請求內容:proxy 的資料庫端點、例外文字與堆疊追蹤、無法連線的 guardrail 錯誤,以及任何 URL 上的查詢字串。

如果該租戶的後端無法連線,其 spans 不會重新路由到您的 exporters。此覆寫的目的,是讓您停止保留該團隊的流量。

也保留您自己的副本​

將模式切換為 additive,您的 exporter 也會保留每個請求,因此整體組織視圖仍然完整:

litellm_settings:
otel_tenant_destination_mode: additive # default: "override"

LITELLM_OTEL_TENANT_DESTINATION_MODE=additive 也一樣。當某個團隊碰巧指定了您已經有輸出的專案時,該請求只會寫入一次,而不是兩次。

將租戶傳送到其自己的 Langfuse 主機​

金鑰或團隊上的 langfuse_host 會將該租戶的 traces 移到他們自己的 Langfuse 伺服器。請與其所屬的金鑰組一起傳入,因為單獨的主機會被忽略。也要將該主機加入 allowlist,否則 proxy 會記錄警告,並將請求保留在您的 exporters 上:

litellm_settings:
provider_url_destination_allowed_hosts: ["langfuse.acme.com"]

您自己的 LANGFUSE_HOST 不需要 allowlist 項目。SigNoz 的運作方式相同:金鑰或團隊上的 signoz_ingestion_endpoint,連同 signoz_ingestion_key 一起傳入,會將該租戶的 traces 移到其自己的 SigNoz Cloud 區域或 collector,而其主機必須加入 allowlist;沒有金鑰或不在 allowlist 上的端點會被忽略並附帶警告。請參閱 SigNoz per-team routing。其他預設會從 proxy 的環境取得其端點;每個租戶只會變動憑證,另外還有 New Relic 的區域,則從固定的 us/eu 對照表中選取。

只將模型呼叫傳送到 Langfuse​

預設情況下,Langfuse 專案,不論是您的還是租戶的,都會接收整個請求樹:HTTP 請求根節點、驗證步驟、資料庫與快取查詢、每一次 guardrail 執行、MCP 工具呼叫、模型呼叫,以及支出寫入。如果您只想讓 generations 出現在 Langfuse 中,請將 scope 設為 llm_only。proxy 會保留模型呼叫 spans,並停止將該請求的其他所有 span 傳送到該 Langfuse 專案。模型呼叫 span 是 proxy 代表呼叫端為每個提供者呼叫所發出的 span,無論路由為何:chat 與 text completions、Responses API 呼叫、embeddings、image、audio 與 OCR 生成、moderation、vector store 呼叫以及 agent 訊息都算在內。它們是攜帶 gen_ai.operation.name 的 spans,但不包含 MCP 工具呼叫。generation 會保留其 trace id,因此 Langfuse 仍會將一個請求的 generations 歸在同一個 trace 下,並保留呼叫端的 langfuse.trace.name、user.id、session.id 與 langfuse.trace.tags。由於請求根節點不再被傳送,該 Langfuse 專案會將 generation 作為 trace 的根節點,而當呼叫端未設定 langfuse_trace_name 或 metadata.trace_name 時,該 trace 會採用 generation 自己的名稱,例如 chat claude-3-5-haiku,而不是顯示為未命名。只有該專案中的 span 副本會被變更;full 專案或接收相同請求的一般 collector 仍會在請求 span 下看到 generation。當租戶的 full 專案與您自己的 llm_only exporter 屬於同一個 Langfuse 帳戶時,該帳戶會只接收整棵樹一次,而 generation 仍會保留在請求 span 下原本的位置

團隊或金鑰會在其 langfuse_otel 回呼中,將其設為與憑證並列:

curl -X POST 'http://localhost:4000/team/<team-id>/callback' \
-H "Authorization: Bearer $LITELLM_API_KEY" -H 'Content-Type: application/json' \
-d '{
"callback_name": "langfuse_otel",
"callback_type": "success",
"callback_vars": {
"langfuse_public_key": "pk-lf-...",
"langfuse_secret_key": "sk-lf-...",
"langfuse_span_scope": "llm_only"
}
}'

Admin UI 會將相同欄位顯示為在團隊或金鑰的 Langfuse OTEL 憑證旁,於 langfuse span scope 與 full 之間的 llm_only 選擇

您自己的 Langfuse exporter 在 proxy 環境中有一個獨立開關:

LITELLM_OTEL_LANGFUSE_SPAN_SCOPE=llm_only   # default: full

這兩者彼此獨立。租戶的 llm_only 只會縮小該租戶的專案,而操作員設定只會縮小由 LANGFUSE_PUBLIC_KEY 與 LANGFUSE_SECRET_KEY 建立的 exporter,無論 otel_tenant_destination_mode 處於哪種模式。兩者都不會影響一般的 otel collector 或任何其他預設,因此同一請求在 Datadog 或 Grafana 中的視圖仍然完整。可接受的值是 full 與 llm_only,而金鑰或團隊回呼中的任何其他值在儲存時都會被拒絕。此設定僅適用於 langfuse_otel 預設:在舊版 langfuse_span_scope 回呼或其他後端的回呼上儲存 langfuse 也會被拒絕,因為那裡沒有任何東西會讀取它

guardrail 與 MCP spans 會在 llm_only 下被捨棄,因此在任何模型被呼叫之前就失敗的 guardrail block,不會在該 Langfuse 專案中留下任何內容。當您依賴 Langfuse 觀察那些內容時,請保留 full

將 Redis 和 Postgres span 排除在租戶追蹤之外​

一次請求也會產生 proxy 自身資料存放區工作的 spans:用於 auth 與 response 快取的 Redis 查詢,以及 Postgres 的支出寫入。將 traces 傳送到自己帳戶的金鑰或團隊也會收到這些內容。設定 excluded_services 可停止將它們轉送到金鑰與團隊目的地,同時請求根節點、驗證、guardrail 與模型呼叫 spans 仍會通過:

callback_settings:
otel:
excluded_services: ["redis", "postgres"]

或者在 proxy 環境中:

LITELLM_OTEL_EXCLUDED_SERVICES=redis,postgres

當兩者都設定時,以設定值為準。可接受的名稱是 redis 與 postgres(postgresql 也適用),不論如何皆然。當某個 span 的 db.system.name,或舊版的 db.system,屬於列出的系統之一時,就會被捨棄。像 auth 這類未知名稱會被記錄為錯誤並忽略;其旁邊有效的名稱仍然適用,而 proxy 會正常啟動。若兩者都未設定,則不會捨棄任何內容

此設定只會縮小金鑰與團隊目的地,意即在團隊或金鑰上設定的 langfuse_otel、arize、weave_otel 或 newrelic 回呼,如同 在團隊上設定 中所示,無論是透過 API 或 Admin UI 中團隊的記錄設定。租戶不需要任何新設定。您的自有 exporters、otel collector,以及 litellm_settings.callbacks 中列出的任何預設(包括 proxy 全域的 langfuse_otel),都會繼續接收每個 span。沒有 excluded_services 的 Admin UI 欄位,因為它是 proxy 全域設定

langfuse_span_scope: llm_only 已經會捨棄這些 Langfuse 專案的 spans,連同請求根節點、驗證與 guardrail spans 一起捨棄。當租戶應保留請求樹的其餘部分時,請使用 excluded_services

須知​

金鑰會完全優先於團隊。如果金鑰有任何 metadata.logging 項目,團隊的回呼根本不會被考慮,而不是與金鑰的設定合併,因此覆寫某個後端的金鑰,必須重新列出它仍然想要的其他後端。

憑證只會套用到其所屬預設所貢獻的 exporter。攜帶某個租戶 Arize 金鑰的請求,絕不會改寫同時配置的 Langfuse 或自架 collector exporter 的標頭,因此租戶的金鑰不會洩漏到不應使用的後端。租戶未指定的後端上的 exporters 仍然會收到該請求的 spans,並使用它們自己的 proxy 全域憑證。

proxy 會針對每組不同的憑證快取一個 tracer provider,最多同時 256 個,並在汰除時 flush 最近最少使用的那一個。租戶變動的成本是 exporter 重新建立,而不是遺失 span。

os.environ/... 參照在金鑰與團隊 callback_vars 中會被拒絕;請傳入已解析的值。欄位名稱必須是已知的 callback 參數,而未知名稱會使整個項目失敗。

此 routing 僅適用於 traces。GenAI 用戶端指標(請參閱 指標)一律會送往 proxy 全域 exporter。

分散式追蹤​

如果傳入的請求帶有 W3C traceparent 標頭,LiteLLM 會延續該追蹤,而不是建立新的追蹤。接著,您的 LiteLLM span 就會以內嵌方式顯示在應用程式既有的分散式追蹤中,因此您可以在同一個檢視中追蹤請求從應用程式、經過 proxy,到 LLM 提供者的完整流程。

組態參考​

所有值皆為環境變數。布林旗標接受 true/false。

變數預設值用途
LITELLM_OTEL_V2false總開關。 在此項目設為 true 之前,OTel v2 不會執行任何動作。
LITELLM_OTEL_TENANT_DESTINATION_MODEoverrideadditive 會保留您自己的 exporter 對於某個 key 或 team 路由到其自身帳戶之請求的副本。
LITELLM_OTEL_LANGFUSE_SPAN_SCOPEfullllm_only 只會將模型呼叫 span 傳送到您自己的 Langfuse exporter。租戶會透過在 key 或 team 上設定 langfuse_span_scope 來設定自己的值。請參閱只將模型呼叫傳送到 Langfuse。
LITELLM_OTEL_EXCLUDED_SERVICESnone以逗號分隔的 datastores、redis 與 postgres,其 span 不會轉送到 key 和 team 目的地。callback_settings.otel.excluded_services 會覆寫此設定。請參閱將 Redis 和 Postgres spans 排除在租戶追蹤之外。
OTEL_EXPORTER (alias OTEL_EXPORTER_OTLP_PROTOCOL)consoleexporter 類型:console、otlp_http、otlp_grpc。
OTEL_ENDPOINT (alias OTEL_EXPORTER_OTLP_ENDPOINT)noneOTLP collector URL。設定 endpoint 即表示 otlp_http,除非您覆寫 OTEL_EXPORTER。
OTEL_HEADERS (alias OTEL_EXPORTER_OTLP_HEADERS)none提供給後端的以逗號分隔 key=value 驗證標頭。
OTEL_SERVICE_NAMElitellm顯示在後端中的 service.name 資源屬性。
OTEL_ENVIRONMENT_NAMEnonedeployment.environment 資源屬性(例如 production)。
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENTno_content提示詞/回應擷取:no_content、span_only、event_only、span_and_event。
OTEL_PYTHON_FASTAPI_EXCLUDED_URLShealth/metrics/UI routes要從追蹤中排除的以逗號分隔路徑(子字串比對)。設為 "" 可追蹤所有內容。
LITELLM_OTEL_INTEGRATION_ENABLE_METRICSfalse也發出 GenAI client 指標(持續時間、token 用量、成本、串流計時)。請參閱指標。
LITELLM_OTEL_LEGACY_COMPATtrue也發出舊版 Traceloop 金鑰名稱下的屬性。請參閱屬性慣例。

每一種 span 類型上的完整金鑰集合請參閱Span 屬性。

疑難排解​

沒有看到任何 traces 嗎?

  1. 確認 LITELLM_OTEL_V2=true 已在 proxy 的環境中設定。
  2. 先嘗試 OTEL_EXPORTER="console"。如果 span 印出到 stdout,問題就在您的 exporter endpoint/標頭,而不是 LiteLLM。
  3. 請確認您有觸發 LLM 路由(例如 /v1/chat/completions)。健康檢查與 UI 路由預設會被排除。
  4. 確認已安裝 opentelemetry-instrumentation-fastapi(請參閱需求)。

只看到 LLM 呼叫,但沒有 auth/postgres/server span? 這些 server 與 DB span 需要 FastAPI instrumentation 套件,因此請安裝 opentelemetry-instrumentation-fastapi。

我看到 metadata,但沒有 prompts/responses。 這是預設行為。設定 OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=span_only 即可擷取內容。

支援​

如有問題,請在 BerriAI/litellm 開啟 issue。