如何基于 OpenTelemetry 采集 token 级延迟并上报 Prometheus?

解读

在国内大模型落地场景中,token 级延迟是衡量用户体验与成本的核心指标:它直接决定首包时间、流式输出节奏与 GPU 利用率。面试官问“如何基于 OpenTelemetry 采集并上报 Prometheus”,表面看是监控技术题,实则考察三点:

  1. 是否理解生成式 AI 推理链路(预填充、解码、流式返回)与 token 的对应关系;
  2. 能否在不侵入模型代码的前提下,用OTel 语义规范把“token 延迟”表达为可聚合的指标;
  3. 是否熟悉国内可观测性基础设施(阿里云 ARMS、腾讯云 TPS、自建 Thanos+Grafana)的集成方式。

答得太浅(只讲 counter 和 histogram)会被认为没做过大模型;答得太深(魔改 CUDA kernel)会被认为过度设计。必须给出工程可落地、云原生友好、符合国内合规要求的完整路径。

知识点

  1. Token 级延迟定义

    • TTFT(Time To First Token):用户侧首包时间,对应预填充阶段结束。
    • TPOT(Time Per Output Token):首 token 之后每 decode 一步的间隔。
    • E2E Latency = TTFT + (TPOT × token 数) + 网络抖动。
  2. OpenTelemetry 指标模型

    • Instrument:Histogram 最贴合,可自动产生 _bucket、_sum、_count,供 Prometheus quantile 计算。
    • 属性维度:model_name、gpu_type、quantization、request_id、user_id(脱敏后)、scene(chat/embedding/rerank)。
    • 单位:秒(s)或毫秒(ms),必须显式声明,避免 Prometheus 默认秒级假设导致数量级错误。
  3. 采集点选择

    • 服务端拦截:在 Triton Inference Server / vLLM / FastAPI 的流式 generate 接口里,用 Python decorator 或 C++ callback 在每次 yield token 时打时间戳。
    • 零侵入方案:若模型服务不可改,可在边车(Sidecar) 里解析 HTTP Chunk 的 SSE 事件,用正则提取 "data: {"token":"xxx"}" 并计算间隔;该方案对国产芯片(华为昇腾、寒武纪)同样适用,无需 GPU 代码。
  4. 合规与脱敏

    • 根据《个人信息保护法》,user_id 必须做哈希或 tokenization 后才能写入 label;高基数场景改用 span attribute,指标维度仅保留低基数字段。
    • 若客户为金融或国企,需支持国密 SM4 脱敏专网隔离,OTel Collector 需开启 TLS 双向认证(国密套件)。
  5. 上报链路

    • OTel Collector → Prometheus Remote Write:国内云厂商已支持,阿里云可直写 ARMS Prometheus,腾讯云通过 TPS 实例接入;自建场景用 Thanos Receiver。
    • 采样策略:高并发下开启头部采样(1%~5%),防止 Prometheus 内存爆炸;关键 VIP 客户可基于属性采样(user_tier=vip 全采)。
  6. Grafana 大盘

    • histogram_quantile(0.95, rate(ttft_seconds_bucket[5m])) 展示 P95 TTFT;
    • increase(output_token_total[1m]) / increase(output_token_duration_seconds_sum[1m]) 计算实时吞吐(token/s);
    • 告警规则:TTFT>2s 持续 5 分钟且 QPS>50 时触发钉钉、飞书、企业微信,并自动扩容 GPU 节点(HPA 基于自定义指标)。

答案

  1. 定义指标 在 Python 服务启动时注册 OTel Histogram:

    from opentelemetry import metrics
    meter = metrics.get_meter("llm", version="1.0.0")
    ttft_histogram = meter.create_histogram(
        name="llm_ttft_seconds",
        description="Time to first token",
        unit="s"
    )
    tpot_histogram = meter.create_histogram(
        name="llm_tpot_seconds",
        description="Time per output token",
        unit="s"
    )
    token_counter = meter.create_counter(
        name="llm_output_token_total",
        description="Number of output tokens",
        unit="1"
    )
    
  2. 注入采集逻辑 在 FastAPI 流式接口里,用生成器包装 yield:

    async def generate(request):
        first = True
        async for token in model.stream(request.prompt):
            now = time.time()
            if first:
                ttft_histogram.record(now - request.start_time,
                                      attributes={"model": request.model})
                first = False
            else:
                tpot_histogram.record(now - last_time,
                                      attributes={"model": request.model})
            last_time = now
            token_counter.add(1, attributes={"model": request.model})
            yield token
    
  3. 启动 OTel Collector 国内镜像加速:

    exporters:
      prometheusremotewrite:
        endpoint: "https://arms-grafana.aliyuncs.com/prometheus/v1/write"
        headers:
          Authorization: "Bearer your-arms-token"
    

    开启 batch processormemory_limiter,单实例 8 卡 A100 场景下,batch=1024 可降 30% 网络带宽。

  4. Prometheus 验证 查询 {__name__=~"llm_.*"} 确认指标到达;若发现 cardinality explosion,立即检查是否把 request_id 写进 label,及时改为 attribute。

  5. 压测对齐wrk2 + lua 脚本 模拟 100 并发流式请求,对比 TTFT、TPOT 曲线与 NVIDIA nvidia-smi dmon 的 GPU 利用率,确保监控值与真实用户体验误差 <5%。

拓展思考

  1. 多 LoRA 动态加载 场景下,同一张卡可能服务多个微调模型,此时需在属性里加上 lora_idbase_model,否则 histogram 聚合会掩盖慢模型。
  2. 国产芯片(昇腾 910B)使用 CANN 栈时,stream 回调接口与 CUDA 不同,需在 C++ 侧用 aclrtLaunchCallback 插入时间戳,再通过 opentelemetry-cpp 的 OTLP gRPC exporter 发送到 Collector,避免 Python GIL 带来的误差。
  3. 成本治理:把 token 延迟与 GPU 功耗(DCGM 指标)联合建模,可算出每 token 能耗(J/token),在华东/华北电力差价大的机房做绿色调度,实现“双碳”合规。
  4. 审计回溯:对金融客户,需把同一 request 的 trace_id 写入日志与指标,事后可重放整条链路;此时推荐把 trace_id 作为 exemplar 挂在 histogram 上,Grafana 10 以上支持一键下钻到 Jaeger 链路。
  5. 下一步演进:当业务规模到 10 亿级 token/天 时,Prometheus 本地存储成为瓶颈,可切换到 Apache Doris/StarRocks 作为 OLAP 指标仓库,通过 OTel Collector 的 dorisexporter 直写,实现 1 分钟级大规模聚合,支撑实时计费与 SLA 对账。

掌握以上思路,面试时既能给出可落地的代码级方案,又能结合国内合规、国产芯片、成本优化侃侃而谈,将“监控 token 延迟”这一单点问题升维到LLMOps 体系化建设,可稳稳拿到高分。