mirror of
https://github.com/prometheus/prometheus.git
synced 2026-05-16 18:17:35 +02:00
Merge pull request #18684 from roidelapluie/roidelapluie/revert-duration-expr-stable
Revert "PromQL: Promote duration expressions as stable"
This commit is contained in:
commit
e793b26713
@ -260,7 +260,8 @@ func (c *flagConfig) setFeatureListOptions(logger *slog.Logger) error {
|
||||
c.parserOpts.EnableExperimentalFunctions = true
|
||||
logger.Info("Experimental PromQL functions enabled.")
|
||||
case "promql-duration-expr":
|
||||
logger.Warn("This option for --enable-feature is now permanently enabled and therefore a no-op.", "option", o)
|
||||
c.parserOpts.ExperimentalDurationExpr = true
|
||||
logger.Info("Experimental duration expression parsing enabled.")
|
||||
case "native-histograms":
|
||||
logger.Warn("This option for --enable-feature is a no-op. To scrape native histograms, set the scrape_native_histograms scrape config setting to true.", "option", o)
|
||||
case "ooo-native-histograms":
|
||||
@ -619,7 +620,7 @@ func main() {
|
||||
a.Flag("scrape.discovery-reload-interval", "Interval used by scrape manager to throttle target groups updates.").
|
||||
Hidden().Default("5s").SetValue(&cfg.scrape.DiscoveryReloadInterval)
|
||||
|
||||
a.Flag("enable-feature", "Comma separated feature names to enable. Valid options: concurrent-rule-eval, created-timestamp-zero-ingestion, delayed-compaction, exemplar-storage, extra-scrape-metrics, memory-snapshot-on-shutdown, metadata-wal-records, old-ui, otlp-deltatocumulative, otlp-native-delta-ingestion, promql-binop-fill-modifiers, promql-delayed-name-removal, promql-experimental-functions, promql-extended-range-selectors, promql-per-step-stats, st-storage, type-and-unit-labels, use-start-timestamps, use-uncached-io, xor2-encoding. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details.").
|
||||
a.Flag("enable-feature", "Comma separated feature names to enable. Valid options: concurrent-rule-eval, created-timestamp-zero-ingestion, delayed-compaction, exemplar-storage, extra-scrape-metrics, memory-snapshot-on-shutdown, metadata-wal-records, old-ui, otlp-deltatocumulative, otlp-native-delta-ingestion, promql-binop-fill-modifiers, promql-delayed-name-removal, promql-duration-expr, promql-experimental-functions, promql-extended-range-selectors, promql-per-step-stats, st-storage, type-and-unit-labels, use-start-timestamps, use-uncached-io, xor2-encoding. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details.").
|
||||
StringsVar(&cfg.featureList)
|
||||
|
||||
a.Flag("agent", "Run Prometheus in 'Agent mode'.").BoolVar(&agentMode)
|
||||
|
||||
2
cmd/prometheus/testdata/features.json
vendored
2
cmd/prometheus/testdata/features.json
vendored
@ -29,7 +29,7 @@
|
||||
"bool": true,
|
||||
"by": true,
|
||||
"delayed_name_removal": false,
|
||||
"duration_expr": true,
|
||||
"duration_expr": false,
|
||||
"fill": false,
|
||||
"fill_left": false,
|
||||
"fill_right": false,
|
||||
|
||||
@ -320,7 +320,7 @@ func main() {
|
||||
promQLLabelsDeleteQuery := promQLLabelsDeleteCmd.Arg("query", "PromQL query.").Required().String()
|
||||
promQLLabelsDeleteName := promQLLabelsDeleteCmd.Arg("name", "Name of the label to delete.").Required().String()
|
||||
|
||||
featureList := app.Flag("enable-feature", "Comma separated feature names to enable. Valid options: promql-experimental-functions, promql-delayed-name-removal, promql-extended-range-selectors. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details").Default("").Strings()
|
||||
featureList := app.Flag("enable-feature", "Comma separated feature names to enable. Valid options: promql-experimental-functions, promql-delayed-name-removal, promql-duration-expr, promql-extended-range-selectors. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details").Default("").Strings()
|
||||
|
||||
documentationCmd := app.Command("write-documentation", "Generate command line documentation. Internal use.").Hidden()
|
||||
|
||||
@ -358,7 +358,7 @@ func main() {
|
||||
case "promql-delayed-name-removal":
|
||||
promqlEnableDelayedNameRemoval = true
|
||||
case "promql-duration-expr":
|
||||
fmt.Printf(" WARNING: promql-duration-expr is now permanently enabled and therefore a no-op")
|
||||
promtoolParserOpts.ExperimentalDurationExpr = true
|
||||
case "promql-extended-range-selectors":
|
||||
promtoolParserOpts.EnableExtendedRangeSelectors = true
|
||||
case "":
|
||||
|
||||
@ -62,7 +62,7 @@ The Prometheus monitoring server
|
||||
| <code class="text-nowrap">--query.timeout</code> | Maximum time a query may take before being aborted. Use with server mode only. | `2m` |
|
||||
| <code class="text-nowrap">--query.max-concurrency</code> | Maximum number of queries executed concurrently. Use with server mode only. | `20` |
|
||||
| <code class="text-nowrap">--query.max-samples</code> | Maximum number of samples a single query can load into memory. Note that queries will fail if they try to load more samples than this into memory, so this also limits the number of samples a query can return. Use with server mode only. | `50000000` |
|
||||
| <code class="text-nowrap">--enable-feature</code> <code class="text-nowrap">...<code class="text-nowrap"> | Comma separated feature names to enable. Valid options: concurrent-rule-eval, created-timestamp-zero-ingestion, delayed-compaction, exemplar-storage, extra-scrape-metrics, memory-snapshot-on-shutdown, metadata-wal-records, old-ui, otlp-deltatocumulative, otlp-native-delta-ingestion, promql-binop-fill-modifiers, promql-delayed-name-removal, promql-experimental-functions, promql-extended-range-selectors, promql-per-step-stats, st-storage, type-and-unit-labels, use-start-timestamps, use-uncached-io, xor2-encoding. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details. | |
|
||||
| <code class="text-nowrap">--enable-feature</code> <code class="text-nowrap">...<code class="text-nowrap"> | Comma separated feature names to enable. Valid options: concurrent-rule-eval, created-timestamp-zero-ingestion, delayed-compaction, exemplar-storage, extra-scrape-metrics, memory-snapshot-on-shutdown, metadata-wal-records, old-ui, otlp-deltatocumulative, otlp-native-delta-ingestion, promql-binop-fill-modifiers, promql-delayed-name-removal, promql-duration-expr, promql-experimental-functions, promql-extended-range-selectors, promql-per-step-stats, st-storage, type-and-unit-labels, use-start-timestamps, use-uncached-io, xor2-encoding. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details. | |
|
||||
| <code class="text-nowrap">--agent</code> | Run Prometheus in 'Agent mode'. | |
|
||||
| <code class="text-nowrap">--log.level</code> | Only log messages with the given severity or above. One of: [debug, info, warn, error] | `info` |
|
||||
| <code class="text-nowrap">--log.format</code> | Output format of log messages. One of: [logfmt, json] | `logfmt` |
|
||||
|
||||
@ -12,7 +12,7 @@ Tooling for the Prometheus monitoring system.
|
||||
| <code class="text-nowrap">-h</code>, <code class="text-nowrap">--help</code> | Show context-sensitive help (also try --help-long and --help-man). |
|
||||
| <code class="text-nowrap">--version</code> | Show application version. |
|
||||
| <code class="text-nowrap">--experimental</code> | Enable experimental commands. |
|
||||
| <code class="text-nowrap">--enable-feature</code> <code class="text-nowrap">...<code class="text-nowrap"> | Comma separated feature names to enable. Valid options: promql-experimental-functions, promql-delayed-name-removal, promql-extended-range-selectors. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details |
|
||||
| <code class="text-nowrap">--enable-feature</code> <code class="text-nowrap">...<code class="text-nowrap"> | Comma separated feature names to enable. Valid options: promql-experimental-functions, promql-delayed-name-removal, promql-duration-expr, promql-extended-range-selectors. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details |
|
||||
|
||||
|
||||
|
||||
|
||||
@ -192,6 +192,63 @@ state is mutex guarded. Cumulative-only OTLP requests are not affected.
|
||||
|
||||
[d2c]: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/deltatocumulativeprocessor
|
||||
|
||||
## PromQL arithmetic expressions in time durations
|
||||
|
||||
`--enable-feature=promql-duration-expr`
|
||||
|
||||
With this flag, arithmetic expressions can be used in time durations in range queries and offset durations.
|
||||
|
||||
In range queries:
|
||||
```
|
||||
rate(http_requests_total[5m * 2]) # 10 minute range
|
||||
rate(http_requests_total[(5+2) * 1m]) # 7 minute range
|
||||
```
|
||||
|
||||
In offset durations:
|
||||
```
|
||||
http_requests_total offset (1h / 2) # 30 minute offset
|
||||
http_requests_total offset ((2 ^ 3) * 1m) # 8 minute offset
|
||||
```
|
||||
|
||||
When using offset with duration expressions, you must wrap the expression in
|
||||
parentheses. Without parentheses, only the first duration value will be used in
|
||||
the offset calculation.
|
||||
|
||||
`step()` can be used in duration expressions.
|
||||
For a **range query**, it resolves to the step width of the range query.
|
||||
For an **instant query**, it resolves to `0s`.
|
||||
|
||||
`range()` can be used in duration expressions.
|
||||
For a **range query**, it resolves to the full range of the query (end time - start time).
|
||||
For an **instant query**, it resolves to `0s`.
|
||||
This is particularly useful in combination with `@end()` to look back over the entire query range, e.g., `max_over_time(metric[range()] @ end())`.
|
||||
|
||||
`min(<duration>, <duration>)` and `max(<duration>, <duration>)` can be used to find the minimum or maximum of two duration expressions.
|
||||
|
||||
**Note**: Duration expressions are not supported in the @ timestamp operator.
|
||||
|
||||
The following operators are supported:
|
||||
|
||||
* `+` - addition
|
||||
* `-` - subtraction
|
||||
* `*` - multiplication
|
||||
* `/` - division
|
||||
* `%` - modulo
|
||||
* `^` - exponentiation
|
||||
|
||||
Examples of equivalent durations:
|
||||
|
||||
* `5m * 2` is equivalent to `10m` or `600s`
|
||||
* `10m - 1m` is equivalent to `9m` or `540s`
|
||||
* `(5+2) * 1m` is equivalent to `7m` or `420s`
|
||||
* `1h / 2` is equivalent to `30m` or `1800s`
|
||||
* `4h % 3h` is equivalent to `1h` or `3600s`
|
||||
* `(2 ^ 3) * 1m` is equivalent to `8m` or `480s`
|
||||
* `step() + 1` is equivalent to the query step width increased by 1s.
|
||||
* `max(step(), 5s)` is equivalent to the larger of the query step width and `5s`.
|
||||
* `min(2 * step() + 5s, 5m)` is equivalent to the smaller of twice the query step increased by `5s` and `5m`.
|
||||
|
||||
|
||||
## OTLP Native Delta Support
|
||||
|
||||
`--enable-feature=otlp-native-delta-ingestion`
|
||||
|
||||
@ -174,57 +174,6 @@ Examples:
|
||||
12h34m56s # Equivalent to 45296s and thus 45296.
|
||||
54s321ms # Equivalent to 54.321.
|
||||
|
||||
#### Duration expressions
|
||||
|
||||
Duration expressions can be used in range selectors, subquery range and
|
||||
resolution fields, and offset durations.
|
||||
|
||||
Examples:
|
||||
|
||||
rate(http_requests_total[5m * 2]) # 10 minute range.
|
||||
rate(http_requests_total[(5 + 2) * 1m]) # 7 minute range.
|
||||
http_requests_total offset (1h / 2) # 30 minute offset.
|
||||
http_requests_total offset ((2 ^ 3) * 1m) # 8 minute offset.
|
||||
|
||||
When using offset with duration expressions, you must wrap the expression in
|
||||
parentheses. Without parentheses, only the first duration value will be used in
|
||||
the offset calculation.
|
||||
|
||||
`step()` can be used in duration expressions. For a range query, it resolves to
|
||||
the step width of the range query. For an instant query, it resolves to `0s`.
|
||||
|
||||
`range()` can be used in duration expressions. For a range query, it resolves to
|
||||
the full range of the query (end time minus start time). For an instant query,
|
||||
it resolves to `0s`. This is particularly useful in combination with `@ end()`
|
||||
to look back over the entire query range, e.g.,
|
||||
`max_over_time(metric[range()] @ end())`.
|
||||
|
||||
`min(<duration>, <duration>)` and `max(<duration>, <duration>)` can be used to
|
||||
find the minimum or maximum of two duration expressions.
|
||||
|
||||
Duration expressions are not supported in the @ timestamp operator.
|
||||
|
||||
The following operators are supported:
|
||||
|
||||
* `+` - addition.
|
||||
* `-` - subtraction.
|
||||
* `*` - multiplication.
|
||||
* `/` - division.
|
||||
* `%` - modulo.
|
||||
* `^` - exponentiation.
|
||||
|
||||
Examples of equivalent durations:
|
||||
|
||||
* `5m * 2` is equivalent to `10m` or `600s`.
|
||||
* `10m - 1m` is equivalent to `9m` or `540s`.
|
||||
* `(5 + 2) * 1m` is equivalent to `7m` or `420s`.
|
||||
* `1h / 2` is equivalent to `30m` or `1800s`.
|
||||
* `4h % 3h` is equivalent to `1h` or `3600s`.
|
||||
* `(2 ^ 3) * 1m` is equivalent to `8m` or `480s`.
|
||||
* `step() + 1` is equivalent to the query step width increased by 1s.
|
||||
* `max(step(), 5s)` is equivalent to the larger of the query step width and `5s`.
|
||||
* `min(2 * step() + 5s, 5m)` is equivalent to the smaller of twice the query step increased by `5s` and `5m`.
|
||||
|
||||
## Time series selectors
|
||||
|
||||
These are the basic building-blocks that instruct PromQL what data to fetch.
|
||||
@ -333,13 +282,14 @@ A workaround for this restriction is to use the `__name__` label:
|
||||
|
||||
Range vector literals work like instant vector literals, except that they
|
||||
select a range of samples back from the current instant. Syntactically, a
|
||||
[duration](#float-literals-and-time-durations) is appended in square brackets
|
||||
(`[]`) at the end of a vector selector to specify how far back in time values
|
||||
should be fetched for each resulting range vector element. Commonly, this uses
|
||||
one or more time units, e.g. `[5m]`. The range is a left-open and right-closed
|
||||
interval, i.e. samples with timestamps coinciding with the left boundary of the
|
||||
range are excluded from the selection, while samples coinciding with the right
|
||||
boundary of the range are included in the selection.
|
||||
[float literal](#float-literals-and-time-durations) is appended in square
|
||||
brackets (`[]`) at the end of a vector selector to specify for how many seconds
|
||||
back in time values should be fetched for each resulting range vector element.
|
||||
Commonly, the float literal uses the syntax with one or more time units, e.g.
|
||||
`[5m]`. The range is a left-open and right-closed interval, i.e. samples with
|
||||
timestamps coinciding with the left boundary of the range are excluded from the
|
||||
selection, while samples coinciding with the right boundary of the range are
|
||||
included in the selection.
|
||||
|
||||
In this example, we select all the values recorded less than 5m ago for all
|
||||
time series that have the metric name `http_requests_total` and a `job` label
|
||||
@ -429,9 +379,8 @@ Note that the `@` modifier allows a query to look ahead of its evaluation time.
|
||||
|
||||
Subquery allows you to run an instant query for a given range and resolution. The result of a subquery is a range vector.
|
||||
|
||||
Syntax: `<instant_query> '[' <range> ':' [<resolution>] ']' [ @ <float_literal> ] [ offset <duration> ]`
|
||||
Syntax: `<instant_query> '[' <range> ':' [<resolution>] ']' [ @ <float_literal> ] [ offset <float_literal> ]`
|
||||
|
||||
* `<range>`, `<resolution>`, and `offset` support duration expressions.
|
||||
* `<resolution>` is optional. Default is the global evaluation interval.
|
||||
|
||||
## Operators
|
||||
|
||||
@ -961,7 +961,8 @@ These functions act on histograms in the following way:
|
||||
select the first sample of `m` _within_ the 1m range, where `m offset 1m` will
|
||||
select the most recent sample within the lookback interval _outside and prior
|
||||
to_ the 1m offset. This is particularly useful with `first_over_time(m[step()])`
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when `--enable-feature=promql-duration-expr` is set)
|
||||
to ensure that the sample selected is within the range step.
|
||||
|
||||
## Trigonometric Functions
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
func TestDurationVisitor(t *testing.T) {
|
||||
p := parser.NewParser(parser.Options{})
|
||||
p := parser.NewParser(parser.Options{ExperimentalDurationExpr: true})
|
||||
complexExpr := `sum_over_time(
|
||||
rate(metric[5m] offset 1h)[10m:30s] offset 2h
|
||||
) +
|
||||
|
||||
@ -53,6 +53,6 @@ func (pql *promQLParser) RegisterFeatures(r features.Collector) {
|
||||
r.Set(features.PromQLFunctions, f, !fc.Experimental || pql.options.EnableExperimentalFunctions)
|
||||
}
|
||||
|
||||
// Register parser features.
|
||||
r.Enable(features.PromQL, "duration_expr")
|
||||
// Register experimental parser features.
|
||||
r.Set(features.PromQL, "duration_expr", pql.options.ExperimentalDurationExpr)
|
||||
}
|
||||
|
||||
@ -1201,23 +1201,27 @@ offset_duration_expr : number_duration_literal
|
||||
}
|
||||
| STEP LEFT_PAREN RIGHT_PAREN
|
||||
{
|
||||
$$ = &DurationExpr{
|
||||
Op: STEP,
|
||||
de := &DurationExpr{
|
||||
Op: STEP,
|
||||
StartPos: $1.PositionRange().Start,
|
||||
EndPos: $3.PositionRange().End,
|
||||
EndPos: $3.PositionRange().End,
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
$$ = de
|
||||
}
|
||||
| RANGE LEFT_PAREN RIGHT_PAREN
|
||||
{
|
||||
$$ = &DurationExpr{
|
||||
Op: RANGE,
|
||||
de := &DurationExpr{
|
||||
Op: RANGE,
|
||||
StartPos: $1.PositionRange().Start,
|
||||
EndPos: $3.PositionRange().End,
|
||||
EndPos: $3.PositionRange().End,
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
$$ = de
|
||||
}
|
||||
| unary_op STEP LEFT_PAREN RIGHT_PAREN
|
||||
{
|
||||
$$ = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: $1.Typ,
|
||||
RHS: &DurationExpr{
|
||||
Op: STEP,
|
||||
@ -1226,10 +1230,12 @@ offset_duration_expr : number_duration_literal
|
||||
},
|
||||
StartPos: $1.Pos,
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
$$ = de
|
||||
}
|
||||
| unary_op RANGE LEFT_PAREN RIGHT_PAREN
|
||||
{
|
||||
$$ = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: $1.Typ,
|
||||
RHS: &DurationExpr{
|
||||
Op: RANGE,
|
||||
@ -1238,20 +1244,24 @@ offset_duration_expr : number_duration_literal
|
||||
},
|
||||
StartPos: $1.Pos,
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
$$ = de
|
||||
}
|
||||
| min_max LEFT_PAREN duration_expr COMMA duration_expr RIGHT_PAREN
|
||||
{
|
||||
$$ = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: $1.Typ,
|
||||
StartPos: $1.PositionRange().Start,
|
||||
EndPos: $6.PositionRange().End,
|
||||
LHS: $3.(Expr),
|
||||
RHS: $5.(Expr),
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
$$ = de
|
||||
}
|
||||
| unary_op min_max LEFT_PAREN duration_expr COMMA duration_expr RIGHT_PAREN
|
||||
{
|
||||
$$ = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: $1.Typ,
|
||||
StartPos: $1.Pos,
|
||||
EndPos: $6.PositionRange().End,
|
||||
@ -1263,6 +1273,8 @@ offset_duration_expr : number_duration_literal
|
||||
RHS: $6.(Expr),
|
||||
},
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
$$ = de
|
||||
}
|
||||
| unary_op LEFT_PAREN duration_expr RIGHT_PAREN %prec MUL
|
||||
{
|
||||
@ -1327,18 +1339,22 @@ duration_expr : number_duration_literal
|
||||
}
|
||||
| duration_expr ADD duration_expr
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr($1.(Expr))
|
||||
$$ = &DurationExpr{Op: ADD, LHS: $1.(Expr), RHS: $3.(Expr)}
|
||||
}
|
||||
| duration_expr SUB duration_expr
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr($1.(Expr))
|
||||
$$ = &DurationExpr{Op: SUB, LHS: $1.(Expr), RHS: $3.(Expr)}
|
||||
}
|
||||
| duration_expr MUL duration_expr
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr($1.(Expr))
|
||||
$$ = &DurationExpr{Op: MUL, LHS: $1.(Expr), RHS: $3.(Expr)}
|
||||
}
|
||||
| duration_expr DIV duration_expr
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr($1.(Expr))
|
||||
if nl, ok := $3.(*NumberLiteral); ok && nl.Val == 0 {
|
||||
yylex.(*parser).addParseErrf($2.PositionRange(), "division by zero")
|
||||
$$ = &NumberLiteral{Val: 0}
|
||||
@ -1348,6 +1364,7 @@ duration_expr : number_duration_literal
|
||||
}
|
||||
| duration_expr MOD duration_expr
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr($1.(Expr))
|
||||
if nl, ok := $3.(*NumberLiteral); ok && nl.Val == 0 {
|
||||
yylex.(*parser).addParseErrf($2.PositionRange(), "modulo by zero")
|
||||
$$ = &NumberLiteral{Val: 0}
|
||||
@ -1357,39 +1374,47 @@ duration_expr : number_duration_literal
|
||||
}
|
||||
| duration_expr POW duration_expr
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr($1.(Expr))
|
||||
$$ = &DurationExpr{Op: POW, LHS: $1.(Expr), RHS: $3.(Expr)}
|
||||
}
|
||||
| STEP LEFT_PAREN RIGHT_PAREN
|
||||
{
|
||||
$$ = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: STEP,
|
||||
StartPos: $1.PositionRange().Start,
|
||||
EndPos: $3.PositionRange().End,
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
$$ = de
|
||||
}
|
||||
| RANGE LEFT_PAREN RIGHT_PAREN
|
||||
{
|
||||
$$ = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: RANGE,
|
||||
StartPos: $1.PositionRange().Start,
|
||||
EndPos: $3.PositionRange().End,
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
$$ = de
|
||||
}
|
||||
| min_max LEFT_PAREN duration_expr COMMA duration_expr RIGHT_PAREN
|
||||
{
|
||||
$$ = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: $1.Typ,
|
||||
StartPos: $1.PositionRange().Start,
|
||||
EndPos: $6.PositionRange().End,
|
||||
LHS: $3.(Expr),
|
||||
RHS: $5.(Expr),
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
$$ = de
|
||||
}
|
||||
| paren_duration_expr
|
||||
;
|
||||
|
||||
paren_duration_expr : LEFT_PAREN duration_expr RIGHT_PAREN
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr($2.(Expr))
|
||||
if durationExpr, ok := $2.(*DurationExpr); ok {
|
||||
durationExpr.Wrapped = true
|
||||
$$ = durationExpr
|
||||
|
||||
@ -2316,25 +2316,29 @@ yydefault:
|
||||
case 282:
|
||||
yyDollar = yyS[yypt-3 : yypt+1]
|
||||
{
|
||||
yyVAL.node = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: STEP,
|
||||
StartPos: yyDollar[1].item.PositionRange().Start,
|
||||
EndPos: yyDollar[3].item.PositionRange().End,
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
yyVAL.node = de
|
||||
}
|
||||
case 283:
|
||||
yyDollar = yyS[yypt-3 : yypt+1]
|
||||
{
|
||||
yyVAL.node = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: RANGE,
|
||||
StartPos: yyDollar[1].item.PositionRange().Start,
|
||||
EndPos: yyDollar[3].item.PositionRange().End,
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
yyVAL.node = de
|
||||
}
|
||||
case 284:
|
||||
yyDollar = yyS[yypt-4 : yypt+1]
|
||||
{
|
||||
yyVAL.node = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: yyDollar[1].item.Typ,
|
||||
RHS: &DurationExpr{
|
||||
Op: STEP,
|
||||
@ -2343,11 +2347,13 @@ yydefault:
|
||||
},
|
||||
StartPos: yyDollar[1].item.Pos,
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
yyVAL.node = de
|
||||
}
|
||||
case 285:
|
||||
yyDollar = yyS[yypt-4 : yypt+1]
|
||||
{
|
||||
yyVAL.node = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: yyDollar[1].item.Typ,
|
||||
RHS: &DurationExpr{
|
||||
Op: RANGE,
|
||||
@ -2356,22 +2362,26 @@ yydefault:
|
||||
},
|
||||
StartPos: yyDollar[1].item.Pos,
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
yyVAL.node = de
|
||||
}
|
||||
case 286:
|
||||
yyDollar = yyS[yypt-6 : yypt+1]
|
||||
{
|
||||
yyVAL.node = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: yyDollar[1].item.Typ,
|
||||
StartPos: yyDollar[1].item.PositionRange().Start,
|
||||
EndPos: yyDollar[6].item.PositionRange().End,
|
||||
LHS: yyDollar[3].node.(Expr),
|
||||
RHS: yyDollar[5].node.(Expr),
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
yyVAL.node = de
|
||||
}
|
||||
case 287:
|
||||
yyDollar = yyS[yypt-7 : yypt+1]
|
||||
{
|
||||
yyVAL.node = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: yyDollar[1].item.Typ,
|
||||
StartPos: yyDollar[1].item.Pos,
|
||||
EndPos: yyDollar[6].node.PositionRange().End,
|
||||
@ -2383,6 +2393,8 @@ yydefault:
|
||||
RHS: yyDollar[6].node.(Expr),
|
||||
},
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
yyVAL.node = de
|
||||
}
|
||||
case 288:
|
||||
yyDollar = yyS[yypt-4 : yypt+1]
|
||||
@ -2446,21 +2458,25 @@ yydefault:
|
||||
case 294:
|
||||
yyDollar = yyS[yypt-3 : yypt+1]
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr(yyDollar[1].node.(Expr))
|
||||
yyVAL.node = &DurationExpr{Op: ADD, LHS: yyDollar[1].node.(Expr), RHS: yyDollar[3].node.(Expr)}
|
||||
}
|
||||
case 295:
|
||||
yyDollar = yyS[yypt-3 : yypt+1]
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr(yyDollar[1].node.(Expr))
|
||||
yyVAL.node = &DurationExpr{Op: SUB, LHS: yyDollar[1].node.(Expr), RHS: yyDollar[3].node.(Expr)}
|
||||
}
|
||||
case 296:
|
||||
yyDollar = yyS[yypt-3 : yypt+1]
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr(yyDollar[1].node.(Expr))
|
||||
yyVAL.node = &DurationExpr{Op: MUL, LHS: yyDollar[1].node.(Expr), RHS: yyDollar[3].node.(Expr)}
|
||||
}
|
||||
case 297:
|
||||
yyDollar = yyS[yypt-3 : yypt+1]
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr(yyDollar[1].node.(Expr))
|
||||
if nl, ok := yyDollar[3].node.(*NumberLiteral); ok && nl.Val == 0 {
|
||||
yylex.(*parser).addParseErrf(yyDollar[2].item.PositionRange(), "division by zero")
|
||||
yyVAL.node = &NumberLiteral{Val: 0}
|
||||
@ -2471,6 +2487,7 @@ yydefault:
|
||||
case 298:
|
||||
yyDollar = yyS[yypt-3 : yypt+1]
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr(yyDollar[1].node.(Expr))
|
||||
if nl, ok := yyDollar[3].node.(*NumberLiteral); ok && nl.Val == 0 {
|
||||
yylex.(*parser).addParseErrf(yyDollar[2].item.PositionRange(), "modulo by zero")
|
||||
yyVAL.node = &NumberLiteral{Val: 0}
|
||||
@ -2481,40 +2498,48 @@ yydefault:
|
||||
case 299:
|
||||
yyDollar = yyS[yypt-3 : yypt+1]
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr(yyDollar[1].node.(Expr))
|
||||
yyVAL.node = &DurationExpr{Op: POW, LHS: yyDollar[1].node.(Expr), RHS: yyDollar[3].node.(Expr)}
|
||||
}
|
||||
case 300:
|
||||
yyDollar = yyS[yypt-3 : yypt+1]
|
||||
{
|
||||
yyVAL.node = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: STEP,
|
||||
StartPos: yyDollar[1].item.PositionRange().Start,
|
||||
EndPos: yyDollar[3].item.PositionRange().End,
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
yyVAL.node = de
|
||||
}
|
||||
case 301:
|
||||
yyDollar = yyS[yypt-3 : yypt+1]
|
||||
{
|
||||
yyVAL.node = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: RANGE,
|
||||
StartPos: yyDollar[1].item.PositionRange().Start,
|
||||
EndPos: yyDollar[3].item.PositionRange().End,
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
yyVAL.node = de
|
||||
}
|
||||
case 302:
|
||||
yyDollar = yyS[yypt-6 : yypt+1]
|
||||
{
|
||||
yyVAL.node = &DurationExpr{
|
||||
de := &DurationExpr{
|
||||
Op: yyDollar[1].item.Typ,
|
||||
StartPos: yyDollar[1].item.PositionRange().Start,
|
||||
EndPos: yyDollar[6].item.PositionRange().End,
|
||||
LHS: yyDollar[3].node.(Expr),
|
||||
RHS: yyDollar[5].node.(Expr),
|
||||
}
|
||||
yylex.(*parser).experimentalDurationExpr(de)
|
||||
yyVAL.node = de
|
||||
}
|
||||
case 304:
|
||||
yyDollar = yyS[yypt-3 : yypt+1]
|
||||
{
|
||||
yylex.(*parser).experimentalDurationExpr(yyDollar[2].node.(Expr))
|
||||
if durationExpr, ok := yyDollar[2].node.(*DurationExpr); ok {
|
||||
durationExpr.Wrapped = true
|
||||
yyVAL.node = durationExpr
|
||||
|
||||
@ -43,6 +43,7 @@ var parserPool = sync.Pool{
|
||||
// Options holds the configuration for the PromQL parser.
|
||||
type Options struct {
|
||||
EnableExperimentalFunctions bool
|
||||
ExperimentalDurationExpr bool
|
||||
EnableExtendedRangeSelectors bool
|
||||
EnableBinopFillModifiers bool
|
||||
}
|
||||
@ -1192,6 +1193,12 @@ func (p *parser) getAtModifierVars(e Node) (**int64, *ItemType, *posrange.Pos, b
|
||||
return timestampp, preprocp, endPosp, true
|
||||
}
|
||||
|
||||
func (p *parser) experimentalDurationExpr(e Expr) {
|
||||
if !p.options.ExperimentalDurationExpr {
|
||||
p.addParseErrf(e.PositionRange(), "experimental duration expression is not enabled")
|
||||
}
|
||||
}
|
||||
|
||||
func MustLabelMatcher(mt labels.MatchType, name, val string) *labels.Matcher {
|
||||
m, err := labels.NewMatcher(mt, name, val)
|
||||
if err != nil {
|
||||
|
||||
@ -5327,6 +5327,7 @@ func readable(s string) string {
|
||||
func TestParseExpressions(t *testing.T) {
|
||||
optsParser := NewParser(Options{
|
||||
EnableExperimentalFunctions: true,
|
||||
ExperimentalDurationExpr: true,
|
||||
})
|
||||
|
||||
for _, test := range testExpr {
|
||||
@ -6083,6 +6084,7 @@ func TestParseCustomFunctions(t *testing.T) {
|
||||
func TestNewParser(t *testing.T) {
|
||||
p := NewParser(Options{
|
||||
EnableExperimentalFunctions: true,
|
||||
ExperimentalDurationExpr: true,
|
||||
})
|
||||
|
||||
// ParseExpr should work.
|
||||
|
||||
@ -670,7 +670,7 @@ func TestUnaryPretty(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDurationExprPretty(t *testing.T) {
|
||||
optsParser := NewParser(Options{})
|
||||
optsParser := NewParser(Options{ExperimentalDurationExpr: true})
|
||||
maxCharactersPerLine = 10
|
||||
inputs := []struct {
|
||||
in, out string
|
||||
|
||||
@ -23,6 +23,7 @@ import (
|
||||
|
||||
func TestExprString(t *testing.T) {
|
||||
optsParser := NewParser(Options{
|
||||
ExperimentalDurationExpr: true,
|
||||
EnableExtendedRangeSelectors: true,
|
||||
EnableBinopFillModifiers: true,
|
||||
})
|
||||
|
||||
@ -90,6 +90,7 @@ func LoadedStorage(t testing.TB, input string) *teststorage.TestStorage {
|
||||
// TestParserOpts are the parser options used for all built-in test engines.
|
||||
var TestParserOpts = parser.Options{
|
||||
EnableExperimentalFunctions: true,
|
||||
ExperimentalDurationExpr: true,
|
||||
EnableExtendedRangeSelectors: true,
|
||||
EnableBinopFillModifiers: true,
|
||||
}
|
||||
|
||||
@ -363,6 +363,7 @@ func FuzzParseExpr(f *testing.F) {
|
||||
|
||||
p := parser.NewParser(parser.Options{
|
||||
EnableExperimentalFunctions: true,
|
||||
ExperimentalDurationExpr: true,
|
||||
EnableExtendedRangeSelectors: true,
|
||||
EnableBinopFillModifiers: true,
|
||||
})
|
||||
|
||||
@ -22,7 +22,7 @@ import (
|
||||
)
|
||||
|
||||
func TestTranslateASTDurationExpressions(t *testing.T) {
|
||||
p := parser.NewParser(parser.Options{})
|
||||
p := parser.NewParser(parser.Options{ExperimentalDurationExpr: true})
|
||||
|
||||
type tc struct {
|
||||
name string
|
||||
|
||||
@ -589,7 +589,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -908,7 +909,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -1238,7 +1240,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -2069,7 +2072,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -2219,7 +2223,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -2328,7 +2333,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -2437,7 +2443,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -2652,7 +2659,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -2761,7 +2769,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -3274,7 +3283,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -3383,7 +3393,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -3508,7 +3519,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -3773,7 +3785,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -3882,7 +3895,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -3991,7 +4005,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
@ -4100,7 +4115,8 @@ const funcDocs: Record<string, React.ReactNode> = {
|
||||
first sample of <code>m</code> <em>within</em> the 1m range, where <code>m offset 1m</code> will select the most
|
||||
recent sample within the lookback interval <em>outside and prior to</em> the 1m offset. This is particularly
|
||||
useful with <code>first_over_time(m[step()])</code>
|
||||
in range queries to ensure that the sample selected is within the range step.
|
||||
in range queries (available when <code>--enable-feature=promql-duration-expr</code> is set) to ensure that the
|
||||
sample selected is within the range step.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user