Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

query-frontend: correctly replace @ modifier for split queries #8162

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
* [BUGFIX] Querying: matrix results returned from instant queries were not sorted by series. #8113
* [BUGFIX] Query scheduler: Fix a crash in result marshaling. #8140
* [BUGFIX] Store-gateway: Allow long-running index scans to be interrupted. #8154
* [BUGFIX] Query-frontend: fix splitting of queries using `@ start()` and `@end()` modifiers on a subquery. Previously the `start()` and `end()` would be evaluated using the start end end of the split query instead of the original query. #8162

### Mixin

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,10 @@ func TestInstantSplitterSkippedQueryReason(t *testing.T) {
query: `max_over_time(absent_over_time(deriv(rate(metric_counter[1m])[5m:1m])[2m:])[10m:])`,
skippedReason: SkippedReasonSubquery,
},
{
query: `sum by(group_1) (sum_over_time(metric_counter[7d:] @ start()))`,
skippedReason: SkippedReasonSubquery,
},
} {
tt := tt

Expand Down
19 changes: 14 additions & 5 deletions pkg/frontend/querymiddleware/split_and_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -667,14 +667,23 @@ func evaluateAtModifierFunction(query string, start, end int64) (string, error)
return "", apierror.New(apierror.TypeBadData, decorateWithParamName(err, "query").Error())
}
parser.Inspect(expr, func(n parser.Node, _ []parser.Node) error {
if selector, ok := n.(*parser.VectorSelector); ok {
switch selector.StartOrEnd {
switch exprAt := n.(type) {
case *parser.VectorSelector:
switch exprAt.StartOrEnd {
case parser.START:
selector.Timestamp = &start
exprAt.Timestamp = &start
case parser.END:
selector.Timestamp = &end
exprAt.Timestamp = &end
}
selector.StartOrEnd = 0
exprAt.StartOrEnd = 0
case *parser.SubqueryExpr:
switch exprAt.StartOrEnd {
case parser.START:
exprAt.Timestamp = &start
case parser.END:
exprAt.Timestamp = &end
}
exprAt.StartOrEnd = 0
}
Comment on lines +670 to 687
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't find a brief generic way to write this, so the 7 lines are completely duplicated

return nil
})
Expand Down
14 changes: 14 additions & 0 deletions pkg/frontend/querymiddleware/split_and_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1620,6 +1620,10 @@ func TestSplitQueryByInterval(t *testing.T) {
queryFooAtStartExpr, _ := parser.ParseExpr(queryFooAtStart)
queryFooAtZero := "foo @ 0.000"
queryFooAtZeroExpr, _ := parser.ParseExpr(queryFooAtZero)
queryFooSubqueryAtStart := "sum_over_time(foo[1d:] @ start())"
queryFooSubqueryAtStartExpr, _ := parser.ParseExpr(queryFooSubqueryAtStart)
queryFooSubqueryAtZero := "sum_over_time(foo[1d:] @ 0.000)"
queryFooSubqueryAtZeroExpr, _ := parser.ParseExpr(queryFooSubqueryAtZero)

for i, tc := range []struct {
input MetricsQueryRequest
Expand Down Expand Up @@ -1662,6 +1666,14 @@ func TestSplitQueryByInterval(t *testing.T) {
},
interval: day,
},
{
input: &PrometheusRangeQueryRequest{minT: -(24 * 3600 * seconds), start: 0, end: 2 * 24 * 3600 * seconds, step: 15 * seconds, queryExpr: queryFooSubqueryAtStartExpr},
expected: []MetricsQueryRequest{
&PrometheusRangeQueryRequest{minT: -(24 * 3600 * seconds), start: 0, end: (24 * 3600 * seconds) - (15 * seconds), step: 15 * seconds, queryExpr: queryFooSubqueryAtZeroExpr},
&PrometheusRangeQueryRequest{minT: -(24 * 3600 * seconds), start: 24 * 3600 * seconds, end: 2 * 24 * 3600 * seconds, step: 15 * seconds, queryExpr: queryFooSubqueryAtZeroExpr},
},
interval: day,
},
{
input: &PrometheusRangeQueryRequest{start: 0, end: 2 * 3 * 3600 * seconds, step: 15 * seconds, queryExpr: queryFooExpr},
expected: []MetricsQueryRequest{
Expand Down Expand Up @@ -1797,6 +1809,8 @@ func Test_evaluateAtModifier(t *testing.T) {
{"topk(5, rate(http_requests_total[1h] @ start()))", "topk(5, rate(http_requests_total[1h] @ 1546300.800))", nil},
{"topk(5, rate(http_requests_total[1h] @ 0))", "topk(5, rate(http_requests_total[1h] @ 0.000))", nil},
{"http_requests_total[1h] @ 10.001", "http_requests_total[1h] @ 10.001", nil},
{"sum_over_time(http_requests_total[1h:] @ start())", "sum_over_time(http_requests_total[1h:] @ 1546300.800)", nil},
{"sum_over_time((http_requests_total @ end())[1h:] @ start())", "sum_over_time((http_requests_total @ 1646300.800)[1h:] @ 1546300.800)", nil},
{
`min_over_time(
sum by(cluster) (
Expand Down
Loading