feat: add support for not regex (#1328)

* feat: add support for not regex

Co-authored-by: Vishal Sharma <makeavish786@gmail.com>
This commit is contained in:
Srikanth Chekuri 2022-07-06 15:49:27 +05:30 committed by GitHub
parent 091d769ad8
commit da368ab5e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 25 deletions

View File

@ -50,6 +50,7 @@ import (
"go.signoz.io/query-service/constants" "go.signoz.io/query-service/constants"
am "go.signoz.io/query-service/integrations/alertManager" am "go.signoz.io/query-service/integrations/alertManager"
"go.signoz.io/query-service/model" "go.signoz.io/query-service/model"
"go.signoz.io/query-service/utils"
"go.uber.org/zap" "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 // GetMetricResult runs the query and returns list of time series
func (r *ClickHouseReader) GetMetricResult(ctx context.Context, query string) ([]*model.Series, error) { 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) rows, err := r.db.Query(ctx, query)
if err != nil { if err != nil {

View File

@ -180,10 +180,10 @@ func writeHttpResponse(w http.ResponseWriter, data interface{}) {
} }
func (aH *APIHandler) RegisterMetricsRoutes(router *mux.Router) { func (aH *APIHandler) RegisterMetricsRoutes(router *mux.Router) {
subRouter := router.PathPrefix("/api/v2/metrics").Subrouter() subRouter := router.PathPrefix("/api/v2/metrics").Subrouter()
subRouter.HandleFunc("/query_range", aH.queryRangeMetricsV2).Methods(http.MethodPost) subRouter.HandleFunc("/query_range", ViewAccess(aH.queryRangeMetricsV2)).Methods(http.MethodPost)
subRouter.HandleFunc("/autocomplete/list", aH.metricAutocompleteMetricName).Methods(http.MethodGet) subRouter.HandleFunc("/autocomplete/list", ViewAccess(aH.metricAutocompleteMetricName)).Methods(http.MethodGet)
subRouter.HandleFunc("/autocomplete/tagKey", aH.metricAutocompleteTagKey).Methods(http.MethodGet) subRouter.HandleFunc("/autocomplete/tagKey", ViewAccess(aH.metricAutocompleteTagKey)).Methods(http.MethodGet)
subRouter.HandleFunc("/autocomplete/tagValue", aH.metricAutocompleteTagValue).Methods(http.MethodGet) subRouter.HandleFunc("/autocomplete/tagValue", ViewAccess(aH.metricAutocompleteTagValue)).Methods(http.MethodGet)
} }
func (aH *APIHandler) respond(w http.ResponseWriter, data interface{}) { func (aH *APIHandler) respond(w http.ResponseWriter, data interface{}) {

View File

@ -91,10 +91,9 @@ func BuildMetricsTimeSeriesFilterQuery(fs *model.FilterSet, groupTags []string,
if fs != nil && len(fs.Items) != 0 { if fs != nil && len(fs.Items) != 0 {
for _, item := range fs.Items { for _, item := range fs.Items {
toFormat := item.Value 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 the received value is an array for like/match op, just take the first value
if strings.ToLower(item.Operation) == "like" || if op == "like" || op == "match" || op == "nlike" || op == "nmatch" {
strings.ToLower(item.Operation) == "match" ||
strings.ToLower(item.Operation) == "nlike" {
x, ok := item.Value.([]interface{}) x, ok := item.Value.([]interface{})
if ok { if ok {
if len(x) == 0 { if len(x) == 0 {
@ -104,7 +103,7 @@ func BuildMetricsTimeSeriesFilterQuery(fs *model.FilterSet, groupTags []string,
} }
} }
fmtVal := formattedValue(toFormat) fmtVal := formattedValue(toFormat)
switch op := strings.ToLower(item.Operation); op { switch op {
case "eq": case "eq":
conditions = append(conditions, fmt.Sprintf("labels_object.%s = %s", item.Key, fmtVal)) conditions = append(conditions, fmt.Sprintf("labels_object.%s = %s", item.Key, fmtVal))
case "neq": 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)) conditions = append(conditions, fmt.Sprintf("notLike(labels_object.%s, %s)", item.Key, fmtVal))
case "match": case "match":
conditions = append(conditions, fmt.Sprintf("match(labels_object.%s, %s)", item.Key, fmtVal)) 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: default:
return "", fmt.Errorf("unsupported operation") return "", fmt.Errorf("unsupported operation")
} }
@ -416,6 +417,5 @@ func PrepareBuilderMetricQueries(qp *model.QueryRangeParamsV2, tableName string)
if len(errs) != 0 { if len(errs) != 0 {
return &RunQueries{Err: fmt.Errorf("errors with formulas: %s", FormatErrs(errs, "\n"))} return &RunQueries{Err: fmt.Errorf("errors with formulas: %s", FormatErrs(errs, "\n"))}
} }
fmt.Println(namedQueries)
return &RunQueries{Queries: namedQueries} return &RunQueries{Queries: namedQueries}
} }

View File

@ -42,8 +42,9 @@ func TestBuildQueryWithFilters(t *testing.T) {
"a": { "a": {
QueryName: "a", QueryName: "a",
MetricName: "name", MetricName: "name",
TagFilters: &model.FilterSet{Operation: "AND", Items: []model.FilterItem{ TagFilters: &model.FilterSet{Operator: "AND", Items: []model.FilterItem{
{Key: "a", Value: "b", Operation: "neq"}, {Key: "a", Value: "b", Operator: "neq"},
{Key: "code", Value: "ERROR_*", Operator: "nmatch"},
}}, }},
AggregateOperator: model.RATE_MAX, AggregateOperator: model.RATE_MAX,
Expression: "a", 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, "WHERE metric_name = 'name' AND labels_object.a != 'b'")
So(queries["a"], ShouldContainSubstring, "runningDifference(value)/runningDifference(ts)") 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": { "a": {
QueryName: "a", QueryName: "a",
MetricName: "name", MetricName: "name",
TagFilters: &model.FilterSet{Operation: "AND", Items: []model.FilterItem{ TagFilters: &model.FilterSet{Operator: "AND", Items: []model.FilterItem{
{Key: "in", Value: []interface{}{"a", "b", "c"}, Operation: "in"}, {Key: "in", Value: []interface{}{"a", "b", "c"}, Operator: "in"},
}}, }},
AggregateOperator: model.RATE_AVG, AggregateOperator: model.RATE_AVG,
Expression: "a", Expression: "a",
@ -103,8 +105,8 @@ func TestBuildQueryWithMultipleQueriesAndFormula(t *testing.T) {
"a": { "a": {
QueryName: "a", QueryName: "a",
MetricName: "name", MetricName: "name",
TagFilters: &model.FilterSet{Operation: "AND", Items: []model.FilterItem{ TagFilters: &model.FilterSet{Operator: "AND", Items: []model.FilterItem{
{Key: "in", Value: []interface{}{"a", "b", "c"}, Operation: "in"}, {Key: "in", Value: []interface{}{"a", "b", "c"}, Operator: "in"},
}}, }},
AggregateOperator: model.RATE_MAX, AggregateOperator: model.RATE_MAX,
Expression: "a", Expression: "a",

View File

@ -294,17 +294,12 @@ type GetErrorParams struct {
} }
type FilterItem struct { type FilterItem struct {
Key string `json:"key"` Key string `json:"key"`
Value interface{} `json:"value"` Value interface{} `json:"value"`
Operation string `json:"op"` Operator string `json:"op"`
} }
type FilterSet struct { type FilterSet struct {
Operation string `json:"op,omitempty"` Operator string `json:"op,omitempty"`
Items []FilterItem `json:"items"` Items []FilterItem `json:"items"`
}
type RemoveTTLParams struct {
Type string
RemoveAllTTL bool
} }

View File

@ -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))
}
}