diff --git a/promql/engine.go b/promql/engine.go index 83e44e61f9..fb4e65a84e 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -685,6 +685,9 @@ func durationMilliseconds(d time.Duration) int64 { func (ng *Engine) execEvalStmt(ctx context.Context, query *query, s *parser.EvalStmt) (parser.Value, annotations.Annotations, error) { prepareSpanTimer, ctxPrepare := query.stats.GetSpanTimer(ctx, stats.QueryPreparationTime, ng.metrics.queryPrepareTime) mint, maxt := FindMinMaxTime(s) + // metric[5m] + metric[5m] offset 5m + // mint -10m (-5m - 5m offset) + // maxt now() querier, err := query.queryable.Querier(mint, maxt) if err != nil { prepareSpanTimer.Finish() @@ -2171,6 +2174,15 @@ func (ev *evaluator) matrixSelector(node *parser.MatrixSelector) (Matrix, annota it = storage.NewBuffer(durationMilliseconds(node.Range)) ) + + // TODO Test for case where range of 1ms + if node.OpenLeft { + mint += 1 + } + if node.OpenRight { + maxt -= 1 + } + ws, err := checkAndExpandSeriesSet(ev.ctx, node) if err != nil { ev.error(errWithWarnings{fmt.Errorf("expanding series: %w", err), ws}) diff --git a/promql/functions.go b/promql/functions.go index 9b3be22874..fa94bf6ef9 100644 --- a/promql/functions.go +++ b/promql/functions.go @@ -73,7 +73,7 @@ func extrapolatedRate(vals []parser.Value, args parser.Expressions, enh *EvalNod var ( samples = vals[0].(Matrix)[0] rangeStart = enh.Ts - durationMilliseconds(ms.Range+vs.Offset) - rangeEnd = enh.Ts - durationMilliseconds(vs.Offset) + rangeEnd = enh.Ts - durationMilliseconds(vs.Offset) // TODO Open this in the vector selector resultFloat float64 resultHistogram *histogram.FloatHistogram firstT, lastT int64 diff --git a/promql/parser/ast.go b/promql/parser/ast.go index 830e8a2c5e..3e7e49288c 100644 --- a/promql/parser/ast.go +++ b/promql/parser/ast.go @@ -126,6 +126,9 @@ type MatrixSelector struct { VectorSelector Expr Range time.Duration + OpenLeft bool + OpenRight bool + EndPos posrange.Pos } diff --git a/promql/parser/generated_parser.y b/promql/parser/generated_parser.y index 841bd31c19..c04f32f2b8 100644 --- a/promql/parser/generated_parser.y +++ b/promql/parser/generated_parser.y @@ -28,22 +28,23 @@ import ( %} %union { - node Node - item Item - matchers []*labels.Matcher - matcher *labels.Matcher - label labels.Label - labels labels.Labels - lblList []labels.Label - strings []string - series []SequenceValue - histogram *histogram.FloatHistogram - descriptors map[string]interface{} - bucket_set []float64 - int int64 - uint uint64 - float float64 - duration time.Duration + node Node + item Item + matchers []*labels.Matcher + matcher *labels.Matcher + label labels.Label + labels labels.Labels + lblList []labels.Label + strings []string + series []SequenceValue + histogram *histogram.FloatHistogram + descriptors map[string]interface{} + bucket_set []float64 + int int64 + uint uint64 + float float64 + duration time.Duration + range_duration rangeDuration } @@ -449,7 +450,7 @@ at_modifier_preprocessors: START | END; * Subquery and range selectors. */ -matrix_selector : expr LEFT_BRACKET duration RIGHT_BRACKET +matrix_selector : expr LEFT_BRACKET range_duration RIGHT_BRACKET { var errMsg string vs, ok := $1.(*VectorSelector) @@ -468,7 +469,9 @@ matrix_selector : expr LEFT_BRACKET duration RIGHT_BRACKET $$ = &MatrixSelector{ VectorSelector: $1.(Expr), - Range: $3, + Range: $3.duration, + OpenLeft: $3.openLeft, + OpenRight: $3.openRight, EndPos: yylex.(*parser).lastClosing, } } @@ -899,6 +902,47 @@ duration : DURATION } ; +range_duration : DURATION + { + var err error + $$.duration, err = parseDuration($1.Val) + if err != nil { + yylex.(*parser).addParseErr($1.PositionRange(), err) + } + } + | POW DURATION + { + var err error + $$.duration, err = parseDuration($1.Val) + if err != nil { + yylex.(*parser).addParseErr($1.PositionRange(), err) + } + + $$.openLeft = true + } + | DURATION POW + { + var err error + $$.duration, err = parseDuration($1.Val) + if err != nil { + yylex.(*parser).addParseErr($1.PositionRange(), err) + } + + $$.openRight = true + } + | POW DURATION POW + { + var err error + $$.duration, err = parseDuration($1.Val) + if err != nil { + yylex.(*parser).addParseErr($1.PositionRange(), err) + } + + $$.openLeft = true + $$.openRight = true + } + ; + string_literal : STRING { diff --git a/promql/parser/lex.go b/promql/parser/lex.go index 4e3de2a668..cf5719c860 100644 --- a/promql/parser/lex.go +++ b/promql/parser/lex.go @@ -16,6 +16,7 @@ package parser import ( "fmt" "strings" + "time" "unicode" "unicode/utf8" @@ -1000,3 +1001,9 @@ func isLabel(s string) bool { } return true } + +type rangeDuration struct { + duration time.Duration + openLeft bool + openRight bool +}