Skip to content

Commit 4ba7d59

Browse files
authored
Infer max query downsample resolution from promql query (#7012)
* Adjust max_source_resolution automatically based promql queries Signed-off-by: Ben Ye <[email protected]> * fix data race Signed-off-by: yeya24 <[email protected]> --------- Signed-off-by: Ben Ye <[email protected]> Signed-off-by: yeya24 <[email protected]>
1 parent 4a83459 commit 4ba7d59

File tree

3 files changed

+157
-2
lines changed

3 files changed

+157
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ We use *breaking :warning:* to mark changes that are not backward compatible (re
1313
### Fixed
1414
- [#8091](https://github.com/thanos-io/thanos/pull/8091) *: Add POST into allowed CORS methods header
1515
- [#8046](https://github.com/thanos-io/thanos/pull/8046) Query-Frontend: Fix query statistic reporting for range queries when caching is enabled.
16-
1716
- [#7978](https://github.com/thanos-io/thanos/pull/7978) Receive: Fix deadlock during local writes when `split-tenant-label-name` is used
1817
- [#8016](https://github.com/thanos-io/thanos/pull/8016) Query Frontend: Fix @ modifier not being applied correctly on sub queries.
1918

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

3029
- [#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`.
30+
- [#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.
3131

3232
### Removed
3333

pkg/query/querier.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ import (
2727
"github.com/thanos-io/thanos/pkg/tracing"
2828
)
2929

30+
var promqlFuncRequiresTwoSamples = map[string]struct{}{
31+
"rate": {},
32+
"irate": {},
33+
"increase": {},
34+
"delta": {},
35+
"idelta": {},
36+
"deriv": {},
37+
"predict_linear": {},
38+
"holt_winters": {},
39+
"double_exponential_smoothing": {},
40+
}
41+
3042
type seriesStatsReporter func(seriesStats storepb.SeriesStatsCounter)
3143

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

322334
aggrs := aggrsFromFunc(hints.Func)
335+
maxResolutionMillis := maxResolutionFromSelectHints(q.maxResolutionMillis, hints.Range, hints.Func)
323336

324337
// TODO(bwplotka): Pass it using the SeriesRequest instead of relying on context.
325338
ctx = context.WithValue(ctx, store.StoreMatcherKey, q.storeDebugMatchers)
@@ -333,7 +346,7 @@ func (q *querier) selectFn(ctx context.Context, hints *storage.SelectHints, ms .
333346
MaxTime: hints.End,
334347
Limit: int64(hints.Limit),
335348
Matchers: sms,
336-
MaxResolutionWindow: q.maxResolutionMillis,
349+
MaxResolutionWindow: maxResolutionMillis,
337350
Aggregates: aggrs,
338351
ShardInfo: q.shardInfo,
339352
PartialResponseStrategy: q.partialResponseStrategy,
@@ -460,3 +473,13 @@ func (q *querier) LabelNames(ctx context.Context, hints *storage.LabelHints, mat
460473
}
461474

462475
func (q *querier) Close() error { return nil }
476+
477+
// maxResolutionFromSelectHints finds the max possible resolution by inferring from the promql query.
478+
func maxResolutionFromSelectHints(maxResolutionMillis int64, hintsRange int64, hintsFunc string) int64 {
479+
if hintsRange > 0 {
480+
if _, ok := promqlFuncRequiresTwoSamples[hintsFunc]; ok {
481+
maxResolutionMillis = min(maxResolutionMillis, hintsRange/2)
482+
}
483+
}
484+
return maxResolutionMillis
485+
}

pkg/query/querier_test.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/prometheus/prometheus/util/gate"
3333
"github.com/thanos-io/thanos/pkg/logutil"
3434

35+
"github.com/thanos-io/thanos/pkg/compact/downsample"
3536
"github.com/thanos-io/thanos/pkg/component"
3637
"github.com/thanos-io/thanos/pkg/store"
3738
"github.com/thanos-io/thanos/pkg/store/labelpb"
@@ -1279,3 +1280,134 @@ func storeSeriesResponse(t testing.TB, lset labels.Labels, smplChunks ...[]sampl
12791280
}
12801281
return storepb.NewSeriesResponse(&s)
12811282
}
1283+
1284+
func TestMaxResolutionFromSelectHints(t *testing.T) {
1285+
twoMinRange := int64(2 * 60 * 1000)
1286+
for _, tc := range []struct {
1287+
name string
1288+
maxResolutionMillis int64
1289+
hints storage.SelectHints
1290+
expected int64
1291+
}{
1292+
{
1293+
name: "no range",
1294+
hints: storage.SelectHints{
1295+
Range: 0,
1296+
},
1297+
maxResolutionMillis: downsample.ResLevel1,
1298+
expected: downsample.ResLevel1,
1299+
},
1300+
{
1301+
name: "no function",
1302+
hints: storage.SelectHints{
1303+
Range: twoMinRange,
1304+
},
1305+
maxResolutionMillis: downsample.ResLevel1,
1306+
expected: downsample.ResLevel1,
1307+
},
1308+
{
1309+
name: "function doesn't impact resolution",
1310+
hints: storage.SelectHints{
1311+
Range: twoMinRange,
1312+
Func: "max_over_time",
1313+
},
1314+
maxResolutionMillis: downsample.ResLevel1,
1315+
expected: downsample.ResLevel1,
1316+
},
1317+
{
1318+
name: "rate",
1319+
hints: storage.SelectHints{
1320+
Range: twoMinRange,
1321+
Func: "rate",
1322+
},
1323+
maxResolutionMillis: downsample.ResLevel1,
1324+
expected: twoMinRange / 2,
1325+
},
1326+
{
1327+
name: "rate",
1328+
hints: storage.SelectHints{
1329+
Range: twoMinRange,
1330+
Func: "rate",
1331+
},
1332+
maxResolutionMillis: downsample.ResLevel1,
1333+
expected: twoMinRange / 2,
1334+
},
1335+
{
1336+
name: "irate",
1337+
hints: storage.SelectHints{
1338+
Range: twoMinRange,
1339+
Func: "irate",
1340+
},
1341+
maxResolutionMillis: downsample.ResLevel1,
1342+
expected: twoMinRange / 2,
1343+
},
1344+
{
1345+
name: "increase",
1346+
hints: storage.SelectHints{
1347+
Range: twoMinRange,
1348+
Func: "increase",
1349+
},
1350+
maxResolutionMillis: downsample.ResLevel1,
1351+
expected: twoMinRange / 2,
1352+
},
1353+
{
1354+
name: "delta",
1355+
hints: storage.SelectHints{
1356+
Range: twoMinRange,
1357+
Func: "delta",
1358+
},
1359+
maxResolutionMillis: downsample.ResLevel1,
1360+
expected: twoMinRange / 2,
1361+
},
1362+
{
1363+
name: "idelta",
1364+
hints: storage.SelectHints{
1365+
Range: twoMinRange,
1366+
Func: "idelta",
1367+
},
1368+
maxResolutionMillis: downsample.ResLevel1,
1369+
expected: twoMinRange / 2,
1370+
},
1371+
{
1372+
name: "deriv",
1373+
hints: storage.SelectHints{
1374+
Range: twoMinRange,
1375+
Func: "deriv",
1376+
},
1377+
maxResolutionMillis: downsample.ResLevel1,
1378+
expected: twoMinRange / 2,
1379+
},
1380+
{
1381+
name: "predict_linear",
1382+
hints: storage.SelectHints{
1383+
Range: twoMinRange,
1384+
Func: "predict_linear",
1385+
},
1386+
maxResolutionMillis: downsample.ResLevel1,
1387+
expected: twoMinRange / 2,
1388+
},
1389+
{
1390+
name: "holt_winters",
1391+
hints: storage.SelectHints{
1392+
Range: twoMinRange,
1393+
Func: "holt_winters",
1394+
},
1395+
maxResolutionMillis: downsample.ResLevel1,
1396+
expected: twoMinRange / 2,
1397+
},
1398+
{
1399+
name: "double_exponential_smoothing",
1400+
hints: storage.SelectHints{
1401+
Range: twoMinRange,
1402+
Func: "double_exponential_smoothing",
1403+
},
1404+
maxResolutionMillis: downsample.ResLevel1,
1405+
expected: twoMinRange / 2,
1406+
},
1407+
} {
1408+
t.Run(tc.name, func(t *testing.T) {
1409+
res := maxResolutionFromSelectHints(tc.maxResolutionMillis, tc.hints.Range, tc.hints.Func)
1410+
testutil.Equals(t, tc.expected, res)
1411+
})
1412+
}
1413+
}

0 commit comments

Comments
 (0)