@@ -68,7 +68,6 @@ const (
68
68
LLMDurationCount = "llm_duration_count"
69
69
LLMStreamDurationCount = "llm_stream_duration_count"
70
70
ResponseType = "response_type"
71
- ChatID = "chat_id"
72
71
ChatRound = "chat_round"
73
72
74
73
// Inner span attributes
@@ -285,6 +284,9 @@ func onHttpRequestHeaders(ctx wrapper.HttpContext, config AIStatisticsConfig) ty
285
284
if consumer , _ := proxywasm .GetHttpRequestHeader (ConsumerKey ); consumer != "" {
286
285
ctx .SetContext (ConsumerKey , consumer )
287
286
}
287
+ if requestModel , _ := proxywasm .GetHttpRequestHeader ("x-higress-llm-model" ); requestModel != "" {
288
+ ctx .SetContext (tokenusage .CtxKeyRequestModel , requestModel )
289
+ }
288
290
289
291
ctx .SetRequestBodyBufferLimit (defaultMaxBodyBytes )
290
292
@@ -312,14 +314,15 @@ func onHttpRequestBody(ctx wrapper.HttpContext, config AIStatisticsConfig, body
312
314
requestModel = model .String ()
313
315
} else {
314
316
requestPath := ctx .GetStringContext (RequestPath , "" )
315
- if strings .Contains (requestPath , "generateContent" ) || strings .Contains (requestPath , "streamGenerateContent" ) { // Google Gemini GenerateContent
316
- reg := regexp .MustCompile (`^.*/(?P<api_version>[^/]+)/models/(?P<model>[^:]+):\w+Content$` )
317
+ if strings .Contains (requestPath , "generateContent" ) || strings .Contains (requestPath , "streamGenerateContent" ) || strings . Contains ( requestPath , "countTokens" ) || strings . Contains ( requestPath , "predictLongRunning" ) { // Google Gemini
318
+ reg := regexp .MustCompile (`^.*/(?P<api_version>[^/]+)/models/(?P<model>[^:]+):( \w+Content|countTokens|predictLongRunning) $` )
317
319
matches := reg .FindStringSubmatch (requestPath )
318
320
if len (matches ) == 3 {
319
321
requestModel = matches [2 ]
320
322
}
321
323
}
322
324
}
325
+ ctx .SetContext (tokenusage .CtxKeyRequestModel , requestModel )
323
326
setSpanAttribute (ArmsRequestModel , requestModel )
324
327
// Set the number of conversation rounds
325
328
@@ -383,14 +386,8 @@ func onHttpStreamingBody(ctx wrapper.HttpContext, config AIStatisticsConfig, dat
383
386
}
384
387
385
388
ctx .SetUserAttribute (ResponseType , "stream" )
386
- if chatID := wrapper .GetValueFromBody (data , []string {
387
- "id" ,
388
- "response.id" ,
389
- "responseId" , // Gemini generateContent
390
- "message.id" , // anthropic messages
391
- }); chatID != nil {
392
- ctx .SetUserAttribute (ChatID , chatID .String ())
393
- }
389
+
390
+ tokenusage .ExtractChatId (ctx , data )
394
391
395
392
// Get requestStartTime from http context
396
393
requestStartTime , ok := ctx .GetContext (StatisticsRequestStartTime ).(int64 )
@@ -452,14 +449,8 @@ func onHttpResponseBody(ctx wrapper.HttpContext, config AIStatisticsConfig, body
452
449
ctx .SetUserAttribute (LLMServiceDuration , responseEndTime - requestStartTime )
453
450
454
451
ctx .SetUserAttribute (ResponseType , "normal" )
455
- if chatID := wrapper .GetValueFromBody (body , []string {
456
- "id" ,
457
- "response.id" ,
458
- "responseId" , // Gemini generateContent
459
- "message.id" , // anthropic messages
460
- }); chatID != nil {
461
- ctx .SetUserAttribute (ChatID , chatID .String ())
462
- }
452
+
453
+ tokenusage .ExtractChatId (ctx , body )
463
454
464
455
// Set information about this request
465
456
if ! config .disableOpenaiUsage {
@@ -489,7 +480,7 @@ func onHttpResponseBody(ctx wrapper.HttpContext, config AIStatisticsConfig, body
489
480
func setAttributeBySource (ctx wrapper.HttpContext , config AIStatisticsConfig , source string , body []byte ) {
490
481
for _ , attribute := range config .attributes {
491
482
var key string
492
- var value interface {}
483
+ var value any
493
484
if source == attribute .ValueSource {
494
485
key = attribute .Key
495
486
switch source {
@@ -538,9 +529,9 @@ func setAttributeBySource(ctx wrapper.HttpContext, config AIStatisticsConfig, so
538
529
}
539
530
}
540
531
541
- func extractStreamingBodyByJsonPath (data []byte , jsonPath string , rule string ) interface {} {
532
+ func extractStreamingBodyByJsonPath (data []byte , jsonPath string , rule string ) any {
542
533
chunks := bytes .Split (bytes .TrimSpace (wrapper .UnifySSEChunk (data )), []byte ("\n \n " ))
543
- var value interface {}
534
+ var value any
544
535
if rule == RuleFirst {
545
536
for _ , chunk := range chunks {
546
537
jsonObj := gjson .GetBytes (chunk , jsonPath )
@@ -573,10 +564,10 @@ func extractStreamingBodyByJsonPath(data []byte, jsonPath string, rule string) i
573
564
}
574
565
575
566
// Set the tracing span with value.
576
- func setSpanAttribute (key string , value interface {} ) {
567
+ func setSpanAttribute (key string , value any ) {
577
568
if value != "" {
578
569
traceSpanTag := wrapper .TraceSpanTagPrefix + key
579
- if e := proxywasm .SetProperty ([]string {traceSpanTag }, [] byte ( fmt .Sprint ( value ) )); e != nil {
570
+ if e := proxywasm .SetProperty ([]string {traceSpanTag }, fmt .Append ( nil , value )); e != nil {
580
571
log .Warnf ("failed to set %s in filter state: %v" , traceSpanTag , e )
581
572
}
582
573
} else {
@@ -652,7 +643,7 @@ func writeMetric(ctx wrapper.HttpContext, config AIStatisticsConfig) {
652
643
}
653
644
}
654
645
655
- func convertToUInt (val interface {} ) (uint64 , bool ) {
646
+ func convertToUInt (val any ) (uint64 , bool ) {
656
647
switch v := val .(type ) {
657
648
case float32 :
658
649
return uint64 (v ), true
0 commit comments