资讯详情

资讯详情

LLM API 调用链全链路追踪:OpenTelemetry 上下文注入与 Span 传递实战

LLM API 调用链全链路追踪OpenTelemetry 上下文注入与 Span 传递实战在大模型LLM应用架构中一个看似简单的用户请求在后端往往会经历一段极其错综复杂的“计算旅程”用户提问 - API 网关鉴权 - 向量数据库Milvus检索相关文档 - 提示词工程模板组装 - 外部安全审核模型校验 - 大模型核心生成 - 输出流式敏感词过滤。当用户抱怨某次请求卡顿了 6 秒时如果缺乏全链路追踪Distributed Tracing各组件的日志散落在不同的系统Loki / Elasticsearch中无法通过一个统一的 ID 串联开发团队各执一词无法定位到底是向量检索慢了还是模型生成耗时过长。基于CNCF OpenTelemetryOTel标准我们在全链路中实现W3Ctraceparent请求头的透明传递与 Step 级 Span 注入。本文将提供一份在 Go 微服务与 Python 大模型服务之间实现跨语言链路追踪的生产级实战代码。sequenceDiagram autonumber participant Client as 客户端 participant GoGateway as Go API 网关 (生成 TraceID) participant PythonLLM as Python vLLM 推理服务 participant Collector as OpenTelemetry Collector Client-GoGateway: 1. POST /v1/chat/completions Note over GoGateway: 2. 启动 Root Span: Gateway_Ingressbr/生成 TraceID: 4bf92f3577b34da6a3ce929d0e0e4736 GoGateway-PythonLLM: 3. 发送 HTTP 请求 (附带 Header traceparent: 00-4bf92f...-01) Note over PythonLLM: 4. 提取 traceparent启动 Child Span: vLLM_Prefill_Decodebr/继承完全相同的 TraceID! PythonLLM--GoGateway: 5. 返回流式输出并注入 token 计数属性 GoGateway--Client: 6. 返回最终响应 par 异步上报 Trace 数据 GoGateway--)Collector: 上报 Gateway Span (耗时 3.2s) PythonLLM--)Collector: 上报 LLM Span (Prefill: 200ms, Decode: 2.8s) end1. Go 网关层生成 Trace 并注入 HTTP 请求头package main import ( context net/http go.opentelemetry.io/otel go.opentelemetry.io/otel/propagation go.opentelemetry.io/otel/trace ) var tracer otel.Tracer(ai-gateway) func CallDownstreamLLMService(ctx context.Context, prompt string) (*http.Response, error) { // 1. 开启本地 Span ctx, span : tracer.Start(ctx, HTTP_Post_To_vLLM, trace.WithSpanKind(trace.SpanKindClient)) defer span.End() req, _ : http.NewRequestWithContext(ctx, POST, http://vllm-serving:8000/v1/completions, nil) // 2. 核心操作: 将当前 Context 中的 Trace 上下文自动序列化注入到 HTTP Header otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(req.Header)) // 发送带有 traceparent 的请求 return http.DefaultClient.Do(req) }2. Python 推理服务提取 TraceContext 并延续 Spanfrom fastapi import FastAPI, Request from opentelemetry import trace from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator app FastAPI() tracer trace.get_tracer(vllm-service) app.post(/v1/completions) async def generate_completions(request: Request): # 1. 从 HTTP Headers 中提取父级 TraceContext carrier dict(request.headers) parent_context TraceContextTextMapPropagator().extract(carriercarrier) # 2. 在父级 Context 下开启子 Span无缝延续调用链! with tracer.start_as_current_span(LLM_Prefill_And_Decode, contextparent_context) as span: span.set_attribute(gen_ai.system, vllm) span.set_attribute(gen_ai.request.model, llama-3-70b) # 执行模型推理生成 # ... span.set_attribute(gen_ai.usage.output_tokens, 128) return {text: 生成结果}3. 总结通过遵循 OpenTelemetry 标准化协议跨语言、跨组件的分布式调用链在 Jaeger 看板上被完整拼装为一幅一览无余的拓扑图使每一次慢调用与报错都能被毫秒级定位到具体的代码行与组件。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →