@@ -27,6 +27,7 @@ import (
2727 "github.com/coze-dev/coze-loop/backend/pkg/lang/goroutine"
2828 "github.com/coze-dev/coze-loop/backend/pkg/lang/ptr"
2929 "github.com/coze-dev/coze-loop/backend/pkg/logs"
30+ timeutil "github.com/coze-dev/coze-loop/backend/pkg/time"
3031 "github.com/samber/lo"
3132 "golang.org/x/sync/errgroup"
3233)
@@ -235,6 +236,11 @@ func (m *MetricsService) QueryMetrics(ctx context.Context, req *QueryMetricsReq)
235236 if len (req .MetricsNames ) == 0 {
236237 return & QueryMetricsResp {}, nil
237238 }
239+ if req .FilterFields != nil {
240+ if err := req .FilterFields .Traverse (processSpecificFilter ); err != nil {
241+ return nil , errorx .WrapByCode (err , obErrorx .CommercialCommonInvalidParamCodeCode )
242+ }
243+ }
238244 for _ , metricName := range req .MetricsNames {
239245 mVal , ok := m .metricDefMap [metricName ]
240246 if ! ok {
@@ -854,3 +860,72 @@ func getDaysBeforeTimeStamp(days int) int64 {
854860 daysBefore := time .Date (now .Year (), now .Month (), now .Day ()- days , 0 , 0 , 0 , 0 , now .Location ())
855861 return daysBefore .UnixMilli ()
856862}
863+
864+ // TODO: 合并,有三个地方实现一样...
865+ func processSpecificFilter (f * loop_span.FilterField ) error {
866+ switch f .FieldName {
867+ case loop_span .SpanFieldStatus :
868+ if err := processStatusFilter (f ); err != nil {
869+ return err
870+ }
871+ case loop_span .SpanFieldDuration ,
872+ loop_span .SpanFieldLatencyFirstResp ,
873+ loop_span .SpanFieldStartTimeFirstResp ,
874+ loop_span .SpanFieldStartTimeFirstTokenResp ,
875+ loop_span .SpanFieldLatencyFirstTokenResp ,
876+ loop_span .SpanFieldReasoningDuration :
877+ if err := processLatencyFilter (f ); err != nil {
878+ return err
879+ }
880+ }
881+ return nil
882+ }
883+
884+ func processStatusFilter (f * loop_span.FilterField ) error {
885+ if f .QueryType == nil || * f .QueryType != loop_span .QueryTypeEnumIn {
886+ return fmt .Errorf ("status filter should use in operator" )
887+ }
888+ f .FieldName = loop_span .SpanFieldStatusCode
889+ f .FieldType = loop_span .FieldTypeLong
890+ checkSuccess , checkError := false , false
891+ for _ , val := range f .Values {
892+ switch val {
893+ case loop_span .SpanStatusSuccess :
894+ checkSuccess = true
895+ case loop_span .SpanStatusError :
896+ checkError = true
897+ default :
898+ return fmt .Errorf ("invalid status code field value" )
899+ }
900+ }
901+ if checkSuccess && checkError {
902+ f .QueryType = ptr .Of (loop_span .QueryTypeEnumAlwaysTrue )
903+ f .Values = nil
904+ } else if checkSuccess {
905+ f .Values = []string {"0" }
906+ } else if checkError {
907+ f .QueryType = ptr .Of (loop_span .QueryTypeEnumNotIn )
908+ f .Values = []string {"0" }
909+ } else {
910+ return fmt .Errorf ("invalid status code query" )
911+ }
912+ return nil
913+ }
914+
915+ // ms -> us
916+ func processLatencyFilter (f * loop_span.FilterField ) error {
917+ if f .FieldType != loop_span .FieldTypeLong {
918+ return fmt .Errorf ("latency field type should be long " )
919+ }
920+ micros := make ([]string , 0 )
921+ for _ , val := range f .Values {
922+ integer , err := strconv .ParseInt (val , 10 , 64 )
923+ if err != nil {
924+ return fmt .Errorf ("fail to parse long value %s, %v" , val , err )
925+ }
926+ integer = timeutil .MillSec2MicroSec (integer )
927+ micros = append (micros , strconv .FormatInt (integer , 10 ))
928+ }
929+ f .Values = micros
930+ return nil
931+ }
0 commit comments