feat(ai-statistics): add system field support for Claude /v1/messages API (#3511)

This commit is contained in:
澄潭
2026-02-15 14:16:19 +08:00
committed by GitHub
parent 8e7292c42e
commit 28df33c596

View File

@@ -105,6 +105,7 @@ const (
BuiltinAnswerKey = "answer"
BuiltinToolCallsKey = "tool_calls"
BuiltinReasoningKey = "reasoning"
BuiltinSystemKey = "system"
BuiltinReasoningTokens = "reasoning_tokens"
BuiltinCachedTokens = "cached_tokens"
BuiltinInputTokenDetails = "input_token_details"
@@ -115,6 +116,9 @@ const (
QuestionPathOpenAI = "messages.@reverse.0.content"
QuestionPathClaude = "messages.@reverse.0.content" // Claude uses same format
// System prompt paths (from request body)
SystemPathClaude = "system" // Claude /v1/messages has system as a top-level field
// Answer paths (from response body - non-streaming)
AnswerPathOpenAINonStreaming = "choices.0.message.content"
AnswerPathClaudeNonStreaming = "content.0.text"
@@ -150,6 +154,10 @@ func getDefaultAttributes() []Attribute {
Key: BuiltinQuestionKey,
ApplyToLog: true,
},
{
Key: BuiltinSystemKey,
ApplyToLog: true,
},
{
Key: BuiltinAnswerKey,
ApplyToLog: true,
@@ -871,7 +879,7 @@ func setAttributeBySource(ctx wrapper.HttpContext, config AIStatisticsConfig, so
// isBuiltinAttribute checks if the given key is a built-in attribute
func isBuiltinAttribute(key string) bool {
return key == BuiltinQuestionKey || key == BuiltinAnswerKey || key == BuiltinToolCallsKey || key == BuiltinReasoningKey ||
return key == BuiltinQuestionKey || key == BuiltinAnswerKey || key == BuiltinToolCallsKey || key == BuiltinReasoningKey || key == BuiltinSystemKey ||
key == BuiltinReasoningTokens || key == BuiltinCachedTokens ||
key == BuiltinInputTokenDetails || key == BuiltinOutputTokenDetails
}
@@ -880,7 +888,7 @@ func isBuiltinAttribute(key string) bool {
// Returns nil if the key is not a built-in attribute
func getBuiltinAttributeDefaultSources(key string) []string {
switch key {
case BuiltinQuestionKey:
case BuiltinQuestionKey, BuiltinSystemKey:
return []string{RequestBody}
case BuiltinAnswerKey, BuiltinToolCallsKey, BuiltinReasoningKey:
return []string{ResponseStreamingBody, ResponseBody}
@@ -918,6 +926,13 @@ func getBuiltinAttributeFallback(ctx wrapper.HttpContext, config AIStatisticsCon
return value
}
}
case BuiltinSystemKey:
if source == RequestBody {
// Try Claude /v1/messages format (system is a top-level field)
if value := gjson.GetBytes(body, SystemPathClaude).Value(); value != nil && value != "" {
return value
}
}
case BuiltinAnswerKey:
if source == ResponseStreamingBody {
// Try OpenAI format first
@@ -1069,6 +1084,9 @@ func debugLogAiLog(ctx wrapper.HttpContext) {
if question := ctx.GetUserAttribute("question"); question != nil {
userAttrs["question"] = question
}
if system := ctx.GetUserAttribute("system"); system != nil {
userAttrs["system"] = system
}
if answer := ctx.GetUserAttribute("answer"); answer != nil {
userAttrs["answer"] = answer
}