From 970cbbee60ff8bcd01ccc3644715414280b49ede Mon Sep 17 00:00:00 2001 From: Pedro Tanaka Date: Tue, 7 May 2024 11:05:19 +0200 Subject: [PATCH] *: Promql changes to add support to extended functions throught Thanos (#7338) * fixing extended functions support in more places Signed-off-by: Pedro Tanaka * Adding new failint for the Parse() method Signed-off-by: Pedro Tanaka * Adding new method for ParseMetricSelector Signed-off-by: Pedro Tanaka * Fixing missing imports Extending test to check behavior More missing imports Signed-off-by: Pedro Tanaka * Fixing method name Signed-off-by: Pedro Tanaka * Solving references to forbidden functions Signed-off-by: Pedro Tanaka * Treating promql validation from ParseExpr Signed-off-by: Pedro Tanaka * fixing funcs Signed-off-by: Pedro Tanaka --------- Signed-off-by: Pedro Tanaka Signed-off-by: Pedro Tanaka --- Makefile | 1 + cmd/thanos/rule.go | 3 +- .../querier/queryrange/results_cache.go | 5 +- .../querier/queryrange/split_by_interval.go | 3 +- .../queryrange/split_by_interval_test.go | 9 ++- pkg/api/query/grpc_test.go | 4 +- pkg/api/query/v1.go | 3 +- pkg/block/metadata/meta.go | 4 +- pkg/exemplars/multitsdb.go | 3 +- pkg/exemplars/proxy.go | 3 +- pkg/exemplars/proxy_test.go | 6 +- pkg/extpromql/parser.go | 55 ++++++++++++++- pkg/extpromql/parser_test.go | 68 +++++++++++++++++++ pkg/query/remote_engine_test.go | 4 +- pkg/query/test_test.go | 6 +- pkg/queryfrontend/queryinstant_codec.go | 5 +- pkg/queryfrontend/queryrange_codec.go | 5 +- pkg/querysharding/analyzer.go | 4 +- pkg/rules/rules.go | 4 +- pkg/store/storepb/custom_test.go | 7 +- pkg/tenancy/tenancy.go | 5 +- 21 files changed, 171 insertions(+), 36 deletions(-) create mode 100644 pkg/extpromql/parser_test.go diff --git a/Makefile b/Makefile index bee70ee848..29e1d5cc87 100644 --- a/Makefile +++ b/Makefile @@ -404,6 +404,7 @@ NewHistorgram,NewHistogramVec,NewSummary,NewSummaryVec}=github.com/prometheus/cl NewCounterVec,NewCounterVec,NewGauge,NewGaugeVec,NewGaugeFunc,NewHistorgram,NewHistogramVec,NewSummary,NewSummaryVec},\ github.com/NYTimes/gziphandler.{GzipHandler}=github.com/klauspost/compress/gzhttp.{GzipHandler},\ sync/atomic=go.uber.org/atomic,github.com/cortexproject/cortex=github.com/thanos-io/thanos/internal/cortex,\ +github.com/prometheus/prometheus/promql/parser.{ParseExpr,ParseMetricSelector}=github.com/thanos-io/thanos/pkg/extpromql.{ParseExpr,ParseMetricSelector},\ io/ioutil.{Discard,NopCloser,ReadAll,ReadDir,ReadFile,TempDir,TempFile,Writefile}" $(shell go list ./... | grep -v "internal/cortex") @$(FAILLINT) -paths "fmt.{Print,Println,Sprint}" -ignore-tests ./... @echo ">> linting all of the Go files GOGC=${GOGC}" diff --git a/cmd/thanos/rule.go b/cmd/thanos/rule.go index 4b89989bac..21c1e9fb11 100644 --- a/cmd/thanos/rule.go +++ b/cmd/thanos/rule.go @@ -59,6 +59,7 @@ import ( "github.com/thanos-io/thanos/pkg/extkingpin" "github.com/thanos-io/thanos/pkg/extprom" extpromhttp "github.com/thanos-io/thanos/pkg/extprom/http" + "github.com/thanos-io/thanos/pkg/extpromql" "github.com/thanos-io/thanos/pkg/info" "github.com/thanos-io/thanos/pkg/info/infopb" "github.com/thanos-io/thanos/pkg/logging" @@ -951,7 +952,7 @@ func queryFuncCreator( queryAPIClients := grpcEndpointSet.GetQueryAPIClients() for _, i := range rand.Perm(len(queryAPIClients)) { e := query.NewRemoteEngine(logger, queryAPIClients[i], query.Opts{}) - expr, err := parser.ParseExpr(qs) + expr, err := extpromql.ParseExpr(qs) if err != nil { level.Error(logger).Log("err", err, "query", qs) continue diff --git a/internal/cortex/querier/queryrange/results_cache.go b/internal/cortex/querier/queryrange/results_cache.go index ae012200f6..a3399e2551 100644 --- a/internal/cortex/querier/queryrange/results_cache.go +++ b/internal/cortex/querier/queryrange/results_cache.go @@ -7,6 +7,7 @@ import ( "context" "flag" "fmt" + "github.com/thanos-io/thanos/pkg/extpromql" "net/http" "sort" "strings" @@ -325,7 +326,7 @@ func (s resultsCache) isAtModifierCachable(r Request, maxCacheTime int64) bool { if !strings.Contains(query, "@") { return true } - expr, err := parser.ParseExpr(query) + expr, err := extpromql.ParseExpr(query) if err != nil { // We are being pessimistic in such cases. level.Warn(s.logger).Log("msg", "failed to parse query, considering @ modifier as not cachable", "query", query, "err", err) @@ -370,7 +371,7 @@ func (s resultsCache) isOffsetCachable(r Request) bool { if !strings.Contains(query, "offset") { return true } - expr, err := parser.ParseExpr(query) + expr, err := extpromql.ParseExpr(query) if err != nil { level.Warn(s.logger).Log("msg", "failed to parse query, considering offset as not cachable", "query", query, "err", err) return false diff --git a/internal/cortex/querier/queryrange/split_by_interval.go b/internal/cortex/querier/queryrange/split_by_interval.go index 039306e880..2ae53f7c50 100644 --- a/internal/cortex/querier/queryrange/split_by_interval.go +++ b/internal/cortex/querier/queryrange/split_by_interval.go @@ -5,6 +5,7 @@ package queryrange import ( "context" + "github.com/thanos-io/thanos/pkg/extpromql" "net/http" "time" @@ -97,7 +98,7 @@ func splitQuery(r Request, interval time.Duration) ([]Request, error) { // For example given the start of the query is 10.00, `http_requests_total[1h] @ start()` query will be replaced with `http_requests_total[1h] @ 10.00` // If the modifier is already a constant, it will be returned as is. func EvaluateAtModifierFunction(query string, start, end int64) (string, error) { - expr, err := parser.ParseExpr(query) + expr, err := extpromql.ParseExpr(query) if err != nil { return "", httpgrpc.Errorf(http.StatusBadRequest, `{"status": "error", "error": "%s"}`, err) } diff --git a/internal/cortex/querier/queryrange/split_by_interval_test.go b/internal/cortex/querier/queryrange/split_by_interval_test.go index bd0e96b35d..68b67d95dc 100644 --- a/internal/cortex/querier/queryrange/split_by_interval_test.go +++ b/internal/cortex/querier/queryrange/split_by_interval_test.go @@ -5,6 +5,7 @@ package queryrange import ( "context" + "github.com/thanos-io/thanos/pkg/extpromql" io "io" "net/http" "net/http/httptest" @@ -13,7 +14,6 @@ import ( "testing" "time" - "github.com/prometheus/prometheus/promql/parser" "github.com/stretchr/testify/require" "github.com/weaveworks/common/httpgrpc" "github.com/weaveworks/common/middleware" @@ -332,6 +332,11 @@ func Test_evaluateAtModifier(t *testing.T) { in: "topk(5, rate(http_requests_total[1h] @ start()))", expected: "topk(5, rate(http_requests_total[1h] @ 1546300.800))", }, + { + // extended functions + in: "topk(5, xrate(http_requests_total[1h] @ start()))", + expected: "topk(5, xrate(http_requests_total[1h] @ 1546300.800))", + }, { in: "topk(5, rate(http_requests_total[1h] @ 0))", expected: "topk(5, rate(http_requests_total[1h] @ 0.000))", @@ -390,7 +395,7 @@ func Test_evaluateAtModifier(t *testing.T) { require.Equal(t, tt.expectedErrorCode, int(httpResp.Code)) } else { require.NoError(t, err) - expectedExpr, err := parser.ParseExpr(tt.expected) + expectedExpr, err := extpromql.ParseExpr(tt.expected) require.NoError(t, err) require.Equal(t, expectedExpr.String(), out) } diff --git a/pkg/api/query/grpc_test.go b/pkg/api/query/grpc_test.go index 4885126c46..868ed3d411 100644 --- a/pkg/api/query/grpc_test.go +++ b/pkg/api/query/grpc_test.go @@ -13,7 +13,6 @@ import ( "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/prometheus/promql" - "github.com/prometheus/prometheus/promql/parser" "github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/util/annotations" "github.com/thanos-io/promql-engine/logicalplan" @@ -21,6 +20,7 @@ import ( "github.com/thanos-io/thanos/pkg/api/query/querypb" "github.com/thanos-io/thanos/pkg/component" + "github.com/thanos-io/thanos/pkg/extpromql" "github.com/thanos-io/thanos/pkg/query" "github.com/thanos-io/thanos/pkg/store" ) @@ -36,7 +36,7 @@ func TestGRPCQueryAPIWithQueryPlan(t *testing.T) { } api := NewGRPCAPI(time.Now, nil, queryableCreator, engineFactory, querypb.EngineType_thanos, lookbackDeltaFunc, 0) - expr, err := parser.ParseExpr("metric") + expr, err := extpromql.ParseExpr("metric") testutil.Ok(t, err) lplan := logicalplan.NewFromAST(expr, &equery.Options{}, logicalplan.PlanOptions{}) testutil.Ok(t, err) diff --git a/pkg/api/query/v1.go b/pkg/api/query/v1.go index 0b8bb93fb2..9454dfd65f 100644 --- a/pkg/api/query/v1.go +++ b/pkg/api/query/v1.go @@ -52,6 +52,7 @@ import ( "github.com/thanos-io/thanos/pkg/exemplars" "github.com/thanos-io/thanos/pkg/exemplars/exemplarspb" extpromhttp "github.com/thanos-io/thanos/pkg/extprom/http" + "github.com/thanos-io/thanos/pkg/extpromql" "github.com/thanos-io/thanos/pkg/gate" "github.com/thanos-io/thanos/pkg/logging" "github.com/thanos-io/thanos/pkg/metadata" @@ -374,7 +375,7 @@ func (qapi *QueryAPI) parseStoreDebugMatchersParam(r *http.Request) (storeMatche } for _, s := range r.Form[StoreMatcherParam] { - matchers, err := parser.ParseMetricSelector(s) + matchers, err := extpromql.ParseMetricSelector(s) if err != nil { return nil, &api.ApiError{Typ: api.ErrorBadData, Err: err} } diff --git a/pkg/block/metadata/meta.go b/pkg/block/metadata/meta.go index a479ee242d..11567fb06e 100644 --- a/pkg/block/metadata/meta.go +++ b/pkg/block/metadata/meta.go @@ -20,12 +20,12 @@ import ( "github.com/pkg/errors" "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/relabel" - "github.com/prometheus/prometheus/promql/parser" "github.com/prometheus/prometheus/tsdb" "github.com/prometheus/prometheus/tsdb/fileutil" "github.com/prometheus/prometheus/tsdb/tombstones" "gopkg.in/yaml.v3" + "github.com/thanos-io/thanos/pkg/extpromql" "github.com/thanos-io/thanos/pkg/runutil" ) @@ -136,7 +136,7 @@ type Rewrite struct { type Matchers []*labels.Matcher func (m *Matchers) UnmarshalYAML(value *yaml.Node) (err error) { - *m, err = parser.ParseMetricSelector(value.Value) + *m, err = extpromql.ParseMetricSelector(value.Value) if err != nil { return errors.Wrapf(err, "parse metric selector %v", value.Value) } diff --git a/pkg/exemplars/multitsdb.go b/pkg/exemplars/multitsdb.go index c70811b8db..985f0b6bfe 100644 --- a/pkg/exemplars/multitsdb.go +++ b/pkg/exemplars/multitsdb.go @@ -6,6 +6,7 @@ package exemplars import ( "github.com/pkg/errors" "github.com/prometheus/prometheus/promql/parser" + "github.com/thanos-io/thanos/pkg/extpromql" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -26,7 +27,7 @@ func NewMultiTSDB(tsdbExemplarsServers func() map[string]*TSDB) *MultiTSDB { // Exemplars returns all specified exemplars from a MultiTSDB instance. func (m *MultiTSDB) Exemplars(r *exemplarspb.ExemplarsRequest, s exemplarspb.Exemplars_ExemplarsServer) error { - expr, err := parser.ParseExpr(r.Query) + expr, err := extpromql.ParseExpr(r.Query) if err != nil { return status.Error(codes.Internal, err.Error()) } diff --git a/pkg/exemplars/proxy.go b/pkg/exemplars/proxy.go index 052f7922ac..c7d8fb911c 100644 --- a/pkg/exemplars/proxy.go +++ b/pkg/exemplars/proxy.go @@ -19,6 +19,7 @@ import ( "google.golang.org/grpc/status" "github.com/thanos-io/thanos/pkg/exemplars/exemplarspb" + "github.com/thanos-io/thanos/pkg/extpromql" "github.com/thanos-io/thanos/pkg/store" "github.com/thanos-io/thanos/pkg/store/storepb" "github.com/thanos-io/thanos/pkg/tracing" @@ -59,7 +60,7 @@ func (s *Proxy) Exemplars(req *exemplarspb.ExemplarsRequest, srv exemplarspb.Exe span, ctx := tracing.StartSpan(srv.Context(), "proxy_exemplars") defer span.Finish() - expr, err := parser.ParseExpr(req.Query) + expr, err := extpromql.ParseExpr(req.Query) if err != nil { return err } diff --git a/pkg/exemplars/proxy_test.go b/pkg/exemplars/proxy_test.go index 16c1724f27..0e0ca58f8e 100644 --- a/pkg/exemplars/proxy_test.go +++ b/pkg/exemplars/proxy_test.go @@ -12,6 +12,7 @@ import ( "sync" "testing" + "github.com/efficientgo/core/testutil" "github.com/go-kit/log" "github.com/pkg/errors" "github.com/prometheus/prometheus/model/labels" @@ -21,9 +22,8 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "github.com/efficientgo/core/testutil" - "github.com/thanos-io/thanos/pkg/exemplars/exemplarspb" + "github.com/thanos-io/thanos/pkg/extpromql" "github.com/thanos-io/thanos/pkg/store/labelpb" "github.com/thanos-io/thanos/pkg/store/storepb" ) @@ -54,7 +54,7 @@ func (t *testExemplarClient) Recv() (*exemplarspb.ExemplarsResponse, error) { } func (t *testExemplarClient) Exemplars(ctx context.Context, in *exemplarspb.ExemplarsRequest, opts ...grpc.CallOption) (exemplarspb.Exemplars_ExemplarsClient, error) { - expr, err := parser.ParseExpr(in.Query) + expr, err := extpromql.ParseExpr(in.Query) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/pkg/extpromql/parser.go b/pkg/extpromql/parser.go index 72302b7ef2..43d7188fdc 100644 --- a/pkg/extpromql/parser.go +++ b/pkg/extpromql/parser.go @@ -4,12 +4,63 @@ package extpromql import ( + "fmt" + "strings" + + "github.com/pkg/errors" + "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/promql/parser" + "github.com/thanos-io/promql-engine/execution/function" ) -func ParserExpr(input string) (parser.Expr, error) { - p := parser.NewParser(input, parser.WithFunctions(function.XFunctions)) +// ParseExpr parses the input PromQL expression and returns the parsed representation. +func ParseExpr(input string) (parser.Expr, error) { + allFuncs := make(map[string]*parser.Function, len(function.XFunctions)+len(parser.Functions)) + for k, v := range parser.Functions { + allFuncs[k] = v + } + for k, v := range function.XFunctions { + allFuncs[k] = v + } + p := parser.NewParser(input, parser.WithFunctions(allFuncs)) defer p.Close() return p.ParseExpr() } + +// ParseMetricSelector parses the provided textual metric selector into a list of +// label matchers. +func ParseMetricSelector(input string) ([]*labels.Matcher, error) { + expr, err := ParseExpr(input) + // because of the AST checking present in the ParseExpr function, + // we need to ignore the error if it is just the check for empty name matcher. + if err != nil && !isEmptyNameMatcherErr(err) { + return nil, err + } + + vs, ok := expr.(*parser.VectorSelector) + if !ok { + return nil, fmt.Errorf("expected type *parser.VectorSelector, got %T", expr) + } + + matchers := make([]*labels.Matcher, len(vs.LabelMatchers)) + for i, lm := range vs.LabelMatchers { + matchers[i] = &labels.Matcher{ + Type: lm.Type, + Name: lm.Name, + Value: lm.Value, + } + } + + return matchers, nil +} + +func isEmptyNameMatcherErr(err error) bool { + var parseErrs parser.ParseErrors + if errors.As(err, &parseErrs) { + return len(parseErrs) == 1 && + strings.HasSuffix(parseErrs[0].Error(), "vector selector must contain at least one non-empty matcher") + } + + return false +} diff --git a/pkg/extpromql/parser_test.go b/pkg/extpromql/parser_test.go new file mode 100644 index 0000000000..72ef7b26cb --- /dev/null +++ b/pkg/extpromql/parser_test.go @@ -0,0 +1,68 @@ +// Copyright (c) The Thanos Authors. +// Licensed under the Apache License 2.0. + +package extpromql_test + +import ( + "fmt" + "testing" + + "github.com/efficientgo/core/testutil" + "github.com/prometheus/prometheus/model/labels" + "github.com/prometheus/prometheus/promql/parser" + + "github.com/thanos-io/thanos/pkg/extpromql" +) + +func TestParseMetricSelector(t *testing.T) { + testCases := []struct { + name string + input string + }{ + { + name: "single selector", + input: `http_requests_total{method="GET"}`, + }, + { + name: "empty selectors", + input: `process_cpu_seconds_total`, + }, + { + name: "multiple selectors", + input: `http_requests_total{method="GET",code="200"}`, + }, + { + name: "multiple selectors with different matchers", + input: `http_requests_total{method="GET",code!="200"}`, + }, + { + name: "multiple selectors with regex", + input: `http_requests_total{method="GET",code=~"2.*"}`, + }, + { + name: "selector with negative regex", + input: `{code!~"2.*"}`, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + //lint:ignore faillint Testing against prometheus parser. + want, err := parser.ParseMetricSelector(tc.input) + if err != nil { + t.Fatalf("Prometheus ParseMetricSelector failed: %v", err) + } + + got, err := extpromql.ParseMetricSelector(tc.input) + if err != nil { + t.Fatalf("ParseMetricSelector failed: %v", err) + } + + testutil.Equals(t, stringFmt(want), stringFmt(got)) + }) + } +} + +func stringFmt(got []*labels.Matcher) string { + return fmt.Sprintf("%v", got) +} diff --git a/pkg/query/remote_engine_test.go b/pkg/query/remote_engine_test.go index bca79598e5..137bd73da1 100644 --- a/pkg/query/remote_engine_test.go +++ b/pkg/query/remote_engine_test.go @@ -14,12 +14,12 @@ import ( "github.com/go-kit/log" "github.com/pkg/errors" "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql/parser" "github.com/thanos-io/promql-engine/logicalplan" "github.com/thanos-io/promql-engine/query" "google.golang.org/grpc" "github.com/thanos-io/thanos/pkg/api/query/querypb" + "github.com/thanos-io/thanos/pkg/extpromql" "github.com/thanos-io/thanos/pkg/info/infopb" "github.com/thanos-io/thanos/pkg/store/labelpb" ) @@ -34,7 +34,7 @@ func TestRemoteEngine_Warnings(t *testing.T) { end = time.Unix(120, 0) step = 30 * time.Second ) - qryExpr, err := parser.ParseExpr("up") + qryExpr, err := extpromql.ParseExpr("up") testutil.Ok(t, err) plan := logicalplan.NewFromAST(qryExpr, &query.Options{ diff --git a/pkg/query/test_test.go b/pkg/query/test_test.go index b8457870ca..d8af78c66d 100644 --- a/pkg/query/test_test.go +++ b/pkg/query/test_test.go @@ -24,6 +24,8 @@ import ( "github.com/prometheus/prometheus/promql/parser/posrange" "github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/util/teststorage" + + "github.com/thanos-io/thanos/pkg/extpromql" ) var ( @@ -261,7 +263,7 @@ func ParseStore(lines []string, i int) (int, *storeCmd, error) { } parts := patStore.FindStringSubmatch(lines[i]) - m, err := parser.ParseMetricSelector(parts[1]) + m, err := extpromql.ParseMetricSelector(parts[1]) if err != nil { return i, nil, raise(i, "invalid matcher definition %q: %s", parts[1], err) } @@ -322,7 +324,7 @@ func ParseEval(lines []string, i int) (int, *evalCmd, error) { at = parts[2] expr = parts[3] ) - _, err := parser.ParseExpr(expr) + _, err := extpromql.ParseExpr(expr) if err != nil { if perr, ok := err.(*parser.ParseErr); ok { perr.LineOffset = i diff --git a/pkg/queryfrontend/queryinstant_codec.go b/pkg/queryfrontend/queryinstant_codec.go index edd412a4a9..a44bb7d94e 100644 --- a/pkg/queryfrontend/queryinstant_codec.go +++ b/pkg/queryfrontend/queryinstant_codec.go @@ -17,14 +17,15 @@ import ( "github.com/opentracing/opentracing-go" otlog "github.com/opentracing/opentracing-go/log" "github.com/prometheus/common/model" + "github.com/prometheus/prometheus/promql/parser" "github.com/weaveworks/common/httpgrpc" - "github.com/prometheus/prometheus/promql/parser" "github.com/thanos-io/thanos/internal/cortex/cortexpb" "github.com/thanos-io/thanos/internal/cortex/querier/queryrange" cortexutil "github.com/thanos-io/thanos/internal/cortex/util" "github.com/thanos-io/thanos/internal/cortex/util/spanlogger" queryv1 "github.com/thanos-io/thanos/pkg/api/query" + "github.com/thanos-io/thanos/pkg/extpromql" ) // queryInstantCodec is used to encode/decode Thanos instant query requests and responses. @@ -370,7 +371,7 @@ const ( ) func sortPlanForQuery(q string) (sortPlan, error) { - expr, err := parser.ParseExpr(q) + expr, err := extpromql.ParseExpr(q) if err != nil { return 0, err } diff --git a/pkg/queryfrontend/queryrange_codec.go b/pkg/queryfrontend/queryrange_codec.go index fca6ea7fc7..4de0dd387e 100644 --- a/pkg/queryfrontend/queryrange_codec.go +++ b/pkg/queryfrontend/queryrange_codec.go @@ -16,13 +16,12 @@ import ( "github.com/prometheus/common/model" "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql/parser" "github.com/weaveworks/common/httpgrpc" "github.com/thanos-io/thanos/internal/cortex/querier/queryrange" cortexutil "github.com/thanos-io/thanos/internal/cortex/util" - queryv1 "github.com/thanos-io/thanos/pkg/api/query" + "github.com/thanos-io/thanos/pkg/extpromql" "github.com/thanos-io/thanos/pkg/store/storepb" ) @@ -269,7 +268,7 @@ func parsePartialResponseParam(s string, defaultEnablePartialResponse bool) (boo func parseMatchersParam(ss url.Values, matcherParam string) ([][]*labels.Matcher, error) { matchers := make([][]*labels.Matcher, 0, len(ss[matcherParam])) for _, s := range ss[matcherParam] { - ms, err := parser.ParseMetricSelector(s) + ms, err := extpromql.ParseMetricSelector(s) if err != nil { return nil, httpgrpc.Errorf(http.StatusBadRequest, errCannotParse, matcherParam) } diff --git a/pkg/querysharding/analyzer.go b/pkg/querysharding/analyzer.go index 7b8e849bca..80cb8cb3a8 100644 --- a/pkg/querysharding/analyzer.go +++ b/pkg/querysharding/analyzer.go @@ -22,6 +22,8 @@ import ( lru "github.com/hashicorp/golang-lru/v2" "github.com/prometheus/common/model" "github.com/prometheus/prometheus/promql/parser" + + "github.com/thanos-io/thanos/pkg/extpromql" ) var ( @@ -88,7 +90,7 @@ func (a *CachedQueryAnalyzer) Analyze(query string) (QueryAnalysis, error) { // // The le label is excluded from sharding. func (a *QueryAnalyzer) Analyze(query string) (QueryAnalysis, error) { - expr, err := parser.ParseExpr(query) + expr, err := extpromql.ParseExpr(query) if err != nil { return nonShardableQuery(), err } diff --git a/pkg/rules/rules.go b/pkg/rules/rules.go index 72f5db3a44..1777a45181 100644 --- a/pkg/rules/rules.go +++ b/pkg/rules/rules.go @@ -12,9 +12,9 @@ import ( "github.com/pkg/errors" "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql/parser" "github.com/prometheus/prometheus/util/annotations" + "github.com/thanos-io/thanos/pkg/extpromql" "github.com/thanos-io/thanos/pkg/rules/rulespb" "github.com/thanos-io/thanos/pkg/tracing" ) @@ -64,7 +64,7 @@ func (rr *GRPCClient) Rules(ctx context.Context, req *rulespb.RulesRequest) (*ru var err error matcherSets := make([][]*labels.Matcher, len(req.MatcherString)) for i, s := range req.MatcherString { - matcherSets[i], err = parser.ParseMetricSelector(s) + matcherSets[i], err = extpromql.ParseMetricSelector(s) if err != nil { return nil, nil, errors.Wrap(err, "parser ParseMetricSelector") } diff --git a/pkg/store/storepb/custom_test.go b/pkg/store/storepb/custom_test.go index eff2be6e80..4a1c6d83c2 100644 --- a/pkg/store/storepb/custom_test.go +++ b/pkg/store/storepb/custom_test.go @@ -12,10 +12,11 @@ import ( "github.com/pkg/errors" "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql/parser" "github.com/prometheus/prometheus/tsdb/chunkenc" "github.com/efficientgo/core/testutil" + + "github.com/thanos-io/thanos/pkg/extpromql" "github.com/thanos-io/thanos/pkg/store/labelpb" ) @@ -520,8 +521,8 @@ func TestMatchersToString_Translate(t *testing.T) { testutil.Equals(t, c.expected, MatchersToString(ms...)) // Is this parsable? - promMsParsed, err := parser.ParseMetricSelector(c.expected) - testutil.Ok(t, err) + promMsParsed, err := extpromql.ParseMetricSelector(c.expected) + testutil.Ok(t, err, "unexpected error parsing %q", c.expected) testutil.Assert(t, len(promMs) == len(promMsParsed)) for i := 0; i < len(promMs); i++ { testutil.Equals(t, promMs[i].String(), promMsParsed[i].String()) diff --git a/pkg/tenancy/tenancy.go b/pkg/tenancy/tenancy.go index a350062194..9da1372933 100644 --- a/pkg/tenancy/tenancy.go +++ b/pkg/tenancy/tenancy.go @@ -11,7 +11,6 @@ import ( "github.com/pkg/errors" "github.com/prometheus-community/prom-label-proxy/injectproxy" "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql/parser" "google.golang.org/grpc/metadata" "github.com/thanos-io/thanos/pkg/extpromql" @@ -150,7 +149,7 @@ func EnforceQueryTenancy(tenantLabel string, tenant string, query string) (strin e := injectproxy.NewEnforcer(false, labelMatcher) - expr, err := extpromql.ParserExpr(query) + expr, err := extpromql.ParseExpr(query) if err != nil { return "", errors.Wrap(err, "error parsing query string, when enforcing tenenacy") } @@ -180,7 +179,7 @@ func getLabelMatchers(formMatchers []string, tenant string, enforceTenancy bool, } for _, s := range formMatchers { - matchers, err := parser.ParseMetricSelector(s) + matchers, err := extpromql.ParseMetricSelector(s) if err != nil { return nil, err }