diff --git a/docs/querying/basics.md b/docs/querying/basics.md index 8fc86bc230..1f003b1e2f 100644 --- a/docs/querying/basics.md +++ b/docs/querying/basics.md @@ -303,6 +303,17 @@ When querying for samples in the past, a negative offset will enable temporal co Note that this allows a query to look ahead of its evaluation time. +_Notes about the experimental time expressions:_ + +The offset may be a time expression in parenthesis. A time expression is +different from a normal expression in that it must yield a scalar and +must not query series. The scalar resulting from the time expression will be +used as the offset in seconds. The `time()` function can only be called outside +subqueries. For example, 5 minute offset may be calculated from adding 2 minutes +and 180 seconds together: + + http_requests_total offset (2m + 180) + ### @ modifier The `@` modifier allows changing the evaluation time for individual instant diff --git a/promql/engine.go b/promql/engine.go index a082baa261..4a7c639a70 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -128,7 +128,7 @@ func (e ErrTimeExprNotAFloat) Error() string { var ( // ErrTimeExprUsesStorage is returned if a time expression // (timestamp/duration) calculation includes vector/range selector. - ErrTimeExprUsesStorage = errors.New("time expression must not use storage") + ErrTimeExprUsesStorage = errors.New("time expression must not query for series") // ErrTimeExprDependsOnEvalTime is returned if a time expression // depends on the evaluation time, which is only allowed for the top level // time expressions. @@ -567,7 +567,7 @@ func (tev timeExprVisitor) Visit(node parser.Node, path []parser.Node) (parser.V if nl, ok := expr.(*parser.NumberLiteral); ok { return nl.Val, nil } - val, err := tev.ev.timeValueOf(expr) + val, err := tev.ev.scalarValueOf(expr) if err != nil { return 0, err } @@ -3988,14 +3988,16 @@ func (ev *evaluator) gatherVector(ts int64, input Matrix, output Vector, bufHelp return output, bufHelpers } -// timeValueOf calculates the scalar time value of an expression in float64. -func (ev *evaluator) timeValueOf(e parser.Expr) (float64, error) { +// scalarValueOf calculates the scalar value of an expression in float64. +// Use case for this is to be able to calculate offset durations, +// timestamp, range duration, etc. from scalar expressions. +func (ev *evaluator) scalarValueOf(e parser.Expr) (float64, error) { if e == nil { return 0, nil } if ev.querier != nil { - panic("evaulator does not disallow querier for time expressions") + panic("evaulator does not allow querier for time expressions") } // Shortcut for number literals. diff --git a/promql/parser/functions.go b/promql/parser/functions.go index 7de3cf5da4..b772a91dd8 100644 --- a/promql/parser/functions.go +++ b/promql/parser/functions.go @@ -26,7 +26,7 @@ type Function struct { // the current evaluation timestamp is. For example time(). EvalTimeDependent bool - // StorageDependent means that the out of the function depends on the + // StorageDependent means that the output of the function depends on the // content of TSDB at the time. For example info(). StorageDependent bool } diff --git a/promql/promqltest/testdata/duration_arithmetic.test b/promql/promqltest/testdata/duration_arithmetic.test index 28386510aa..eb6b306ad4 100644 --- a/promql/promqltest/testdata/duration_arithmetic.test +++ b/promql/promqltest/testdata/duration_arithmetic.test @@ -31,6 +31,6 @@ eval instant at 10m metric offset (5m + 1m) metric{} 4 # The time() function is allowed on top level. -# Value at 10m-(1) == 9.59 +# Value at 10m-(1) == 9m59s eval instant at 10m metric offset (time() != bool 0 + time() == bool 0) metric{} 9