From a7db93a3a305908b1f696cf481db743958f053ce Mon Sep 17 00:00:00 2001 From: Jeanette Tan Date: Thu, 27 Aug 2026 09:39:54 +0800 Subject: [PATCH 1/3] MQE: Add test to ensure buckets are not skipped for histogram_stddev and histogram_stdvar --- .../plan/skip_histogram_decoding_test.go | 40 +++++++++++++++++++ .../testdata/ours/native_histograms.test | 10 +++++ 2 files changed, 50 insertions(+) diff --git a/pkg/streamingpromql/optimize/plan/skip_histogram_decoding_test.go b/pkg/streamingpromql/optimize/plan/skip_histogram_decoding_test.go index ccb709aa8cf..796bb26ee94 100644 --- a/pkg/streamingpromql/optimize/plan/skip_histogram_decoding_test.go +++ b/pkg/streamingpromql/optimize/plan/skip_histogram_decoding_test.go @@ -70,6 +70,22 @@ func TestSkipHistogramDecodingOptimizationPass(t *testing.T) { - param 2: VectorSelector: {__name__="some_metric"} `, }, + "single vector selector with histogram_stddev": { + expr: `histogram_stddev(some_metric)`, + expectedPlan: ` + - DeduplicateAndMerge + - FunctionCall: histogram_stddev(...) + - VectorSelector: {__name__="some_metric"} + `, + }, + "single vector selector with histogram_stdvar": { + expr: `histogram_stdvar(some_metric)`, + expectedPlan: ` + - DeduplicateAndMerge + - FunctionCall: histogram_stdvar(...) + - VectorSelector: {__name__="some_metric"} + `, + }, "vector selector eligible for skipping decoding in binary expression": { expr: `2 * histogram_sum(some_metric)`, expectedPlan: ` @@ -126,6 +142,30 @@ func TestSkipHistogramDecodingOptimizationPass(t *testing.T) { - param 1: VectorSelector: {__name__="some_other_metric"} `, }, + "inner vector selector not eligible for skipping decoding due to nesting inside histogram_stddev": { + expr: `histogram_sum(some_metric * histogram_stddev(some_other_metric))`, + expectedPlan: ` + - DeduplicateAndMerge + - FunctionCall: histogram_sum(...) + - BinaryExpression: LHS * RHS + - LHS: VectorSelector: {__name__="some_metric"}, skip histogram buckets + - RHS: DeduplicateAndMerge + - FunctionCall: histogram_stddev(...) + - VectorSelector: {__name__="some_other_metric"} + `, + }, + "inner vector selector not eligible for skipping decoding due to nesting inside histogram_stdvar": { + expr: `histogram_sum(some_metric * histogram_stdvar(some_other_metric))`, + expectedPlan: ` + - DeduplicateAndMerge + - FunctionCall: histogram_sum(...) + - BinaryExpression: LHS * RHS + - LHS: VectorSelector: {__name__="some_metric"}, skip histogram buckets + - RHS: DeduplicateAndMerge + - FunctionCall: histogram_stdvar(...) + - VectorSelector: {__name__="some_other_metric"} + `, + }, "both vector selectors eligible for skipping decoding despite nesting": { expr: `histogram_sum(some_metric * histogram_count(some_other_metric))`, expectedPlan: ` diff --git a/pkg/streamingpromql/testdata/ours/native_histograms.test b/pkg/streamingpromql/testdata/ours/native_histograms.test index f64f75ddd7c..7633ce909e2 100644 --- a/pkg/streamingpromql/testdata/ours/native_histograms.test +++ b/pkg/streamingpromql/testdata/ours/native_histograms.test @@ -34,6 +34,16 @@ eval range from 0 to 5m step 1m histogram_stdvar(single_histogram) eval range from 0 to 5m step 1m histogram_sum(single_histogram) {} 5 5 5 5 5 20 +# histogram_stddev/histogram_stdvar operate on the buckets, so their input's buckets must never be skipped, +# even when nested under histogram_sum/histogram_count/histogram_avg (which would otherwise enable skipping via +# the "skip decoding histogram buckets" optimization). If the buckets were skipped, histogram_stddev/histogram_stdvar +# would see an empty bucket set and return 0, making the surrounding histogram_sum 0 as well. +eval instant at 5m histogram_sum(single_histogram * histogram_stddev(single_histogram)) + {} 59.72564428477802 + +eval instant at 5m histogram_sum(single_histogram * histogram_stdvar(single_histogram)) + {} 178.35762926159188 + clear # Test metric with mixed floats and histograms From 3931ca090926f8444a2a8b84f155405dd3fe4362 Mon Sep 17 00:00:00 2001 From: Jeanette Tan Date: Thu, 27 Aug 2026 09:39:54 +0800 Subject: [PATCH 2/3] Explicitly prevent the skipping --- CHANGELOG.md | 1 + pkg/streamingpromql/optimize/plan/skip_histogram_decoding.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f36996a1fbb..1f1932cacd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ * [BUGFIX] MQE: Fix an issue where series were joined in binary operations using the wrong labels when `group_left()`/`group_right()` were used in combination with `ignoring()`. This bug manifested as valid queries returning an error `grouping labels must ensure unique matches`. #16387 * [BUGFIX] MQE: Fix queries and rules containing a subquery whose range is shorter than its step (e.g. `foo[10m:3d]`) failing with `last bucket must not be before first bucket`. #16442 * [BUGFIX] MQE: Fix `sum_over_time()` over native histograms losing precision when experimental range vector splitting is enabled. The Kahan compensation of each split range was discarded instead of being carried over to the other split ranges. #16455 +* [BUGFIX] MQE: Never skip decoding histogram buckets for `histogram_stddev` and `histogram_stdvar`. #16486 * [BUGFIX] Upgrade Go to 1.26 latest with fixes for [CVE-2026-33818](https://pkg.go.dev/vuln/GO-2026-5972), [CVE-2026-39821](https://pkg.go.dev/vuln/GO-2026-5026), [CVE-2026-46600](https://pkg.go.dev/vuln/GO-2026-5942), [CVE-2026-56853](https://pkg.go.dev/vuln/GO-2026-6089), [CVE-2026-56858](https://pkg.go.dev/vuln/GO-2026-6091), [CVE-2026-56859](https://pkg.go.dev/vuln/GO-2026-6088), [CVE-2026-56860](https://pkg.go.dev/vuln/GO-2026-6218), and [CVE-2026-56862](https://pkg.go.dev/vuln/GO-2026-6090). #16408 #16430 * [BUGFIX] Store-gateway: Drain the chunks range reader before closing it so HTTP object storage connections can be reused. #16338 * [BUGFIX] Block-builder-scheduler: Fail startup instead of silently switching to normal operation without assigning any jobs when probing the initial consumption offsets fails. #16028 diff --git a/pkg/streamingpromql/optimize/plan/skip_histogram_decoding.go b/pkg/streamingpromql/optimize/plan/skip_histogram_decoding.go index 78cfbde4fb5..80bbf0aff30 100644 --- a/pkg/streamingpromql/optimize/plan/skip_histogram_decoding.go +++ b/pkg/streamingpromql/optimize/plan/skip_histogram_decoding.go @@ -56,7 +56,7 @@ func (s *SkipHistogramDecodingOptimizationPass) applyToNode(node planning.Node, switch f.Function { case functions.FUNCTION_HISTOGRAM_COUNT, functions.FUNCTION_HISTOGRAM_SUM, functions.FUNCTION_HISTOGRAM_AVG: skipHistogramBuckets = true - case functions.FUNCTION_HISTOGRAM_FRACTION, functions.FUNCTION_HISTOGRAM_QUANTILE, functions.FUNCTION_HISTOGRAM_QUANTILES: + case functions.FUNCTION_HISTOGRAM_FRACTION, functions.FUNCTION_HISTOGRAM_QUANTILE, functions.FUNCTION_HISTOGRAM_QUANTILES, functions.FUNCTION_HISTOGRAM_STDDEV, functions.FUNCTION_HISTOGRAM_STDVAR: skipHistogramBuckets = false default: // Nothing to do. From 1803742f8583a44cd0baa609745ab3830eccfc53 Mon Sep 17 00:00:00 2001 From: Jeanette Tan Date: Fri, 28 Aug 2026 02:54:59 +0800 Subject: [PATCH 3/3] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f1932cacd5..3e3811101d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,7 +33,7 @@ * [BUGFIX] MQE: Fix an issue where series were joined in binary operations using the wrong labels when `group_left()`/`group_right()` were used in combination with `ignoring()`. This bug manifested as valid queries returning an error `grouping labels must ensure unique matches`. #16387 * [BUGFIX] MQE: Fix queries and rules containing a subquery whose range is shorter than its step (e.g. `foo[10m:3d]`) failing with `last bucket must not be before first bucket`. #16442 * [BUGFIX] MQE: Fix `sum_over_time()` over native histograms losing precision when experimental range vector splitting is enabled. The Kahan compensation of each split range was discarded instead of being carried over to the other split ranges. #16455 -* [BUGFIX] MQE: Never skip decoding histogram buckets for `histogram_stddev` and `histogram_stdvar`. #16486 +* [BUGFIX] MQE: Never skip decoding histogram buckets for `histogram_stddev` and `histogram_stdvar`, as this could return wrong results when these functions are nested in other functions that skip decoding histogram buckets like `histogram_sum`, `histogram_count` or `histogram_avg`. #16486 * [BUGFIX] Upgrade Go to 1.26 latest with fixes for [CVE-2026-33818](https://pkg.go.dev/vuln/GO-2026-5972), [CVE-2026-39821](https://pkg.go.dev/vuln/GO-2026-5026), [CVE-2026-46600](https://pkg.go.dev/vuln/GO-2026-5942), [CVE-2026-56853](https://pkg.go.dev/vuln/GO-2026-6089), [CVE-2026-56858](https://pkg.go.dev/vuln/GO-2026-6091), [CVE-2026-56859](https://pkg.go.dev/vuln/GO-2026-6088), [CVE-2026-56860](https://pkg.go.dev/vuln/GO-2026-6218), and [CVE-2026-56862](https://pkg.go.dev/vuln/GO-2026-6090). #16408 #16430 * [BUGFIX] Store-gateway: Drain the chunks range reader before closing it so HTTP object storage connections can be reused. #16338 * [BUGFIX] Block-builder-scheduler: Fail startup instead of silently switching to normal operation without assigning any jobs when probing the initial consumption offsets fails. #16028