WrapModelCall 包装模型调用,添加 GenAI 追踪
(ctx context.Context, req *ModelRequest, handler ModelCallHandler)
| 98 | |
| 99 | // WrapModelCall 包装模型调用,添加 GenAI 追踪 |
| 100 | func (m *TelemetryMiddleware) WrapModelCall(ctx context.Context, req *ModelRequest, handler ModelCallHandler) (*ModelResponse, error) { |
| 101 | startTime := time.Now() |
| 102 | |
| 103 | // 构建 span 名称: "chat {model}" |
| 104 | spanName := genai.ChatSpanName(m.model) |
| 105 | |
| 106 | // 构建初始属性 |
| 107 | attrs := []telemetry.Attribute{ |
| 108 | telemetry.String(genai.AttrOperationName, genai.OpChat), |
| 109 | telemetry.String(genai.AttrProviderName, m.provider), |
| 110 | telemetry.String(genai.AttrAgentID, m.agentID), |
| 111 | telemetry.String(genai.AttrAgentName, m.agentName), |
| 112 | telemetry.String(genai.AttrRequestModel, m.model), |
| 113 | } |
| 114 | |
| 115 | // 添加会话 ID (如果有) |
| 116 | if m.conversationID != "" { |
| 117 | attrs = append(attrs, telemetry.String(genai.AttrConversationID, m.conversationID)) |
| 118 | } |
| 119 | |
| 120 | // 从 Metadata 中提取额外信息 |
| 121 | if req.Metadata != nil { |
| 122 | if maxTokens, ok := req.Metadata["max_tokens"].(int); ok { |
| 123 | attrs = append(attrs, telemetry.Int(genai.AttrRequestMaxTokens, maxTokens)) |
| 124 | } |
| 125 | if temperature, ok := req.Metadata["temperature"].(float64); ok { |
| 126 | attrs = append(attrs, telemetry.Float64(genai.AttrRequestTemperature, temperature)) |
| 127 | } |
| 128 | if topP, ok := req.Metadata["top_p"].(float64); ok { |
| 129 | attrs = append(attrs, telemetry.Float64(genai.AttrRequestTopP, topP)) |
| 130 | } |
| 131 | // 覆盖模型名称(如果 metadata 中指定了) |
| 132 | if model, ok := req.Metadata["model"].(string); ok && model != "" { |
| 133 | attrs = append(attrs, telemetry.String(genai.AttrRequestModel, model)) |
| 134 | } |
| 135 | // 覆盖 provider(如果 metadata 中指定了) |
| 136 | if provider, ok := req.Metadata["provider"].(string); ok && provider != "" { |
| 137 | attrs = append(attrs, telemetry.String(genai.AttrProviderName, provider)) |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | // 开始 span (CLIENT 类型,因为是调用外部 LLM) |
| 142 | ctx, span := m.tracer.StartSpan(ctx, spanName, |
| 143 | telemetry.WithSpanKind(telemetry.SpanKindClient), |
| 144 | telemetry.WithAttributes(attrs...), |
| 145 | ) |
| 146 | defer span.End() |
| 147 | |
| 148 | // 记录提示词事件 (如果启用) |
| 149 | if m.recordPrompts && len(req.Messages) > 0 { |
| 150 | m.recordPromptEvent(span, req) |
| 151 | } |
| 152 | |
| 153 | // 调用下一层 |
| 154 | resp, err := handler(ctx, req) |
| 155 | |
| 156 | // 计算延迟 |
| 157 | latencyMs := time.Since(startTime).Milliseconds() |