diff --git a/pkg/query-service/app/clickhouseReader/reader.go b/pkg/query-service/app/clickhouseReader/reader.go index 8a6e2e6d36..596354433e 100644 --- a/pkg/query-service/app/clickhouseReader/reader.go +++ b/pkg/query-service/app/clickhouseReader/reader.go @@ -50,6 +50,7 @@ import ( "go.signoz.io/query-service/constants" am "go.signoz.io/query-service/integrations/alertManager" "go.signoz.io/query-service/model" + "go.signoz.io/query-service/utils" "go.uber.org/zap" ) @@ -2829,6 +2830,10 @@ func (r *ClickHouseReader) GetMetricAutocompleteMetricNames(ctx context.Context, // GetMetricResult runs the query and returns list of time series func (r *ClickHouseReader) GetMetricResult(ctx context.Context, query string) ([]*model.Series, error) { + defer utils.Elapsed("GetMetricResult")() + + zap.S().Infof("Executing metric result query: %s", query) + rows, err := r.db.Query(ctx, query) if err != nil { diff --git a/pkg/query-service/app/http_handler.go b/pkg/query-service/app/http_handler.go index 51ff99a8a9..4e923af79c 100644 --- a/pkg/query-service/app/http_handler.go +++ b/pkg/query-service/app/http_handler.go @@ -180,10 +180,10 @@ func writeHttpResponse(w http.ResponseWriter, data interface{}) { } func (aH *APIHandler) RegisterMetricsRoutes(router *mux.Router) { subRouter := router.PathPrefix("/api/v2/metrics").Subrouter() - subRouter.HandleFunc("/query_range", aH.queryRangeMetricsV2).Methods(http.MethodPost) - subRouter.HandleFunc("/autocomplete/list", aH.metricAutocompleteMetricName).Methods(http.MethodGet) - subRouter.HandleFunc("/autocomplete/tagKey", aH.metricAutocompleteTagKey).Methods(http.MethodGet) - subRouter.HandleFunc("/autocomplete/tagValue", aH.metricAutocompleteTagValue).Methods(http.MethodGet) + subRouter.HandleFunc("/query_range", ViewAccess(aH.queryRangeMetricsV2)).Methods(http.MethodPost) + subRouter.HandleFunc("/autocomplete/list", ViewAccess(aH.metricAutocompleteMetricName)).Methods(http.MethodGet) + subRouter.HandleFunc("/autocomplete/tagKey", ViewAccess(aH.metricAutocompleteTagKey)).Methods(http.MethodGet) + subRouter.HandleFunc("/autocomplete/tagValue", ViewAccess(aH.metricAutocompleteTagValue)).Methods(http.MethodGet) } func (aH *APIHandler) respond(w http.ResponseWriter, data interface{}) { diff --git a/pkg/query-service/app/metrics/query_builder.go b/pkg/query-service/app/metrics/query_builder.go index bf1896af2e..26f57261b9 100644 --- a/pkg/query-service/app/metrics/query_builder.go +++ b/pkg/query-service/app/metrics/query_builder.go @@ -91,10 +91,9 @@ func BuildMetricsTimeSeriesFilterQuery(fs *model.FilterSet, groupTags []string, if fs != nil && len(fs.Items) != 0 { for _, item := range fs.Items { toFormat := item.Value + op := strings.ToLower(strings.TrimSpace(item.Operator)) // if the received value is an array for like/match op, just take the first value - if strings.ToLower(item.Operation) == "like" || - strings.ToLower(item.Operation) == "match" || - strings.ToLower(item.Operation) == "nlike" { + if op == "like" || op == "match" || op == "nlike" || op == "nmatch" { x, ok := item.Value.([]interface{}) if ok { if len(x) == 0 { @@ -104,7 +103,7 @@ func BuildMetricsTimeSeriesFilterQuery(fs *model.FilterSet, groupTags []string, } } fmtVal := formattedValue(toFormat) - switch op := strings.ToLower(item.Operation); op { + switch op { case "eq": conditions = append(conditions, fmt.Sprintf("labels_object.%s = %s", item.Key, fmtVal)) case "neq": @@ -119,6 +118,8 @@ func BuildMetricsTimeSeriesFilterQuery(fs *model.FilterSet, groupTags []string, conditions = append(conditions, fmt.Sprintf("notLike(labels_object.%s, %s)", item.Key, fmtVal)) case "match": conditions = append(conditions, fmt.Sprintf("match(labels_object.%s, %s)", item.Key, fmtVal)) + case "nmatch": + conditions = append(conditions, fmt.Sprintf("not match(labels_object.%s, %s)", item.Key, fmtVal)) default: return "", fmt.Errorf("unsupported operation") } @@ -416,6 +417,5 @@ func PrepareBuilderMetricQueries(qp *model.QueryRangeParamsV2, tableName string) if len(errs) != 0 { return &RunQueries{Err: fmt.Errorf("errors with formulas: %s", FormatErrs(errs, "\n"))} } - fmt.Println(namedQueries) return &RunQueries{Queries: namedQueries} } diff --git a/pkg/query-service/app/metrics/query_builder_test.go b/pkg/query-service/app/metrics/query_builder_test.go index 4530a01a79..f6f9944605 100644 --- a/pkg/query-service/app/metrics/query_builder_test.go +++ b/pkg/query-service/app/metrics/query_builder_test.go @@ -42,8 +42,9 @@ func TestBuildQueryWithFilters(t *testing.T) { "a": { QueryName: "a", MetricName: "name", - TagFilters: &model.FilterSet{Operation: "AND", Items: []model.FilterItem{ - {Key: "a", Value: "b", Operation: "neq"}, + TagFilters: &model.FilterSet{Operator: "AND", Items: []model.FilterItem{ + {Key: "a", Value: "b", Operator: "neq"}, + {Key: "code", Value: "ERROR_*", Operator: "nmatch"}, }}, AggregateOperator: model.RATE_MAX, Expression: "a", @@ -56,6 +57,7 @@ func TestBuildQueryWithFilters(t *testing.T) { So(queries["a"], ShouldContainSubstring, "WHERE metric_name = 'name' AND labels_object.a != 'b'") So(queries["a"], ShouldContainSubstring, "runningDifference(value)/runningDifference(ts)") + So(queries["a"], ShouldContainSubstring, "not match(labels_object.code, 'ERROR_*')") }) } @@ -70,8 +72,8 @@ func TestBuildQueryWithMultipleQueries(t *testing.T) { "a": { QueryName: "a", MetricName: "name", - TagFilters: &model.FilterSet{Operation: "AND", Items: []model.FilterItem{ - {Key: "in", Value: []interface{}{"a", "b", "c"}, Operation: "in"}, + TagFilters: &model.FilterSet{Operator: "AND", Items: []model.FilterItem{ + {Key: "in", Value: []interface{}{"a", "b", "c"}, Operator: "in"}, }}, AggregateOperator: model.RATE_AVG, Expression: "a", @@ -103,8 +105,8 @@ func TestBuildQueryWithMultipleQueriesAndFormula(t *testing.T) { "a": { QueryName: "a", MetricName: "name", - TagFilters: &model.FilterSet{Operation: "AND", Items: []model.FilterItem{ - {Key: "in", Value: []interface{}{"a", "b", "c"}, Operation: "in"}, + TagFilters: &model.FilterSet{Operator: "AND", Items: []model.FilterItem{ + {Key: "in", Value: []interface{}{"a", "b", "c"}, Operator: "in"}, }}, AggregateOperator: model.RATE_MAX, Expression: "a", diff --git a/pkg/query-service/model/queryParams.go b/pkg/query-service/model/queryParams.go index d1763a0440..69509849d2 100644 --- a/pkg/query-service/model/queryParams.go +++ b/pkg/query-service/model/queryParams.go @@ -294,17 +294,12 @@ type GetErrorParams struct { } type FilterItem struct { - Key string `json:"key"` - Value interface{} `json:"value"` - Operation string `json:"op"` + Key string `json:"key"` + Value interface{} `json:"value"` + Operator string `json:"op"` } type FilterSet struct { - Operation string `json:"op,omitempty"` - Items []FilterItem `json:"items"` -} - -type RemoveTTLParams struct { - Type string - RemoveAllTTL bool + Operator string `json:"op,omitempty"` + Items []FilterItem `json:"items"` } diff --git a/pkg/query-service/utils/time.go b/pkg/query-service/utils/time.go new file mode 100644 index 0000000000..90e132aff2 --- /dev/null +++ b/pkg/query-service/utils/time.go @@ -0,0 +1,14 @@ +package utils + +import ( + "time" + + "go.uber.org/zap" +) + +func Elapsed(funcName string) func() { + start := time.Now() + return func() { + zap.S().Infof("%s took %v\n", funcName, time.Since(start)) + } +}