From 5bd0d00f8ca1ec808015b30f30b3cf1dba656518 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Linas=20Med=C5=BEi=C5=ABnas?=
Date: Wed, 18 Feb 2026 18:32:29 +0200
Subject: [PATCH] PromQL: Add experimental histogram_quantiles variadic
function (#17285)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Linas Medziunas
Signed-off-by: Björn Rabenstein
Signed-off-by: beorn7
Co-authored-by: Björn Rabenstein
Co-authored-by: beorn7
---
cmd/prometheus/testdata/features.json | 1 +
docs/querying/functions.md | 17 ++++
promql/engine.go | 34 ++++++-
promql/functions.go | 88 ++++++++++++++++++-
promql/parser/functions.go | 7 ++
promql/promqltest/testdata/histograms.test | 86 +++++++++++++++++-
.../testdata/native_histograms.test | 15 ++++
web/ui/mantine-ui/src/promql/functionDocs.tsx | 27 ++++++
.../src/promql/functionSignatures.ts | 6 ++
.../src/complete/promql.terms.ts | 6 ++
.../codemirror-promql/src/types/function.ts | 7 ++
web/ui/module/lezer-promql/src/promql.grammar | 2 +
12 files changed, 292 insertions(+), 4 deletions(-)
diff --git a/cmd/prometheus/testdata/features.json b/cmd/prometheus/testdata/features.json
index c39f60ab33..5fc01aa195 100644
--- a/cmd/prometheus/testdata/features.json
+++ b/cmd/prometheus/testdata/features.json
@@ -80,6 +80,7 @@
"histogram_count": true,
"histogram_fraction": true,
"histogram_quantile": true,
+ "histogram_quantiles": false,
"histogram_stddev": true,
"histogram_stdvar": true,
"histogram_sum": true,
diff --git a/docs/querying/functions.md b/docs/querying/functions.md
index 3a9b7025f8..68a003359d 100644
--- a/docs/querying/functions.md
+++ b/docs/querying/functions.md
@@ -433,6 +433,23 @@ and is therefore flagged by an info-level annotation reading `input to
histogram_quantile needed to be fixed for monotonicity`. If you encounter this
annotation, you should find and remove the source of the invalid data.
+## `histogram_quantiles()`
+
+**This function has to be enabled via the [feature
+flag](../feature_flags.md#experimental-promql-functions)
+`--enable-feature=promql-experimental-functions`.**
+
+`histogram_quantiles(v instant-vector, quantile_label string, φ_1 scalar, φ_2 scalar, ...)` calculates multiple (between 1 and 10) φ-quantiles (0 ≤
+φ ≤ 1) from a [classic
+histogram](https://prometheus.io/docs/concepts/metric_types/#histogram) or from
+a native histogram. Quantile calculation works the same way as in `histogram_quantile()`.
+The second argument (a string) specifies the label name that is used to identify different quantiles in the query result.
+```
+histogram_quantiles(sum(rate(foo[1m])), "quantile", 0.9, 0.99)
+# => {quantile="0.9"} 123
+ {quantile="0.99"} 128
+```
+
## `histogram_stddev()` and `histogram_stdvar()`
`histogram_stddev(v instant-vector)` returns the estimated standard deviation
diff --git a/promql/engine.go b/promql/engine.go
index eb41e40605..bd7b868d86 100644
--- a/promql/engine.go
+++ b/promql/engine.go
@@ -1214,6 +1214,9 @@ type EvalNodeHelper struct {
// funcHistogramQuantile and funcHistogramFraction for classic histograms.
signatureToMetricWithBuckets map[string]*metricWithBuckets
nativeHistogramSamples []Sample
+ // funcHistogramQuantiles for histograms.
+ quantileStrs map[float64]string
+ signatureToLabelsWithQuantile map[string]map[float64]labels.Labels
lb *labels.Builder
lblBuf []byte
@@ -1305,6 +1308,35 @@ func (enh *EvalNodeHelper) resetHistograms(inVec Vector, arg parser.Expr) annota
return annos
}
+func (enh *EvalNodeHelper) getOrCreateLblsWithQuantile(lbls labels.Labels, quantileLabel string, q float64) labels.Labels {
+ if enh.signatureToLabelsWithQuantile == nil {
+ enh.signatureToLabelsWithQuantile = make(map[string]map[float64]labels.Labels)
+ }
+
+ enh.lblBuf = lbls.Bytes(enh.lblBuf)
+ cachedLbls, ok := enh.signatureToLabelsWithQuantile[string(enh.lblBuf)]
+ if !ok {
+ cachedLbls = make(map[float64]labels.Labels, len(enh.quantileStrs))
+ enh.signatureToLabelsWithQuantile[string(enh.lblBuf)] = cachedLbls
+ }
+
+ cachedLblsWithQuantile, ok := cachedLbls[q]
+ if !ok {
+ quantileStr := "NaN"
+ if !math.IsNaN(q) {
+ // Cannot do map lookup by NaN key.
+ quantileStr = enh.quantileStrs[q]
+ }
+ cachedLblsWithQuantile = labels.NewBuilder(lbls).
+ Set(quantileLabel, quantileStr).
+ Labels()
+
+ cachedLbls[q] = cachedLblsWithQuantile
+ }
+
+ return cachedLblsWithQuantile
+}
+
// rangeEval evaluates the given expressions, and then for each step calls
// the given funcCall with the values computed for each expression at that
// step. The return value is the combination into time series of all the
@@ -4320,7 +4352,7 @@ func detectHistogramStatsDecoding(expr parser.Expr) {
// further up (the latter wouldn't make sense,
// but no harm in detecting it).
n.SkipHistogramBuckets = true
- case "histogram_quantile", "histogram_fraction":
+ case "histogram_quantile", "histogram_quantiles", "histogram_fraction":
// If we ever see a function that needs the
// whole histogram, we will not skip the
// buckets.
diff --git a/promql/functions.go b/promql/functions.go
index 2cb90a9b6c..546f94df12 100644
--- a/promql/functions.go
+++ b/promql/functions.go
@@ -1720,8 +1720,8 @@ func funcHistogramQuantile(vectorVals []Vector, _ Matrix, args parser.Expression
inVec := vectorVals[1]
var annos annotations.Annotations
- if math.IsNaN(q) || q < 0 || q > 1 {
- annos.Add(annotations.NewInvalidQuantileWarning(q, args[0].PositionRange()))
+ if err := validateQuantile(q, args[0]); err != nil {
+ annos.Add(err)
}
annos.Merge(enh.resetHistograms(inVec, args[1]))
@@ -1770,6 +1770,89 @@ func funcHistogramQuantile(vectorVals []Vector, _ Matrix, args parser.Expression
return enh.Out, annos
}
+func validateQuantile(q float64, arg parser.Expr) error {
+ if math.IsNaN(q) || q < 0 || q > 1 {
+ return annotations.NewInvalidQuantileWarning(q, arg.PositionRange())
+ }
+ return nil
+}
+
+// === histogram_quantiles(Vector parser.ValueTypeVector, label parser.ValueTypeString, q0 parser.ValueTypeScalar, qs parser.ValueTypeScalar...) (Vector, Annotations) ===
+func funcHistogramQuantiles(vectorVals []Vector, _ Matrix, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
+ var (
+ inVec = vectorVals[0]
+ quantileLabel = args[1].(*parser.StringLiteral).Val
+ numQuantiles = len(vectorVals[2:])
+ qs = make([]float64, 0, numQuantiles)
+
+ annos annotations.Annotations
+ )
+
+ if enh.quantileStrs == nil {
+ enh.quantileStrs = make(map[float64]string, numQuantiles)
+ }
+ for i := 2; i < len(vectorVals); i++ {
+ q := vectorVals[i][0].F
+
+ if err := validateQuantile(q, args[i]); err != nil {
+ annos.Add(err)
+ }
+
+ if _, ok := enh.quantileStrs[q]; !ok {
+ enh.quantileStrs[q] = labels.FormatOpenMetricsFloat(q)
+ }
+ qs = append(qs, q)
+ }
+
+ annos.Merge(enh.resetHistograms(inVec, args[0]))
+
+ for _, q := range qs {
+ // Deal with the native histograms.
+ for _, sample := range enh.nativeHistogramSamples {
+ if sample.H == nil {
+ // Native histogram conflicts with classic histogram at the same timestamp, ignore.
+ continue
+ }
+ if !enh.enableDelayedNameRemoval {
+ sample.Metric = sample.Metric.DropReserved(schema.IsMetadataLabel)
+ }
+ hq, hqAnnos := HistogramQuantile(q, sample.H, sample.Metric.Get(model.MetricNameLabel), args[0].PositionRange())
+ annos.Merge(hqAnnos)
+ enh.Out = append(enh.Out, Sample{
+ Metric: enh.getOrCreateLblsWithQuantile(sample.Metric, quantileLabel, q),
+ F: hq,
+ DropName: true,
+ })
+ }
+
+ // Deal with classic histograms that have already been filtered for conflicting native histograms.
+ for _, mb := range enh.signatureToMetricWithBuckets {
+ if len(mb.buckets) > 0 {
+ hq, forcedMonotonicity, _, minBucket, maxBucket, maxDiff := BucketQuantile(q, mb.buckets)
+ if forcedMonotonicity {
+ metricName := ""
+ if enh.enableDelayedNameRemoval {
+ metricName = getMetricName(mb.metric)
+ }
+ annos.Add(annotations.NewHistogramQuantileForcedMonotonicityInfo(metricName, args[1].PositionRange(), enh.Ts, minBucket, maxBucket, maxDiff))
+ }
+
+ if !enh.enableDelayedNameRemoval {
+ mb.metric = mb.metric.DropReserved(schema.IsMetadataLabel)
+ }
+
+ enh.Out = append(enh.Out, Sample{
+ Metric: enh.getOrCreateLblsWithQuantile(mb.metric, quantileLabel, q),
+ F: hq,
+ DropName: true,
+ })
+ }
+ }
+ }
+
+ return enh.Out, annos
+}
+
// pickFirstSampleIndex returns the index of the last sample before
// or at the range start, or 0 if none exist before the range start.
// If the vector selector is not anchored, it always returns 0, true.
@@ -2100,6 +2183,7 @@ var FunctionCalls = map[string]FunctionCall{
"histogram_count": funcHistogramCount,
"histogram_fraction": funcHistogramFraction,
"histogram_quantile": funcHistogramQuantile,
+ "histogram_quantiles": funcHistogramQuantiles,
"histogram_sum": funcHistogramSum,
"histogram_stddev": funcHistogramStdDev,
"histogram_stdvar": funcHistogramStdVar,
diff --git a/promql/parser/functions.go b/promql/parser/functions.go
index c7c7332305..180a255ab0 100644
--- a/promql/parser/functions.go
+++ b/promql/parser/functions.go
@@ -205,6 +205,13 @@ var Functions = map[string]*Function{
ArgTypes: []ValueType{ValueTypeScalar, ValueTypeVector},
ReturnType: ValueTypeVector,
},
+ "histogram_quantiles": {
+ Name: "histogram_quantiles",
+ ArgTypes: []ValueType{ValueTypeVector, ValueTypeString, ValueTypeScalar, ValueTypeScalar},
+ Variadic: 9,
+ ReturnType: ValueTypeVector,
+ Experimental: true,
+ },
"double_exponential_smoothing": {
Name: "double_exponential_smoothing",
ArgTypes: []ValueType{ValueTypeMatrix, ValueTypeScalar, ValueTypeScalar},
diff --git a/promql/promqltest/testdata/histograms.test b/promql/promqltest/testdata/histograms.test
index 436390ee41..db7d5de230 100644
--- a/promql/promqltest/testdata/histograms.test
+++ b/promql/promqltest/testdata/histograms.test
@@ -598,6 +598,40 @@ eval instant at 50m histogram_quantile(1, testhistogram3_bucket)
{start="positive"} 1
{start="negative"} -0.1
+eval instant at 50m histogram_quantiles(testhistogram3, "q", 0, 0.25, 0.5, 0.75, 1)
+ expect no_warn
+ {q="0.0", start="positive"} 0
+ {q="0.0", start="negative"} -0.25
+ {q="0.25", start="positive"} 0.055
+ {q="0.25", start="negative"} -0.225
+ {q="0.5", start="positive"} 0.125
+ {q="0.5", start="negative"} -0.2
+ {q="0.75", start="positive"} 0.45
+ {q="0.75", start="negative"} -0.15
+ {q="1.0", start="positive"} 1
+ {q="1.0", start="negative"} -0.1
+
+eval instant at 50m histogram_quantiles(testhistogram3_bucket, "q", 0, 0.25, 0.5, 0.75, 1)
+ expect no_warn
+ {q="0.0", start="positive"} 0
+ {q="0.0", start="negative"} -0.25
+ {q="0.25", start="positive"} 0.055
+ {q="0.25", start="negative"} -0.225
+ {q="0.5", start="positive"} 0.125
+ {q="0.5", start="negative"} -0.2
+ {q="0.75", start="positive"} 0.45
+ {q="0.75", start="negative"} -0.15
+ {q="1.0", start="positive"} 1
+ {q="1.0", start="negative"} -0.1
+
+# Break label set uniqueness.
+
+eval instant at 50m histogram_quantiles(testhistogram3, "start", 0, 0.25, 0.5, 0.75, 1)
+ expect fail
+
+eval instant at 50m histogram_quantiles(testhistogram3_bucket, "start", 0, 0.25, 0.5, 0.75, 1)
+ expect fail
+
# Quantile too low.
eval instant at 50m histogram_quantile(-0.1, testhistogram)
@@ -610,6 +644,16 @@ eval instant at 50m histogram_quantile(-0.1, testhistogram_bucket)
{start="positive"} -Inf
{start="negative"} -Inf
+eval instant at 50m histogram_quantiles(testhistogram, "q", -0.1)
+ expect warn
+ {q="-0.1", start="positive"} -Inf
+ {q="-0.1", start="negative"} -Inf
+
+eval instant at 50m histogram_quantiles(testhistogram_bucket, "q", -0.1)
+ expect warn
+ {q="-0.1", start="positive"} -Inf
+ {q="-0.1", start="negative"} -Inf
+
# Quantile too high.
eval instant at 50m histogram_quantile(1.01, testhistogram)
@@ -622,6 +666,16 @@ eval instant at 50m histogram_quantile(1.01, testhistogram_bucket)
{start="positive"} +Inf
{start="negative"} +Inf
+eval instant at 50m histogram_quantiles(testhistogram, "q", 1.01)
+ expect warn
+ {q="1.01", start="positive"} +Inf
+ {q="1.01", start="negative"} +Inf
+
+eval instant at 50m histogram_quantiles(testhistogram_bucket, "q", 1.01)
+ expect warn
+ {q="1.01", start="positive"} +Inf
+ {q="1.01", start="negative"} +Inf
+
# Quantile invalid.
eval instant at 50m histogram_quantile(NaN, testhistogram)
@@ -634,9 +688,22 @@ eval instant at 50m histogram_quantile(NaN, testhistogram_bucket)
{start="positive"} NaN
{start="negative"} NaN
+eval instant at 50m histogram_quantiles(testhistogram, "q", NaN)
+ expect warn
+ {q="NaN", start="positive"} NaN
+ {q="NaN", start="negative"} NaN
+
+eval instant at 50m histogram_quantiles(testhistogram_bucket, "q", NaN)
+ expect warn
+ {q="NaN", start="positive"} NaN
+ {q="NaN", start="negative"} NaN
+
eval instant at 50m histogram_quantile(NaN, non_existent)
expect warn msg: PromQL warning: quantile value should be between 0 and 1, got NaN
+eval instant at 50m histogram_quantiles(non_existent, "q", NaN)
+ expect warn msg: PromQL warning: quantile value should be between 0 and 1, got NaN
+
# Quantile value in lowest bucket.
eval instant at 50m histogram_quantile(0, testhistogram)
@@ -967,6 +1034,12 @@ eval instant at 50m histogram_quantile(0.99, nonmonotonic_bucket)
expect info
{} 979.75
+eval instant at 50m histogram_quantiles(nonmonotonic_bucket, "q", 0.01, 0.5, 0.99)
+ expect info
+ {q="0.01"} 0.0045
+ {q="0.5"} 8.5
+ {q="0.99"} 979.75
+
# Buckets with different representations of the same upper bound.
eval instant at 50m histogram_quantile(0.5, rate(mixed_bucket[10m]))
{instance="ins1", job="job1"} 0.15
@@ -1002,9 +1075,15 @@ load_with_nhcb 5m
eval instant at 50m histogram_quantile(0.99, {__name__=~"request_duration_seconds\\d*_bucket"})
expect fail
+eval instant at 50m histogram_quantiles({__name__=~"request_duration_seconds\\d*_bucket"}, "q", 0.99)
+ expect fail
+
eval instant at 50m histogram_quantile(0.99, {__name__=~"request_duration_seconds\\d*"})
expect fail
+eval instant at 50m histogram_quantiles({__name__=~"request_duration_seconds\\d*"}, "q", 0.99)
+ expect fail
+
# Histogram with constant buckets.
load_with_nhcb 1m
const_histogram_bucket{le="0.0"} 1 1 1 1 1
@@ -1066,7 +1145,7 @@ eval instant at 10m histogram_sum(increase(histogram_with_reset[15m]))
clear
-# Test histogram_quantile and histogram_fraction with conflicting classic and native histograms.
+# Test histogram_quantile(s) and histogram_fraction with conflicting classic and native histograms.
load 1m
series{host="a"} {{schema:0 sum:5 count:4 buckets:[9 2 1]}}
series{host="a", le="0.1"} 2
@@ -1081,6 +1160,11 @@ eval instant at 0 histogram_quantile(0.8, series)
expect warn msg: PromQL warning: vector contains a mix of classic and native histograms for metric name "series"
# Should return no results.
+eval instant at 0 histogram_quantiles(series, "q", 0.1, 0.2)
+ expect no_info
+ expect warn msg: PromQL warning: vector contains a mix of classic and native histograms for metric name "series"
+ # Should return no results.
+
eval instant at 0 histogram_fraction(-Inf, 1, series)
expect no_info
expect warn msg: PromQL warning: vector contains a mix of classic and native histograms for metric name "series"
diff --git a/promql/promqltest/testdata/native_histograms.test b/promql/promqltest/testdata/native_histograms.test
index 3b497e5ff4..40789b295a 100644
--- a/promql/promqltest/testdata/native_histograms.test
+++ b/promql/promqltest/testdata/native_histograms.test
@@ -55,6 +55,10 @@ eval instant at 1m histogram_quantile(0.5, single_histogram)
expect no_info
{} 1.414213562373095
+eval instant at 1m histogram_quantiles(single_histogram, "q", 0.5)
+ expect no_info
+ {q="0.5"} 1.414213562373095
+
clear
# Repeat the same histogram 10 times.
@@ -1605,6 +1609,11 @@ eval instant at 1m histogram_quantile(0.81, histogram_nan)
{case="100% NaNs"} NaN
{case="20% NaNs"} NaN
+eval instant at 1m histogram_quantiles(histogram_nan, "q", 0.81)
+ expect info msg: PromQL info: input to histogram_quantile has NaN observations, result is NaN for metric name "histogram_nan"
+ {case="100% NaNs", q="0.81"} NaN
+ {case="20% NaNs", q="0.81"} NaN
+
eval instant at 1m histogram_quantile(0.8, histogram_nan{case="100% NaNs"})
expect info msg: PromQL info: input to histogram_quantile has NaN observations, result is NaN for metric name "histogram_nan"
{case="100% NaNs"} NaN
@@ -1891,6 +1900,9 @@ eval instant at 1m histogram_quantile(0.5, myHistogram2)
eval instant at 1m histogram_quantile(0.5, mixedHistogram)
expect warn msg: PromQL warning: vector contains a mix of classic and native histograms for metric name "mixedHistogram"
+eval instant at 1m histogram_quantiles(mixedHistogram, "q", 0.5)
+ expect warn msg: PromQL warning: vector contains a mix of classic and native histograms for metric name "mixedHistogram"
+
clear
# A counter reset only in a bucket. Sub-queries still need to detect
@@ -1960,6 +1972,9 @@ eval instant at 1m histogram_count(histogram unless histogram_quantile(0.5, hist
eval instant at 1m histogram_quantile(0.5, histogram unless histogram_count(histogram) == 0)
{} 3.1748021039363987
+eval instant at 1m histogram_quantiles(histogram unless histogram_count(histogram) == 0, "q", 0.5)
+ {q="0.5"} 3.1748021039363987
+
clear
# Regression test for:
diff --git a/web/ui/mantine-ui/src/promql/functionDocs.tsx b/web/ui/mantine-ui/src/promql/functionDocs.tsx
index 4cc70a39e6..c7f744ba6f 100644
--- a/web/ui/mantine-ui/src/promql/functionDocs.tsx
+++ b/web/ui/mantine-ui/src/promql/functionDocs.tsx
@@ -1543,6 +1543,33 @@ const funcDocs: Record = {
>
),
+ histogram_quantiles: (
+ <>
+
+
+ This function has to be enabled via the{" "}
+ feature flag
+ --enable-feature=promql-experimental-functions.
+
+
+
+
+ histogram_quantiles(v instant-vector, quantile_label string, φ_1 scalar, φ_2 scalar, ...){" "}
+ calculates multiple (between 1 and 10) φ-quantiles (0 ≤ φ ≤ 1) from a{" "}
+ classic histogram or from a native
+ histogram. Quantile calculation works the same way as in histogram_quantile(). The second argument
+ (a string) specifies the label name that is used to identify different quantiles in the query result.
+
+
+
+
+ histogram_quantiles(sum(rate(foo[1m])), "quantile", 0.9, 0.99) # => {"{"}quantile="0.9"
+ {"}"} 123
+ {"{"}quantile="0.99"{"}"} 128
+
+
+ >
+ ),
histogram_stddev: (
<>
diff --git a/web/ui/mantine-ui/src/promql/functionSignatures.ts b/web/ui/mantine-ui/src/promql/functionSignatures.ts
index da21a2d4aa..837a271dce 100644
--- a/web/ui/mantine-ui/src/promql/functionSignatures.ts
+++ b/web/ui/mantine-ui/src/promql/functionSignatures.ts
@@ -69,6 +69,12 @@ export const functionSignatures: Record = {
variadic: 0,
returnType: valueType.vector,
},
+ histogram_quantiles: {
+ name: "histogram_quantiles",
+ argTypes: [valueType.vector, valueType.string, valueType.scalar, valueType.scalar],
+ variadic: 9,
+ returnType: valueType.vector,
+ },
histogram_stddev: {
name: "histogram_stddev",
argTypes: [valueType.vector],
diff --git a/web/ui/module/codemirror-promql/src/complete/promql.terms.ts b/web/ui/module/codemirror-promql/src/complete/promql.terms.ts
index 3670fffff7..68d7b06553 100644
--- a/web/ui/module/codemirror-promql/src/complete/promql.terms.ts
+++ b/web/ui/module/codemirror-promql/src/complete/promql.terms.ts
@@ -243,6 +243,12 @@ export const functionIdentifierTerms = [
info: 'Calculate quantiles from native histograms and from conventional histogram buckets',
type: 'function',
},
+ {
+ label: 'histogram_quantiles',
+ detail: 'function',
+ info: 'Calculate multiple quantiles from native histograms and from conventional histogram buckets',
+ type: 'function',
+ },
{
label: 'histogram_sum',
detail: 'function',
diff --git a/web/ui/module/codemirror-promql/src/types/function.ts b/web/ui/module/codemirror-promql/src/types/function.ts
index cfbf3524b5..cc1c0524fb 100644
--- a/web/ui/module/codemirror-promql/src/types/function.ts
+++ b/web/ui/module/codemirror-promql/src/types/function.ts
@@ -44,6 +44,7 @@ import {
HistogramCount,
HistogramFraction,
HistogramQuantile,
+ HistogramQuantiles,
HistogramStdDev,
HistogramStdVar,
HistogramSum,
@@ -306,6 +307,12 @@ const promqlFunctions: { [key: number]: PromQLFunction } = {
variadic: 0,
returnType: ValueType.vector,
},
+ [HistogramQuantiles]: {
+ name: 'histogram_quantiles',
+ argTypes: [ValueType.vector, ValueType.string, ValueType.scalar, ValueType.scalar],
+ variadic: 10,
+ returnType: ValueType.vector,
+ },
[HistogramStdDev]: {
name: 'histogram_stddev',
argTypes: [ValueType.vector],
diff --git a/web/ui/module/lezer-promql/src/promql.grammar b/web/ui/module/lezer-promql/src/promql.grammar
index 9308ad01be..e4308186bb 100644
--- a/web/ui/module/lezer-promql/src/promql.grammar
+++ b/web/ui/module/lezer-promql/src/promql.grammar
@@ -167,6 +167,7 @@ FunctionIdentifier {
HistogramCount |
HistogramFraction |
HistogramQuantile |
+ HistogramQuantiles |
HistogramStdDev |
HistogramStdVar |
HistogramSum |
@@ -426,6 +427,7 @@ NumberDurationLiteralInDurationContext {
HistogramCount { condFn<"histogram_count"> }
HistogramFraction { condFn<"histogram_fraction"> }
HistogramQuantile { condFn<"histogram_quantile"> }
+ HistogramQuantiles { condFn<"histogram_quantiles"> }
HistogramStdDev { condFn<"histogram_stddev"> }
HistogramStdVar { condFn<"histogram_stdvar"> }
HistogramSum { condFn<"histogram_sum"> }