排查推理請求變慢、或者看板上的指標與預期對不上時,需要確認鏈路上每個 Span 對應哪個執行階段、每個屬性的統計口徑是什麼、指標該怎麼計算。本文列出 ARMS Python 探針接入 vLLM / SGLang 推理引擎後實際上報的全部 Span、Span 屬性、Span Event 與指標,可在分析調用鏈、配置指標看板和定位效能問題時逐項對照。
Span 的通用約定
所有 Span 的 SpanKind 均為 INTERNAL。探針自身產生的 Span 通過 gen_ai.span.kind 屬性工作表達業務語義(取值 LLM / EMBEDDING / RERANKER);引擎原生埋點產生的 Span 不攜帶該屬性,需要靠 Span 名稱區分所處階段。
耗時類屬性的單位隨引擎與版本不同,跨引擎或跨版本對照同名欄位(如 gen_ai.latency.e2e、gen_ai.latency.time_in_queue、gen_ai.usage.prompt_tokens)時需注意:
引擎與版本 | 耗時類屬性單位 |
vLLM V0 | 秒 |
vLLM V1 | 納秒 |
SGLang 入口 Span 與請求 Span | 秒 |
配置看板或警示閾值前先確認單位;指標的單位見各指標表的“單位”列。
vLLM 的 Span
Span 構成與層級
vLLM 情境下的 Span 分為兩類:探針在 OpenAI 相容介面層產生的入口 Span,以及引擎內部產生的請求級 Span 與階段子 Span。引擎內部 Span 的層級關係如下:
llm_request ← 單個請求在引擎內的完整生命週期,V0 與 V1 均產生
├─ wait ← 僅 V1、採集精度不低於 1
│ └─ kv_transfer ← 嵌套在 wait 之內,僅 V1、採集精度不低於 1
├─ prefill ← 僅 V1、採集精度不低於 1
└─ decode ← 僅 V1、採集精度不低於 1kv_transfer 嵌套在 wait 之內而非與之並列:vLLM 在等待遠端 KV 期間請求始終處於 WAITING_FOR_REMOTE_KVS 狀態,傳輸耗時被包含在等待視窗裡,因此“wait 耗時減去 kv_transfer 耗時”才是真實的排隊時間。在 PD 分離部署下,Prefill 節點只產生 prefill 子 Span,Decode 節點只產生 decode 子 Span。
Span 列表
Span 名稱 | 產生位置 | 說明 |
| OpenAI 相容介面層 | Chat Completions 請求入口, |
| OpenAI 相容介面層 | Completions 請求入口, |
| OpenAI 相容介面層 | Embedding 請求入口 |
| OpenAI 相容介面層 | Rerank / Score 請求入口 |
| 引擎內部 | 單個請求在引擎內的完整生命週期,V0 與 V1 均產生 |
| 引擎內部 | 請求排隊等待被調度的時間,僅 V1、採集精度 ≥ 1 |
| 引擎內部 | 從遠端拉取 KV Cache 的耗時,掛在 |
| 引擎內部 | Prefill 階段耗時,僅 V1、採集精度 ≥ 1 |
| 引擎內部 | Decode 階段耗時,僅 V1、採集精度 ≥ 1 |
入口 Span 屬性
入口 Span 由通用 GenAI 埋點產生,屬性口徑與其他大模型架構插樁保持一致。
屬性 | 說明 |
| 業務語義類型, |
| 操作類型, |
| 請求指定的模型名 |
| 請求的候選數量(對應 |
| 採樣溫度 |
| Top-P 參數 |
| Top-K 參數 |
| 最大產生 token 數 |
| 是否為流式請求 |
| 請求攜帶的 user 欄位 |
| 流式情境下的請求標識 |
| 響應 ID |
| 響應中返回的模型名 |
| 結束原因 |
| 輸入 token 數 |
| 輸出 token 數 |
| token 總數 |
| 輸入內容,受內容採集開關控制 |
| 輸出內容,受內容採集開關控制 |
llm_request Span 屬性(vLLM V0)
V0 引擎的耗時類屬性單位為秒。
屬性 | 說明 |
| 引擎內部請求 ID |
| 模型名 |
| 採樣溫度 |
| Top-P 參數 |
| 最大產生 token 數 |
| 候選數量 |
| 序列數量 |
| 輸入 token 數 |
| 輸出 token 數 |
| 請求端到端耗時 |
| 排隊耗時 |
| 首 token 耗時 |
| 調度耗時,引擎提供該資料時才上報 |
| 模型前向計算耗時,引擎提供該資料時才上報 |
| 模型執行耗時(含前向、跨 worker 同步、CPU-GPU 同步與採樣),引擎提供該資料時才上報 |
llm_request Span 屬性(vLLM V1)
V1 引擎的耗時類屬性單位為納秒。
屬性 | 說明 |
| 引擎內部請求 ID |
| 模型名 |
| 採樣溫度 |
| Top-P 參數 |
| 最大產生 token 數 |
| 候選數量 |
| 輸入 token 數 |
| 輸出 token 數 |
| 命中緩衝而無需重新 Prefill 的輸入 token 數,含本地 Prefix Cache 命中與遠端 KV 複用;命中為 0 時也會上報,便於計算快取命中率 |
| 請求端到端耗時 |
| 排隊耗時 |
| 首 token 耗時 |
| Prefill 階段耗時 |
| Decode 階段耗時 |
| 推理階段總耗時(Prefill + Decode) |
| Prompt 分詞耗時,發生在前端進程 |
| 增量反分詞累計耗時 |
| 遠端 KV Cache 傳輸總耗時,僅發生過傳輸時上報 |
| 請求被搶佔的次數,僅發生過搶佔時上報 |
| EngineCore 執行個體序號,多引擎部署下用於區分 |
| PD 分離角色, |
PD 分離下的耗時口徑:Prefill 節點只有 Prefill 耗時是準確的,time_in_model_decode 恒為 0;Decode 節點只有 Decode 耗時是準確的,time_in_model_prefill 恒為 0。vLLM 在搶佔時不會重設調度時間戳記,因此 Prefill / Decode / Inference 耗時已經包含了搶佔帶來的停頓,gen_ai.request.preemption_count 是解釋這類耗時突增的依據。
階段子 Span 屬性
wait、kv_transfer、prefill、decode 四個子 Span 都攜帶 gen_ai.request.id、gen_ai.request.model_name、gen_ai.engine.index、gen_ai.pd_role。kv_transfer 額外攜帶以下屬性:
屬性 | 說明 |
| 傳輸方向, |
| 本次傳輸覆蓋的 token 數,即連接器遠端解析出的 token 量;與表示快取命中量的 |
| 連接器是否上報了本請求的載入失敗 |
Span Event(僅採集精度 2)
採集精度為 2 時,llm_request 上會按引擎的調度迭代追加 Span Event,用於還原逐次迭代的執行過程。
Event 名稱 | 說明 |
| 請求進入等待 |
| 一次 Prefill 迭代 |
| 一次 Decode 迭代 |
| 請求被搶佔以釋放 KV Cache 塊 |
Event 屬性包含 gen_ai.engine.index,以及 token 級資訊 gen_ai.token.ids、gen_ai.token.texts、gen_ai.token.count、gen_ai.token.logprobs。
Event 數量與請求的迭代次數成正比,容易超過 OpenTelemetry 預設的單 Span Event 上限(128)而被丟棄,必要時調大 OTEL_SPAN_EVENT_COUNT_LIMIT。
vLLM 的指標
指標維度
vLLM 的指標分為引擎側指標與介面層 token 指標兩組,攜帶的維度不同。引擎側指標攜帶的公用維度:
維度 | 說明 |
| 固定為 |
| 固定為 |
| EngineCore 執行個體序號,僅 V1 |
| 模型名,僅 V1 |
gen_ai_vllm_request_success 額外攜帶 finished_reason 維度。介面層的 token 指標(genai_llm_usage_tokens)攜帶以下維度:
維度 | 說明 |
| 固定為 |
| 固定為 |
| 固定為 |
| 模型名 |
|
|
|
|
通用指標(V0 與 V1 均上報)
除 genai_llm_usage_tokens 屬於介面層 token 指標外,本表其餘指標攜帶引擎側公用維度。
指標名 | 類型 | 單位 | 說明 |
| Counter | 個 | 輸入 / 輸出 token 消耗量,按 |
| Counter | 次 | 引擎調度迭代次數 |
| Counter | 次 | 成功完成的請求數 |
| Counter | 秒 | 首 token 耗時累計 |
| Counter | 秒 | 單個輸出 token 耗時累計 |
| Counter | 秒 | 請求端到端耗時累計 |
V0 指標
系統狀態類指標為 Gauge,反映採集時刻的瞬時值。本表指標攜帶引擎側公用維度,其中 engine_index 與 model_name 僅 V1 上報,V0 指標不含這兩個維度。
指標名 | 類型 | 單位 | 說明 |
| Gauge | 比例 | GPU KV Cache 使用率 |
| Gauge | 比例 | CPU KV Cache 使用率 |
| Gauge | 個 | 運行中的序列數 |
| Gauge | 個 | 等待中的序列數 |
| Gauge | 個 | 被換出的序列數 |
| Counter | 個 | 迭代內處理的輸入 token 數 |
| Counter | 個 | 迭代內產生的輸出 token 數 |
| Counter | 個 | 迭代內處理的 token 總數 |
| Counter | 次 | 迭代內發生的搶佔次數 |
Gauge 類指標僅由真正接收到引擎調度統計的進程上報。未參與推理的進程(如純前端進程)不會上報 0 值,避免多進程部署下出現無意義的 0 曲線。
V1 指標
本表指標攜帶引擎側公用維度,包括僅 V1 上報的 engine_index 與 model_name。
指標名 | 類型 | 單位 | 說明 |
| Gauge | 個 | 正在執行批次內的請求數 |
| Gauge | 個 | 等待處理的請求數 |
| Gauge | 比例 | KV Cache 使用率,取值範圍 [0,1] |
| Counter | 個 | Prefix Cache 查詢的 token 數 |
| Counter | 個 | Prefix Cache 命中的 token 數 |
| Counter | 次 | 引擎累計搶佔次數 |
| Counter | 個 | Prefill 處理的 token 數 |
| Counter | 個 | 產生的 token 數 |
| Counter | 個 | 請求 |
| Counter | 個 | 請求 |
| Counter | 秒 | 請求在 WAITING 階段的耗時累計 |
| Counter | 秒 | 請求 Prefill 階段耗時累計 |
| Counter | 秒 | 請求 Decode 階段耗時累計 |
| Counter | 秒 | 請求 RUNNING 階段耗時累計 |
Prefix Cache 命中率可由 gen_ai_vllm_prefix_cache_hits / gen_ai_vllm_prefix_cache_queries 得到。
SGLang 的 Span
Span 構成與層級
SGLang 情境下的鏈路由兩部分 Span 組成:探針在 OpenAI 相容介面層產生的入口 Span,以及 SGLang 引擎原生埋點產生的 Span。探針會把入口 Span 的上下文注入引擎的要求標頭,因此原生 Span 會掛在入口 Span 之下,形成一條完整鏈路:
chat {模型名} ← 探針入口 Span
└─ Req {請求 ID 前 8 位} ← 原生請求 Span,每請求一個
├─ Tokenizer (host:… | pid:…) ← 原生線程 Span,前端進程
│ ├─ tokenize
│ └─ api_server_dispatch
└─ Scheduler [TP 0] (host:… | pid:…) ← 原生線程 Span,調度器進程
├─ prefill_waiting
├─ prefill_forward
│ └─ chunked_prefill
└─ decode_forward
└─ decode_loop原生埋點採用“請求 → 線程 → 階段”三層結構:請求 Span 代表一次完整請求,線程 Span 代表參與處理該請求的每個進程/線程,階段 Span 代表該線程內的一段處理邏輯。因此在多卡(TP / PP / DP)部署下,同一請求會出現多個線程 Span,分別對應各調度器進程。同一線程內相鄰的階段 Span、以及跨進程銜接的階段 Span 之間會建立 Span Link,用於還原執行順序,這類關聯不是父子關係。
入口 Span 列表
探針的入口埋點為每個請求產生一個 Span,不再產生子 Span,請求內部的階段拆分由原生埋點提供。
Span 名稱 | 說明 |
| Chat Completions 請求, |
| Completions 請求, |
入口 Span 屬性
請求側屬性:
屬性 | 說明 |
| 固定為 |
|
|
| 請求指定的模型名 |
| 請求 ID,Chat 流式情境上報 |
| 是否為流式請求 |
| 採樣溫度 |
| Top-P 參數 |
| Top-K 參數 |
| 最大產生 token 數 |
| 候選數量 |
響應側屬性:
屬性 | 說明 |
| 響應 ID |
| 響應中返回的模型名,非流式情境上報 |
| 結束原因 |
| 輸入 token 數 |
| 輸出 token 數 |
| token 總數 |
| 命中緩衝的輸入 token 數 |
| 請求端到端耗時,單位秒 |
| 流式情境下的輸出 token 估算值,按流式增量數量乘以引擎的 |
| 輸入內容,受內容採集開關控制 |
| 輸出內容,受內容採集開關控制 |
工具調用相關屬性(Chat 流式情境):
屬性 | 說明 |
| 請求是否聲明了工具 |
| 響應中是否檢測到工具調用 |
| 檢測到的工具調用數量 |
| 第 i 個候選、第 j 個工具調用的名稱 |
| 對應的調用參數 |
入口 Span 不產生自訂 Span Event。當內容採集策略配置為 event 時,輸入輸出內容以 gen_ai.client.inference.operation.details 日誌事件的形式上報,而不寫入 Span 屬性。
原生埋點的開啟與採集層級
探針在引擎啟動時會自動開啟 SGLang 的原生 tracing 開關,無需手動添加 --enable-trace;原生 Span 複用探針註冊的全域 TracerProvider 上報,因此也不需要配置 --otlp-traces-endpoint,原生 Span 與入口 Span 歸屬同一個應用。
原生埋點為每個階段 Span 定義了採集層級,由環境變數 SGLANG_TRACE_LEVEL 控制:預設值 3 表示上報層級 1 至 3 的全部階段 Span,調小則只保留更關鍵的階段,設為 0 表示關閉原生埋點。引擎另外提供 /set_trace_level?level=N 介面用於運行期動態調整。原生埋點的 Span 數量隨部署規模放大,單個請求在多卡部署下會產生十個以上 Span,鏈路資料量偏大時優先調低 SGLANG_TRACE_LEVEL。
請求 Span 與線程 Span
請求 Span 是原生埋點的根 Span,在前端進程建立並結束,名稱格式為 {角色} Req {請求 ID 前 8 位},角色在 PD 分離下取 prefill / decode,非 PD 部署為空白。
屬性 | 說明 |
| 請求 ID |
| 固定為 |
| PD 分離下的請求關聯標識,十六進位字串,僅 PD 情境上報 |
| 請求 ID |
| 採樣溫度 |
| Top-P 參數 |
| Top-K 參數 |
| 候選數量 |
| 最大產生 token 數 |
| 服務端配置的模型名 |
| 結束原因,JSON 數組字串 |
| 輸入 token 數 |
| 輸出 token 數,非 Embedding 請求上報 |
| 命中緩衝的輸入 token 數 |
| 首 token 耗時 |
| 請求端到端耗時 |
| 請求分發完成到首 token 的耗時 |
| 首 token 到請求結束的耗時 |
| 請求分發完成到請求結束的耗時 |
耗時類屬性單位均為秒。這些耗時是前端進程視角的時間差,與調度器內部實際前向計算耗時不完全等價,後者請看階段 Span 的實際耗時。請求 Span 上的屬性只在請求正常結束時補齊。
線程 Span 的名稱格式為 {線程標籤} [TP n] [PP n] [DP n] (host:{主機標識} | pid:{線程 ID}),其中 rank 資訊僅在對應值存在時拼接。線程標籤取值 Tokenizer / MultiTokenizer-{編號} / DP Controller / Scheduler,PD 分離下帶 Prefill / Decode 首碼。Detokenizer 進程沒有原生埋點,不會出現對應的線程 Span。
屬性 | 說明 |
| 主機唯一標識,用於區分不同節點上的同名 PID |
| 線程 ID |
| 線程標籤 |
| 張量並行 rank,存在時上報 |
| 流水線並行 rank,存在時上報 |
| 資料並行 rank,存在時上報 |
請求異常終止時,錯誤狀態與結束原因被記錄線上程 Span 上(狀態置為 ERROR,並追加結束原因相關屬性),請求 Span 本身不會被標記為錯誤。排查失敗請求時應關注線程 Span 的狀態。
階段 Span 列表
下表的“層級”對應 SGLANG_TRACE_LEVEL,層級值大於配置值的 Span 不產生。通用階段:
Span 名稱 | 層級 | 產生進程 | 說明 |
| 1 | 前端 | Prompt 分詞耗時 |
| 2 | 前端 | 請求從前端分發到調度器的耗時 |
| 2 | DP Controller | 資料並行控制器分發請求的耗時,開啟 DP 時才有 |
| 2 | 調度器 | 請求進入調度器後到進入等待隊列的處理耗時,僅非 PD 分離部署 |
| 1 | 調度器 | 請求在等待隊列排隊,直到被調度執行 Prefill |
| 1 | 調度器 | Prefill 前向計算耗時 |
| 3 | 調度器 | 單個分塊的 Prefill 耗時,嵌套在 |
| 1 | 調度器 | Prefill 完成到首個 Decode 被調度之間的等待 |
| 1 | 調度器 | Decode 階段整體耗時 |
| 3 | 調度器 | 單輪 Decode 迭代耗時,嵌套在 |
decode_forward 沒有獨立的結束點,它在請求收尾時隨線程一起關閉,因此其耗時覆蓋從首次 Decode 調度到請求結束的整個區間。
推測解碼階段(開啟 Speculative Decoding 時產生,嵌套在前向 Span 之下):
Span 名稱 | 層級 | 說明 |
| 2 | 草稿模型產生候選 token 的耗時 |
| 2 | 目標模型校正草稿 token 的耗時 |
| 3 | 草稿模型的 extend 階段耗時 |
流水線並行階段:
Span 名稱 | 層級 | 說明 |
| 4 | 流水線並行下 CPU 側批次處理耗時。層級 4 高於預設值 3,需顯式設定 |
PD 分離部署下的額外階段,Prefill 節點:
Span 名稱 | 層級 | 說明 |
| 1 | Prefill 節點接收請求後的準備耗時 |
| 1 | 與 Decode 節點建立傳輸串連的耗時 |
| 1 | 向 Decode 節點傳輸 KV Cache 的耗時 |
PD 分離部署下的額外階段,Decode 節點:
Span 名稱 | 層級 | 說明 |
| 1 | Decode 節點接收請求後的準備耗時 |
| 1 | 與 Prefill 節點建立傳輸串連的耗時 |
| 1 | 等待 KV Cache 傳輸完成的耗時 |
| 3 | Decode 節點補齊 Prefill 階段輸出的耗時 |
PD 分離下 Prefill 與 Decode 各有獨立的請求 Span,是兩條獨立的鏈路,通過請求 Span 上的 bootstrap_room 屬性關聯同一次請求。decode_waiting 在 PD 分離的 Decode 節點上語義變為“KV Cache 傳輸完成到進入前向計算之間的排隊”,與非 PD 部署下的含義不同。
階段 Span 屬性與 Span Event
階段 Span 預設不攜帶自訂屬性,僅以下三個例外:
Span 名稱 | 屬性 | 說明 |
|
| 當前是第幾輪 Decode 迭代 |
|
| 本次校正通過的草稿 token 數; |
|
| 流水線並行的 micro-batch 編號 |
原生埋點產生兩類 Span Event:
Event 名稱 | 層級 | 屬性 | 說明 |
| 1 | 無 | 請求因資源不足被回退、重新排隊時記錄 |
| 3 |
| 請求被編入某個批次時記錄。 |
Event 按時間戳記歸屬到覆蓋該時刻的階段 Span 上;不落在任何階段區間內的 Event 會掛到線程 Span 上,因此同名 Event 在不同請求上的掛載位置可能不同。
SGLang 的指標
指標維度
引擎側指標(調度器與前端統計)攜帶的維度:
維度 | 說明 |
| 固定為 |
| 固定為 |
| 固定為 |
token 消耗指標(genai_llm_usage_tokens)額外攜帶 modelName、spanKind、usageType(input / output)。
指標列表
除 genai_llm_usage_tokens 屬於 token 消耗指標外,本表其餘指標攜帶引擎側維度。
指標名 | 類型 | 單位 | 說明 |
| Counter | 個 | 輸入 / 輸出 token 消耗量,按 |
| Counter | 個 | 運行中的請求數快照 |
| Counter | 個 | 隊列中的請求數快照 |
| Counter | 個 | 當前佔用的 token 數快照 |
| Counter | 比例 | KV Cache token 使用率快照 |
| Counter | token/s | 產生吞吐快照 |
| Counter | 比例 | 快取命中率快照,引擎提供該欄位時才上報 |
| Counter | 個 | 推測解碼的接受長度 |
| Counter | 次 | 統計上報次數,用於對快照類指標做平均值計算 |
| Counter | 個 | 累計輸入 token 數 |
| Counter | 個 | 累計輸出 token 數 |
| Counter | 個 | 累計命中緩衝的輸入 token 數 |
| Counter | 次 | 累計請求數 |
| Counter | 秒 | 首 token 耗時累計 |
| Counter | 秒 | 單個輸出 token 耗時累計 |
| Counter | 秒 | token 間延遲累計 |
| Counter | 秒 | 請求端到端耗時累計 |
SGLang 的系統狀態類指標在實現上以 Counter 上報,語義上是每次統計周期的瞬時快照,包括 sglang_num_running_reqs、sglang_num_queue_reqs、sglang_num_used_tokens、sglang_token_usage、sglang_gen_throughput 與 gen_ai_sglang_cache_hit_rate,在看板上應配合 sglang_log_count 做周期內平均,而不是直接看累計值。gen_ai_server_time_per_output_token 由端到端耗時除以輸出 token 數得到,是平均值口徑;需要觀察真實的 token 間隔時請使用 sglang_inter_token_latency_seconds。