Skip to content

Commit

Permalink
Infer max query downsample resolution from promql query (thanos-io#7012)
Browse files Browse the repository at this point in the history
* Adjust max_source_resolution automatically based promql queries

Signed-off-by: Ben Ye <benye@amazon.com>

* fix data race

Signed-off-by: yeya24 <benye@amazon.com>

---------

Signed-off-by: Ben Ye <benye@amazon.com>
Signed-off-by: yeya24 <benye@amazon.com>
  • Loading branch information
yeya24 authored Feb 25, 2025
1 parent 4a83459 commit 4ba7d59
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 2 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ We use *breaking :warning:* to mark changes that are not backward compatible (re
### Fixed
- [#8091](https://github.com/thanos-io/thanos/pull/8091) *: Add POST into allowed CORS methods header
- [#8046](https://github.com/thanos-io/thanos/pull/8046) Query-Frontend: Fix query statistic reporting for range queries when caching is enabled.

- [#7978](https://github.com/thanos-io/thanos/pull/7978) Receive: Fix deadlock during local writes when `split-tenant-label-name` is used
- [#8016](https://github.com/thanos-io/thanos/pull/8016) Query Frontend: Fix @ modifier not being applied correctly on sub queries.

Expand All @@ -28,6 +27,7 @@ We use *breaking :warning:* to mark changes that are not backward compatible (re
### Changed

- [#7890](https://github.com/thanos-io/thanos/pull/7890) Query,Ruler: *breaking :warning:* deprecated `--store.sd-file` and `--store.sd-interval` to be replaced with `--endpoint.sd-config` and `--endpoint-sd-config-reload-interval`; removed legacy flags to pass endpoints `--store`, `--metadata`, `--rule`, `--exemplar`.
- [#7012](https://github.com/thanos-io/thanos/pull/7012) Query: Automatically adjust `max_source_resolution` based on promql query to avoid querying data from higher resolution resulting empty results.

### Removed

Expand Down
25 changes: 24 additions & 1 deletion pkg/query/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ import (
"github.com/thanos-io/thanos/pkg/tracing"
)

var promqlFuncRequiresTwoSamples = map[string]struct{}{
"rate": {},
"irate": {},
"increase": {},
"delta": {},
"idelta": {},
"deriv": {},
"predict_linear": {},
"holt_winters": {},
"double_exponential_smoothing": {},
}

type seriesStatsReporter func(seriesStats storepb.SeriesStatsCounter)

var NoopSeriesStatsReporter seriesStatsReporter = func(_ storepb.SeriesStatsCounter) {}
Expand Down Expand Up @@ -320,6 +332,7 @@ func (q *querier) selectFn(ctx context.Context, hints *storage.SelectHints, ms .
}

aggrs := aggrsFromFunc(hints.Func)
maxResolutionMillis := maxResolutionFromSelectHints(q.maxResolutionMillis, hints.Range, hints.Func)

// TODO(bwplotka): Pass it using the SeriesRequest instead of relying on context.
ctx = context.WithValue(ctx, store.StoreMatcherKey, q.storeDebugMatchers)
Expand All @@ -333,7 +346,7 @@ func (q *querier) selectFn(ctx context.Context, hints *storage.SelectHints, ms .
MaxTime: hints.End,
Limit: int64(hints.Limit),
Matchers: sms,
MaxResolutionWindow: q.maxResolutionMillis,
MaxResolutionWindow: maxResolutionMillis,
Aggregates: aggrs,
ShardInfo: q.shardInfo,
PartialResponseStrategy: q.partialResponseStrategy,
Expand Down Expand Up @@ -460,3 +473,13 @@ func (q *querier) LabelNames(ctx context.Context, hints *storage.LabelHints, mat
}

func (q *querier) Close() error { return nil }

// maxResolutionFromSelectHints finds the max possible resolution by inferring from the promql query.
func maxResolutionFromSelectHints(maxResolutionMillis int64, hintsRange int64, hintsFunc string) int64 {
if hintsRange > 0 {
if _, ok := promqlFuncRequiresTwoSamples[hintsFunc]; ok {
maxResolutionMillis = min(maxResolutionMillis, hintsRange/2)
}
}
return maxResolutionMillis
}
132 changes: 132 additions & 0 deletions pkg/query/querier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/prometheus/prometheus/util/gate"
"github.com/thanos-io/thanos/pkg/logutil"

"github.com/thanos-io/thanos/pkg/compact/downsample"
"github.com/thanos-io/thanos/pkg/component"
"github.com/thanos-io/thanos/pkg/store"
"github.com/thanos-io/thanos/pkg/store/labelpb"
Expand Down Expand Up @@ -1279,3 +1280,134 @@ func storeSeriesResponse(t testing.TB, lset labels.Labels, smplChunks ...[]sampl
}
return storepb.NewSeriesResponse(&s)
}

func TestMaxResolutionFromSelectHints(t *testing.T) {
twoMinRange := int64(2 * 60 * 1000)
for _, tc := range []struct {
name string
maxResolutionMillis int64
hints storage.SelectHints
expected int64
}{
{
name: "no range",
hints: storage.SelectHints{
Range: 0,
},
maxResolutionMillis: downsample.ResLevel1,
expected: downsample.ResLevel1,
},
{
name: "no function",
hints: storage.SelectHints{
Range: twoMinRange,
},
maxResolutionMillis: downsample.ResLevel1,
expected: downsample.ResLevel1,
},
{
name: "function doesn't impact resolution",
hints: storage.SelectHints{
Range: twoMinRange,
Func: "max_over_time",
},
maxResolutionMillis: downsample.ResLevel1,
expected: downsample.ResLevel1,
},
{
name: "rate",
hints: storage.SelectHints{
Range: twoMinRange,
Func: "rate",
},
maxResolutionMillis: downsample.ResLevel1,
expected: twoMinRange / 2,
},
{
name: "rate",
hints: storage.SelectHints{
Range: twoMinRange,
Func: "rate",
},
maxResolutionMillis: downsample.ResLevel1,
expected: twoMinRange / 2,
},
{
name: "irate",
hints: storage.SelectHints{
Range: twoMinRange,
Func: "irate",
},
maxResolutionMillis: downsample.ResLevel1,
expected: twoMinRange / 2,
},
{
name: "increase",
hints: storage.SelectHints{
Range: twoMinRange,
Func: "increase",
},
maxResolutionMillis: downsample.ResLevel1,
expected: twoMinRange / 2,
},
{
name: "delta",
hints: storage.SelectHints{
Range: twoMinRange,
Func: "delta",
},
maxResolutionMillis: downsample.ResLevel1,
expected: twoMinRange / 2,
},
{
name: "idelta",
hints: storage.SelectHints{
Range: twoMinRange,
Func: "idelta",
},
maxResolutionMillis: downsample.ResLevel1,
expected: twoMinRange / 2,
},
{
name: "deriv",
hints: storage.SelectHints{
Range: twoMinRange,
Func: "deriv",
},
maxResolutionMillis: downsample.ResLevel1,
expected: twoMinRange / 2,
},
{
name: "predict_linear",
hints: storage.SelectHints{
Range: twoMinRange,
Func: "predict_linear",
},
maxResolutionMillis: downsample.ResLevel1,
expected: twoMinRange / 2,
},
{
name: "holt_winters",
hints: storage.SelectHints{
Range: twoMinRange,
Func: "holt_winters",
},
maxResolutionMillis: downsample.ResLevel1,
expected: twoMinRange / 2,
},
{
name: "double_exponential_smoothing",
hints: storage.SelectHints{
Range: twoMinRange,
Func: "double_exponential_smoothing",
},
maxResolutionMillis: downsample.ResLevel1,
expected: twoMinRange / 2,
},
} {
t.Run(tc.name, func(t *testing.T) {
res := maxResolutionFromSelectHints(tc.maxResolutionMillis, tc.hints.Range, tc.hints.Func)
testutil.Equals(t, tc.expected, res)
})
}
}

0 comments on commit 4ba7d59

Please sign in to comment.