From c88f5a36d0f651b72f09294b8b35500172e52590 Mon Sep 17 00:00:00 2001 From: Ben Ye Date: Fri, 10 Mar 2023 08:16:45 -0800 Subject: [PATCH] disable absent and absent_over_time for vertical sharding (#6201) --- CHANGELOG.md | 1 + pkg/querysharding/analyzer.go | 18 +++++++++++++++++- pkg/querysharding/analyzer_test.go | 8 ++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 194a6dc29b..964a3fd328 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ We use *breaking :warning:* to mark changes that are not backward compatible (re ### Changed - [#6168](https://github.com/thanos-io/thanos/pull/6168) Receiver: Make ketama hashring fail early when configured with number of nodes lower than the replication factor. +- [#6201](https://github.com/thanos-io/thanos/pull/6201) Query-Frontend: Disable absent and absent_over_time for vertical sharding. ### Removed diff --git a/pkg/querysharding/analyzer.go b/pkg/querysharding/analyzer.go index dc8b16ca72..37a0d30296 100644 --- a/pkg/querysharding/analyzer.go +++ b/pkg/querysharding/analyzer.go @@ -17,11 +17,17 @@ package querysharding import ( + "fmt" + lru "github.com/hashicorp/golang-lru" "github.com/prometheus/common/model" "github.com/prometheus/prometheus/promql/parser" ) +var ( + notShardableErr = fmt.Errorf("expressions are not shardable") +) + type Analyzer interface { Analyze(string) (QueryAnalysis, error) } @@ -72,7 +78,9 @@ func (a *CachedQueryAnalyzer) Analyze(query string) (QueryAnalysis, error) { // Analyze uses the following algorithm: // - if a query has functions which cannot be sharded such as -// label_join or label_replace, then treat the query as non shardable. +// absent or absent_over_time, then treat the query as non shardable. +// - if a query has functions `label_join` or `label_replace`, +// calculate the shard labels based on grouping labels. // - Walk the query and find the least common labelset // used in grouping expressions. If non-empty, treat the query // as shardable by those labels. @@ -89,6 +97,7 @@ func (a *QueryAnalyzer) Analyze(query string) (QueryAnalysis, error) { analysis QueryAnalysis dynamicLabels []string ) + isShardable := true parser.Inspect(expr, func(node parser.Node, nodes []parser.Node) error { switch n := node.(type) { case *parser.Call: @@ -96,6 +105,9 @@ func (a *QueryAnalyzer) Analyze(query string) (QueryAnalysis, error) { if n.Func.Name == "label_join" || n.Func.Name == "label_replace" { dstLabel := stringFromArg(n.Args[1]) dynamicLabels = append(dynamicLabels, dstLabel) + } else if n.Func.Name == "absent_over_time" || n.Func.Name == "absent" { + isShardable = false + return notShardableErr } } case *parser.BinaryExpr: @@ -117,6 +129,10 @@ func (a *QueryAnalyzer) Analyze(query string) (QueryAnalysis, error) { return nil }) + if !isShardable { + return nonShardableQuery(), nil + } + // If currently it is shard by, it is still shardable if there is // any label left after removing the dynamic labels. // If currently it is shard without, it is still shardable if we diff --git a/pkg/querysharding/analyzer_test.go b/pkg/querysharding/analyzer_test.go index b13e805667..6faa6e839f 100644 --- a/pkg/querysharding/analyzer_test.go +++ b/pkg/querysharding/analyzer_test.go @@ -67,6 +67,14 @@ http_requests_total`, name: "aggregate by expression with label_join, sharding label is dynamic", expression: `sum by (dst_label) (label_join(metric, "dst_label", ",", "src_label"))`, }, + { + name: "absent_over_time is not shardable", + expression: `sum by (url) (absent_over_time(http_requests_total{code="400"}[5m]))`, + }, + { + name: "absent is not shardable", + expression: `sum by (url) (absent(http_requests_total{code="400"}))`, + }, } shardableByLabels := []testCase{