From 0f5f1955e5bf9ce11975b74e1e34a121097f90d7 Mon Sep 17 00:00:00 2001 From: Mohammad Alavi Date: Thu, 13 Nov 2025 17:17:51 +0700 Subject: [PATCH 01/14] promql: fix histogram_fraction issue when lower falls within the first bucket (#17424) Signed-off-by: Mohammad Alavi --- promql/promqltest/testdata/histograms.test | 377 +++++++++++++++++++++ promql/quantile.go | 34 +- 2 files changed, 410 insertions(+), 1 deletion(-) diff --git a/promql/promqltest/testdata/histograms.test b/promql/promqltest/testdata/histograms.test index 84a467a314..436390ee41 100644 --- a/promql/promqltest/testdata/histograms.test +++ b/promql/promqltest/testdata/histograms.test @@ -158,6 +158,383 @@ eval instant at 50m histogram_fraction(0, 0.2, rate(testhistogram3_bucket[10m])) {start="positive"} 0.6363636363636364 {start="negative"} 0 +# Positive buckets, lower falls in the first bucket. +load_with_nhcb 5m + positive_buckets_lower_falls_in_the_first_bucket_bucket{le="1"} 1+0x10 + positive_buckets_lower_falls_in_the_first_bucket_bucket{le="2"} 3+0x10 + positive_buckets_lower_falls_in_the_first_bucket_bucket{le="3"} 6+0x10 + positive_buckets_lower_falls_in_the_first_bucket_bucket{le="+Inf"} 100+0x10 + +# - Bucket [0, 1]: contributes 1.0 observation (full bucket). +# - Bucket [1, 2]: contributes (1.5-1)/(2-1) * (3-1) = 0.5 * 2 = 1.0 observations. +# Total: (1.0 + 1.0) / 100.0 = 0.02 + +eval instant at 50m histogram_fraction(0, 1.5, positive_buckets_lower_falls_in_the_first_bucket_bucket) + expect no_warn + {} 0.02 + +eval instant at 50m histogram_fraction(0, 1.5, positive_buckets_lower_falls_in_the_first_bucket) + expect no_warn + {} 0.02 + +# Negative buckets, lower falls in the first bucket. +load_with_nhcb 5m + negative_buckets_lower_falls_in_the_first_bucket_bucket{le="-3"} 10+0x10 + negative_buckets_lower_falls_in_the_first_bucket_bucket{le="-2"} 12+0x10 + negative_buckets_lower_falls_in_the_first_bucket_bucket{le="-1"} 15+0x10 + negative_buckets_lower_falls_in_the_first_bucket_bucket{le="+Inf"} 100+0x10 + +# - Bucket [-Inf, -3]: contributes zero observations (no interpolation with infinite width bucket). +# - Bucket [-3, -2]: contributes 12-10 = 2.0 observations (full bucket). +# Total: 2.0 / 100.0 = 0.02 + +eval instant at 50m histogram_fraction(-4, -2, negative_buckets_lower_falls_in_the_first_bucket_bucket) + expect no_warn + {} 0.02 + +eval instant at 50m histogram_fraction(-4, -2, negative_buckets_lower_falls_in_the_first_bucket) + expect no_warn + {} 0.02 + +# Lower is -Inf. +load_with_nhcb 5m + lower_is_negative_Inf_bucket{le="-3"} 10+0x10 + lower_is_negative_Inf_bucket{le="-2"} 12+0x10 + lower_is_negative_Inf_bucket{le="-1"} 15+0x10 + lower_is_negative_Inf_bucket{le="+Inf"} 100+0x10 + +# - Bucket [-Inf, -3]: contributes 10.0 observations (full bucket). +# - Bucket [-3, -2]: contributes 12-10 = 2.0 observations (full bucket). +# - Bucket [-2, -1]: contributes (-1.5-(-2))/(-1-(-2)) * (15-12) = 0.5 * 3 = 1.5 observations. +# Total: (10.0 + 2.0 + 1.5) / 100.0 = 0.135 + +eval instant at 50m histogram_fraction(-Inf, -1.5, lower_is_negative_Inf_bucket) + expect no_warn + {} 0.135 + +eval instant at 50m histogram_fraction(-Inf, -1.5, lower_is_negative_Inf) + expect no_warn + {} 0.135 + +# Lower is -Inf and upper is +Inf (positive buckets). +load_with_nhcb 5m + lower_is_negative_Inf_and_upper_is_positive_Inf__positive_buckets__bucket{le="1"} 1+0x10 + lower_is_negative_Inf_and_upper_is_positive_Inf__positive_buckets__bucket{le="2"} 3+0x10 + lower_is_negative_Inf_and_upper_is_positive_Inf__positive_buckets__bucket{le="3"} 6+0x10 + lower_is_negative_Inf_and_upper_is_positive_Inf__positive_buckets__bucket{le="+Inf"} 100+0x10 + +# Range [-Inf, +Inf] captures all observations. + +eval instant at 50m histogram_fraction(-Inf, +Inf, lower_is_negative_Inf_and_upper_is_positive_Inf__positive_buckets__bucket) + expect no_warn + {} 1.0 + +eval instant at 50m histogram_fraction(-Inf, +Inf, lower_is_negative_Inf_and_upper_is_positive_Inf__positive_buckets_) + expect no_warn + {} 1.0 + +# Lower is -Inf and upper is +Inf (negative buckets). +load_with_nhcb 5m + lower_is_negative_Inf_and_upper_is_positive_Inf__negative_buckets__bucket{le="-3"} 10+0x10 + lower_is_negative_Inf_and_upper_is_positive_Inf__negative_buckets__bucket{le="-2"} 12+0x10 + lower_is_negative_Inf_and_upper_is_positive_Inf__negative_buckets__bucket{le="-1"} 15+0x10 + lower_is_negative_Inf_and_upper_is_positive_Inf__negative_buckets__bucket{le="+Inf"} 100+0x10 + +# Range [-Inf, +Inf] captures all observations. + +eval instant at 50m histogram_fraction(-Inf, +Inf, lower_is_negative_Inf_and_upper_is_positive_Inf__negative_buckets__bucket) + expect no_warn + {} 1.0 + +eval instant at 50m histogram_fraction(-Inf, +Inf, lower_is_negative_Inf_and_upper_is_positive_Inf__negative_buckets_) + expect no_warn + {} 1.0 + +# Lower and upper fall in last bucket (positive buckets). +load_with_nhcb 5m + lower_and_upper_fall_in_last_bucket__positive_buckets__bucket{le="1"} 1+0x10 + lower_and_upper_fall_in_last_bucket__positive_buckets__bucket{le="2"} 3+0x10 + lower_and_upper_fall_in_last_bucket__positive_buckets__bucket{le="3"} 6+0x10 + lower_and_upper_fall_in_last_bucket__positive_buckets__bucket{le="+Inf"} 100+0x10 + +# - Bucket [3, +Inf]: contributes zero observations (no interpolation with infinite width bucket). +# Total: 0.0 / 100.0 = 0.0 + +eval instant at 50m histogram_fraction(4, 5, lower_and_upper_fall_in_last_bucket__positive_buckets__bucket) + expect no_warn + {} 0.0 + +eval instant at 50m histogram_fraction(4, 5, lower_and_upper_fall_in_last_bucket__positive_buckets_) + expect no_warn + {} 0.0 + +# Lower and upper fall in last bucket (negative buckets). +load_with_nhcb 5m + lower_and_upper_fall_in_last_bucket__negative_buckets__bucket{le="-3"} 10+0x10 + lower_and_upper_fall_in_last_bucket__negative_buckets__bucket{le="-2"} 12+0x10 + lower_and_upper_fall_in_last_bucket__negative_buckets__bucket{le="-1"} 15+0x10 + lower_and_upper_fall_in_last_bucket__negative_buckets__bucket{le="+Inf"} 100+0x10 + +# - Bucket [-1, +Inf]: contributes zero observations (no interpolation with infinite width bucket). +# Total: 0.0 / 100.0 = 0.0 + +eval instant at 50m histogram_fraction(0, 1, lower_and_upper_fall_in_last_bucket__negative_buckets__bucket) + expect no_warn + {} 0.0 + +eval instant at 50m histogram_fraction(0, 1, lower_and_upper_fall_in_last_bucket__negative_buckets_) + expect no_warn + {} 0.0 + +# Upper falls in last bucket. +load_with_nhcb 5m + upper_falls_in_last_bucket_bucket{le="1"} 1+0x10 + upper_falls_in_last_bucket_bucket{le="2"} 3+0x10 + upper_falls_in_last_bucket_bucket{le="3"} 6+0x10 + upper_falls_in_last_bucket_bucket{le="+Inf"} 100+0x10 + +# - Bucket [2, 3]: 6-3 = 3.0 observations (full bucket). +# - Bucket [3, +Inf]: contributes zero observations (no interpolation with infinite width bucket). +# Total: 3.0 / 100.0 = 0.03 + +eval instant at 50m histogram_fraction(2, 5, upper_falls_in_last_bucket_bucket) + expect no_warn + {} 0.03 + +eval instant at 50m histogram_fraction(2, 5, upper_falls_in_last_bucket) + expect no_warn + {} 0.03 + +# Upper is +Inf. +load_with_nhcb 5m + upper_is_positive_Inf_bucket{le="1"} 1+0x10 + upper_is_positive_Inf_bucket{le="2"} 3+0x10 + upper_is_positive_Inf_bucket{le="3"} 6+0x10 + upper_is_positive_Inf_bucket{le="+Inf"} 100+0x10 + +# All observations in +Inf bucket: 100-6 = 94.0 observations. +# Total: 94.0 / 100.0 = 0.94 + +eval instant at 50m histogram_fraction(400, +Inf, upper_is_positive_Inf_bucket) + expect no_warn + {} 0.94 + +eval instant at 50m histogram_fraction(400, +Inf, upper_is_positive_Inf) + expect no_warn + {} 0.94 + +# Lower equals upper. +load_with_nhcb 5m + lower_equals_upper_bucket{le="1"} 1+0x10 + lower_equals_upper_bucket{le="2"} 3+0x10 + lower_equals_upper_bucket{le="3"} 6+0x10 + lower_equals_upper_bucket{le="+Inf"} 100+0x10 + +# No observations can be captured in a zero-width range. + +eval instant at 50m histogram_fraction(2, 2, lower_equals_upper_bucket) + expect no_warn + {} 0.0 + +eval instant at 50m histogram_fraction(2, 2, lower_equals_upper) + expect no_warn + {} 0.0 + +# Lower greater than upper. +load_with_nhcb 5m + lower_greater_than_upper_bucket{le="1"} 1+0x10 + lower_greater_than_upper_bucket{le="2"} 3+0x10 + lower_greater_than_upper_bucket{le="3"} 6+0x10 + lower_greater_than_upper_bucket{le="+Inf"} 100+0x10 + +eval instant at 50m histogram_fraction(3, 2, lower_greater_than_upper_bucket) + expect no_warn + {} 0.0 + +eval instant at 50m histogram_fraction(3, 2, lower_greater_than_upper) + expect no_warn + {} 0.0 + +# Single bucket. +load_with_nhcb 5m + single_bucket_bucket{le="+Inf"} 100+0x10 + +# - Bucket [0, +Inf]: contributes zero observations (no interpolation with infinite width bucket). +# Total: 0.0 / 100.0 = 0.0 + +eval instant at 50m histogram_fraction(0, 1, single_bucket_bucket) + expect no_warn + {} 0.0 + +eval instant at 50m histogram_fraction(0, 1, single_bucket) + expect no_warn + {} 0.0 + +# All zero counts. +load_with_nhcb 5m + all_zero_counts_bucket{le="1"} 0+0x10 + all_zero_counts_bucket{le="2"} 0+0x10 + all_zero_counts_bucket{le="3"} 0+0x10 + all_zero_counts_bucket{le="+Inf"} 0+0x10 + +eval instant at 50m histogram_fraction(0, 5, all_zero_counts_bucket) + expect no_warn + {} NaN + +eval instant at 50m histogram_fraction(0, 5, all_zero_counts) + expect no_warn + {} NaN + +# Lower exactly on bucket boundary. +load_with_nhcb 5m + lower_exactly_on_bucket_boundary_bucket{le="1"} 1+0x10 + lower_exactly_on_bucket_boundary_bucket{le="2"} 3+0x10 + lower_exactly_on_bucket_boundary_bucket{le="3"} 6+0x10 + lower_exactly_on_bucket_boundary_bucket{le="+Inf"} 100+0x10 + +# - Bucket [2, 3]: 6-3 = 3.0 observations (full bucket). +# - Bucket [3, +Inf]: contributes zero observations (no interpolation with infinite width bucket). +# Total: 3.0 / 100.0 = 0.03 + +eval instant at 50m histogram_fraction(2, 3.5, lower_exactly_on_bucket_boundary_bucket) + expect no_warn + {} 0.03 + +eval instant at 50m histogram_fraction(2, 3.5, lower_exactly_on_bucket_boundary) + expect no_warn + {} 0.03 + +# Upper exactly on bucket boundary. +load_with_nhcb 5m + upper_exactly_on_bucket_boundary_bucket{le="1"} 1+0x10 + upper_exactly_on_bucket_boundary_bucket{le="2"} 3+0x10 + upper_exactly_on_bucket_boundary_bucket{le="3"} 6+0x10 + upper_exactly_on_bucket_boundary_bucket{le="+Inf"} 100+0x10 + +# - Bucket [0, 1]: (1.0-0.5)/(1.0-0.0) * 1.0 = 0.5 * 1.0 = 0.5 observations. +# - Bucket [1, 2]: 3-1 = 2.0 observations (full bucket). +# Total: (0.5 + 2.0) / 100.0 = 0.025 + +eval instant at 50m histogram_fraction(0.5, 2, upper_exactly_on_bucket_boundary_bucket) + expect no_warn + {} 0.025 + +eval instant at 50m histogram_fraction(0.5, 2, upper_exactly_on_bucket_boundary) + expect no_warn + {} 0.025 + +# Both bounds exactly on bucket boundaries. +load_with_nhcb 5m + both_bounds_exactly_on_bucket_boundaries_bucket{le="1"} 1+0x10 + both_bounds_exactly_on_bucket_boundaries_bucket{le="2"} 3+0x10 + both_bounds_exactly_on_bucket_boundaries_bucket{le="3"} 6+0x10 + both_bounds_exactly_on_bucket_boundaries_bucket{le="+Inf"} 100+0x10 + +# - Bucket [1, 2]: 3-1 = 2.0 observations (full bucket). +# - Bucket [2, 3]: 6-3 = 3.0 observations (full bucket). +# Total: (2.0 + 3.0) / 100.0 = 0.05 + +eval instant at 50m histogram_fraction(1, 3, both_bounds_exactly_on_bucket_boundaries_bucket) + expect no_warn + {} 0.05 + +eval instant at 50m histogram_fraction(1, 3, both_bounds_exactly_on_bucket_boundaries) + expect no_warn + {} 0.05 + +# Fractional bucket bounds. +load_with_nhcb 5m + fractional_bucket_bounds_bucket{le="0.5"} 2.5+0x10 + fractional_bucket_bounds_bucket{le="1"} 7.5+0x10 + fractional_bucket_bounds_bucket{le="+Inf"} 100+0x10 + +# - Bucket [0, 0.5]: (0.5-0.1)/(0.5-0.0) * 2.5 = 0.8 * 2.5 = 2.0 observations. +# - Bucket [0.5, 1.0]: (0.75-0.5)/(1.0-0.5) * (7.5-2.5) = 0.5 * 5.0 = 2.5 observations. +# Total: (2.0 + 2.5) / 100.0 = 0.045 + +eval instant at 50m histogram_fraction(0.1, 0.75, fractional_bucket_bounds_bucket) + expect no_warn + {} 0.045 + +eval instant at 50m histogram_fraction(0.1, 0.75, fractional_bucket_bounds) + expect no_warn + {} 0.045 + +# Range crosses zero. +load_with_nhcb 5m + range_crosses_zero_bucket{le="-2"} 5+0x10 + range_crosses_zero_bucket{le="-1"} 10+0x10 + range_crosses_zero_bucket{le="0"} 15+0x10 + range_crosses_zero_bucket{le="1"} 20+0x10 + range_crosses_zero_bucket{le="+Inf"} 100+0x10 + +# - Bucket [-1, 0]: 15-10 = 5.0 observations (full bucket). +# - Bucket [0, 1]: 20-15 = 5.0 observations (full bucket). +# Total: (5.0 + 5.0) / 100.0 = 0.1 + +eval instant at 50m histogram_fraction(-1, 1, range_crosses_zero_bucket) + expect no_warn + {} 0.1 + +eval instant at 50m histogram_fraction(-1, 1, range_crosses_zero) + expect no_warn + {} 0.1 + +# Lower is NaN. +load_with_nhcb 5m + lower_is_NaN_bucket{le="1"} 1+0x10 + lower_is_NaN_bucket{le="+Inf"} 100+0x10 + +eval instant at 50m histogram_fraction(NaN, 1, lower_is_NaN_bucket) + expect no_warn + {} NaN + +eval instant at 50m histogram_fraction(NaN, 1, lower_is_NaN) + expect no_warn + {} NaN + +# Upper is NaN. +load_with_nhcb 5m + upper_is_NaN_bucket{le="1"} 1+0x10 + upper_is_NaN_bucket{le="+Inf"} 100+0x10 + +eval instant at 50m histogram_fraction(0, NaN, upper_is_NaN_bucket) + expect no_warn + {} NaN + +eval instant at 50m histogram_fraction(0, NaN, upper_is_NaN) + expect no_warn + {} NaN + +# Range entirely below all buckets. +load_with_nhcb 5m + range_entirely_below_all_buckets_bucket{le="1"} 1+0x10 + range_entirely_below_all_buckets_bucket{le="2"} 3+0x10 + range_entirely_below_all_buckets_bucket{le="+Inf"} 10+0x10 + +eval instant at 50m histogram_fraction(-10, -5, range_entirely_below_all_buckets_bucket) + expect no_warn + {} 0.0 + +eval instant at 50m histogram_fraction(-10, -5, range_entirely_below_all_buckets) + expect no_warn + {} 0.0 + +# Range entirely above all buckets. +load_with_nhcb 5m + range_entirely_above_all_buckets_bucket{le="1"} 1+0x10 + range_entirely_above_all_buckets_bucket{le="2"} 3+0x10 + range_entirely_above_all_buckets_bucket{le="+Inf"} 10+0x10 + +eval instant at 50m histogram_fraction(5, 10, range_entirely_above_all_buckets_bucket) + expect no_warn + {} 0.0 + +eval instant at 50m histogram_fraction(5, 10, range_entirely_above_all_buckets) + expect no_warn + {} 0.0 + + # In the classic histogram, we can access the corresponding bucket (if # it exists) and divide by the count to get the same result. diff --git a/promql/quantile.go b/promql/quantile.go index 1454974107..78df925c51 100644 --- a/promql/quantile.go +++ b/promql/quantile.go @@ -406,6 +406,18 @@ func HistogramFraction(lower, upper float64, h *histogram.FloatHistogram, metric // consistent with the linear interpolation known from classic // histograms. It is also used for the zero bucket. interpolateLinearly := func(v float64) float64 { + // Note: `v` is a finite value. + // For buckets with infinite bounds, we cannot interpolate meaningfully. + // For +Inf upper bound, interpolation returns the cumulative count of the previous bucket + // as the second term in the interpolation formula yields 0 (finite/Inf). + // In other words, no observations from the last bucket are considered in the fraction calculation. + // For -Inf lower bound, however, the second term would be (v-(-Inf))/(upperBound-(-Inf)) = Inf/Inf = NaN. + // To achieve the same effect of no contribution as the +Inf bucket, handle the -Inf case by returning + // the cumulative count at the first bucket (which equals the bucket's count). + // In both cases, we effectively skip interpolation within the infinite-width bucket. + if b.Lower == math.Inf(-1) { + return b.Count + } return rank + b.Count*(v-b.Lower)/(b.Upper-b.Lower) } @@ -531,14 +543,34 @@ func BucketFraction(lower, upper float64, buckets Buckets) float64 { rank, lowerRank, upperRank float64 lowerSet, upperSet bool ) + + // If the upper bound of the first bucket is greater than 0, we assume + // we are dealing with positive buckets only and lowerBound for the + // first bucket is set to 0; otherwise it is set to -Inf. + lowerBound := 0.0 + if buckets[0].UpperBound <= 0 { + lowerBound = math.Inf(-1) + } + for i, b := range buckets { - lowerBound := math.Inf(-1) if i > 0 { lowerBound = buckets[i-1].UpperBound } upperBound := b.UpperBound interpolateLinearly := func(v float64) float64 { + // Note: `v` is a finite value. + // For buckets with infinite bounds, we cannot interpolate meaningfully. + // For +Inf upper bound, interpolation returns the cumulative count of the previous bucket + // as the second term in the interpolation formula yields 0 (finite/Inf). + // In other words, no observations from the last bucket are considered in the fraction calculation. + // For -Inf lower bound, however, the second term would be (v-(-Inf))/(upperBound-(-Inf)) = Inf/Inf = NaN. + // To achieve the same effect of no contribution as the +Inf bucket, handle the -Inf case by returning + // the cumulative count at the first bucket. + // In both cases, we effectively skip interpolation within the infinite-width bucket. + if lowerBound == math.Inf(-1) { + return b.Count + } return rank + (b.Count-rank)*(v-lowerBound)/(upperBound-lowerBound) } From 743116649bb85a9e22eff1960606a944b149321b Mon Sep 17 00:00:00 2001 From: Jan Fajerski Date: Fri, 7 Nov 2025 14:59:19 +0100 Subject: [PATCH 02/14] prepare release 3.8.0-rc.0 Signed-off-by: Jan Fajerski --- CHANGELOG.md | 34 +++++++++++++++++++- VERSION | 2 +- web/ui/mantine-ui/package.json | 4 +-- web/ui/module/codemirror-promql/package.json | 4 +-- web/ui/module/lezer-promql/package.json | 2 +- web/ui/package-lock.json | 14 ++++---- web/ui/package.json | 2 +- 7 files changed, 47 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11ec004cb6..07b6e1d74b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,39 @@ ## main / unreleased -* [FEATURE] Templates: Add urlQueryEscape to template functions. #17403 +## 3.8.0-rc.0 / 2025-11-07 + +* [CHANGE] TSDB: Native Histogram Custom Bounds with a NaN threshold are now rejected. #17287 +* [FEATURE] Dockerfile: Add OpenContainers spec labels to Dockerfile. #16483 +* [FEATURE] SD: Add unified AWS service discovery for ec2, lightsail and ecs services. #17046 +* [FEATURE] Native histograms are now a stable, but optional feature, use the `scrape_native_histogram` config setting. #17232 #17315 +* [FEATURE] UI: Support anchored and smoothed keyword in promql editor. #17239 +* [FEATURE] UI: Show detailed relabeling steps for each discovered target. #17337 +* [FEATURE] Alerting: Add urlQueryEscape to template functions. #17403 +* [FEATURE] Promtool: Add Remote-Write 2.0 support to `promtool push metrics` via the `--protobuf_message` flag. #17417 +* [ENHANCEMENT] Clarify the docs about handling negative native histograms. #17249 +* [ENHANCEMENT] Mixin: Add static UID to the remote-write dashboard. #17256 +* [ENHANCEMENT] PromQL: Reconcile mismatched NHCB bounds in `Add` and `Sub`. #17278 +* [ENHANCEMENT] Alerting: Add "unknown" state for alerting rules that haven't been evaluated yet. #17282 +* [ENHANCEMENT] Scrape: Allow simultaneous use of classic histogram → NHCB conversion and zero-timestamp ingestion. #17305 +* [ENHANCEMENT] UI: Add smoothed/anchored in explain. #17334 +* [ENHANCEMENT] OTLP: De-duplicate any `target_info` samples with the same timestamp for the same series. #17400 +* [ENHANCEMENT] Document `use_fips_sts_endpoint` in `sigv4` config sections. #17304 +* [ENHANCEMENT] Document Prometheus Agent. #14519 +* [PERF] PromQL: Speed up parsing of variadic functions. #17316 +* [PERF] UI: Speed up alerts/rules/... pages by not rendering collapsed content. #17485 +* [PERF] UI: Performance improvement when getting label name and values in promql editor. #17194 +* [PERF] UI: Speed up /alerts for many firing alerts via virtual scrolling. #17254 +* [BUGFIX] PromQL: Fix slice indexing bug in info function on churning series. #17199 +* [BUGFIX] API: Reduce lock contention on `/api/v1/targets`. #17306 +* [BUGFIX] PromQL: Consistent handling of gauge vs. counter histograms in aggregations. #17312 +* [BUGFIX] TSDB: Allow NHCB with -Inf as the first custom value. #17320 +* [BUGFIX] UI: Fix duplicate loading of data from the API speed up rendering of some pages. #17357 +* [BUGFIX] Old UI: Fix createExpressionLink to correctly build /graph URLs so links from Alerts/Rules work again. #17365 +* [BUGFIX] PromQL: Avoid panic when parsing malformed `info` call. #17379 +* [BUGFIX] PromQL: Include histograms when enforcing sample_limit. #17390 +* [BUGFIX] Config: Fix panic if TLS CA file is absent. #17418 +* [BUGFIX] PromQL: Fix `histogram_fraction` for classic histograms and NHCB if lower bound is in the first bucket. #17424 ## 3.7.3 / 2025-10-29 diff --git a/VERSION b/VERSION index c1e43e6d45..100ac3dfd6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.7.3 +3.8.0-rc.0 diff --git a/web/ui/mantine-ui/package.json b/web/ui/mantine-ui/package.json index 219d357f0d..1f10e4b620 100644 --- a/web/ui/mantine-ui/package.json +++ b/web/ui/mantine-ui/package.json @@ -1,7 +1,7 @@ { "name": "@prometheus-io/mantine-ui", "private": true, - "version": "0.307.3", + "version": "0.308.0-rc.0", "type": "module", "scripts": { "start": "vite", @@ -28,7 +28,7 @@ "@microsoft/fetch-event-source": "^2.0.1", "@nexucis/fuzzy": "^0.5.1", "@nexucis/kvsearch": "^0.9.1", - "@prometheus-io/codemirror-promql": "0.307.3", + "@prometheus-io/codemirror-promql": "0.308.0-rc.0", "@reduxjs/toolkit": "^2.10.1", "@tabler/icons-react": "^3.35.0", "@tanstack/react-query": "^5.90.7", diff --git a/web/ui/module/codemirror-promql/package.json b/web/ui/module/codemirror-promql/package.json index f850342728..b32fd59d19 100644 --- a/web/ui/module/codemirror-promql/package.json +++ b/web/ui/module/codemirror-promql/package.json @@ -1,6 +1,6 @@ { "name": "@prometheus-io/codemirror-promql", - "version": "0.307.3", + "version": "0.308.0-rc.0", "description": "a CodeMirror mode for the PromQL language", "types": "dist/esm/index.d.ts", "module": "dist/esm/index.js", @@ -29,7 +29,7 @@ }, "homepage": "https://github.com/prometheus/prometheus/blob/main/web/ui/module/codemirror-promql/README.md", "dependencies": { - "@prometheus-io/lezer-promql": "0.307.3", + "@prometheus-io/lezer-promql": "0.308.0-rc.0", "lru-cache": "^11.2.2" }, "devDependencies": { diff --git a/web/ui/module/lezer-promql/package.json b/web/ui/module/lezer-promql/package.json index 05511c2b89..d86f1a1e7a 100644 --- a/web/ui/module/lezer-promql/package.json +++ b/web/ui/module/lezer-promql/package.json @@ -1,6 +1,6 @@ { "name": "@prometheus-io/lezer-promql", - "version": "0.307.3", + "version": "0.308.0-rc.0", "description": "lezer-based PromQL grammar", "main": "dist/index.cjs", "type": "module", diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json index 2631802e53..a9a75a131a 100644 --- a/web/ui/package-lock.json +++ b/web/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "prometheus-io", - "version": "0.307.3", + "version": "0.308.0-rc.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "prometheus-io", - "version": "0.307.3", + "version": "0.308.0-rc.0", "workspaces": [ "mantine-ui", "module/*" @@ -24,7 +24,7 @@ }, "mantine-ui": { "name": "@prometheus-io/mantine-ui", - "version": "0.307.3", + "version": "0.308.0-rc.0", "dependencies": { "@codemirror/autocomplete": "^6.19.1", "@codemirror/language": "^6.11.3", @@ -42,7 +42,7 @@ "@microsoft/fetch-event-source": "^2.0.1", "@nexucis/fuzzy": "^0.5.1", "@nexucis/kvsearch": "^0.9.1", - "@prometheus-io/codemirror-promql": "0.307.3", + "@prometheus-io/codemirror-promql": "0.308.0-rc.0", "@reduxjs/toolkit": "^2.10.1", "@tabler/icons-react": "^3.35.0", "@tanstack/react-query": "^5.90.7", @@ -88,10 +88,10 @@ }, "module/codemirror-promql": { "name": "@prometheus-io/codemirror-promql", - "version": "0.307.3", + "version": "0.308.0-rc.0", "license": "Apache-2.0", "dependencies": { - "@prometheus-io/lezer-promql": "0.307.3", + "@prometheus-io/lezer-promql": "0.308.0-rc.0", "lru-cache": "^11.2.2" }, "devDependencies": { @@ -121,7 +121,7 @@ }, "module/lezer-promql": { "name": "@prometheus-io/lezer-promql", - "version": "0.307.3", + "version": "0.308.0-rc.0", "license": "Apache-2.0", "devDependencies": { "@lezer/generator": "^1.8.0", diff --git a/web/ui/package.json b/web/ui/package.json index e237294df8..d8f2c712ff 100644 --- a/web/ui/package.json +++ b/web/ui/package.json @@ -1,7 +1,7 @@ { "name": "prometheus-io", "description": "Monorepo for the Prometheus UI", - "version": "0.307.3", + "version": "0.308.0-rc.0", "private": true, "scripts": { "build": "bash build_ui.sh --all", From 26f8c92de8b5ddec530a53c74a6f50ac28f65388 Mon Sep 17 00:00:00 2001 From: Jan Fajerski Date: Mon, 17 Nov 2025 16:00:12 +0100 Subject: [PATCH 03/14] test: skip TestRemoteWrite_ReshardingWithoutDeadlock temporarily as flaky (#17534) (#17543) (cherry picked from commit 35c3232a2ee541273828982b2ce6aadd6c1c9a5f) Signed-off-by: machine424 Signed-off-by: Jan Fajerski Co-authored-by: Ayoub Mrini --- cmd/prometheus/main_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/prometheus/main_test.go b/cmd/prometheus/main_test.go index ccc9151492..e5e3db39ae 100644 --- a/cmd/prometheus/main_test.go +++ b/cmd/prometheus/main_test.go @@ -969,6 +969,7 @@ remote_write: // TestRemoteWrite_ReshardingWithoutDeadlock ensures that resharding (scaling up) doesn't block when the shards are full. // See: https://github.com/prometheus/prometheus/issues/17384. func TestRemoteWrite_ReshardingWithoutDeadlock(t *testing.T) { + t.Skip("flaky test, see https://github.com/prometheus/prometheus/issues/17489") t.Parallel() tmpDir := t.TempDir() From 3a7ee37d9d1917af5758983ff6d170e7057426b9 Mon Sep 17 00:00:00 2001 From: Jan Fajerski Date: Tue, 18 Nov 2025 11:55:36 +0100 Subject: [PATCH 04/14] chore(deps): bump prometheus/promci from 0.4.7 to 0.5.0 Signed-off-by: Jan Fajerski --- .github/workflows/ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed4cfbf356..1e9118bc3e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7 + - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 - uses: ./.github/promci/actions/setup_environment with: enable_npm: true @@ -37,7 +37,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7 + - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 - uses: ./.github/promci/actions/setup_environment - run: go test --tags=dedupelabels ./... - run: go test --tags=slicelabels -race ./cmd/prometheus ./model/textparse ./prompb/... @@ -81,7 +81,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7 + - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 - uses: ./.github/promci/actions/setup_environment with: enable_go: false @@ -146,7 +146,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7 + - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 - uses: ./.github/promci/actions/build with: promu_opts: "-p linux/amd64 -p windows/amd64 -p linux/arm64 -p darwin/amd64 -p darwin/arm64 -p linux/386" @@ -173,7 +173,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7 + - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 - uses: ./.github/promci/actions/build with: parallelism: 12 @@ -268,7 +268,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7 + - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 - uses: ./.github/promci/actions/publish_main with: docker_hub_login: ${{ secrets.docker_hub_login }} @@ -287,7 +287,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7 + - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 - uses: ./.github/promci/actions/publish_release with: docker_hub_login: ${{ secrets.docker_hub_login }} @@ -304,7 +304,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@443c7fc2397e946bc9f5029e313a9c3441b9b86d # v0.4.7 + - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 - name: Install nodejs uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: From 34b382099df790d3fdf0fd00b2501adfb82c4d07 Mon Sep 17 00:00:00 2001 From: Jan Fajerski Date: Tue, 18 Nov 2025 17:30:44 +0100 Subject: [PATCH 05/14] chore(deps): bump prometheus/promci from 0.5.0 to 0.5.1 Signed-off-by: Jan Fajerski --- .github/workflows/ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e9118bc3e..1f1e86028a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 + - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 - uses: ./.github/promci/actions/setup_environment with: enable_npm: true @@ -37,7 +37,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 + - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 - uses: ./.github/promci/actions/setup_environment - run: go test --tags=dedupelabels ./... - run: go test --tags=slicelabels -race ./cmd/prometheus ./model/textparse ./prompb/... @@ -81,7 +81,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 + - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 - uses: ./.github/promci/actions/setup_environment with: enable_go: false @@ -146,7 +146,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 + - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 - uses: ./.github/promci/actions/build with: promu_opts: "-p linux/amd64 -p windows/amd64 -p linux/arm64 -p darwin/amd64 -p darwin/arm64 -p linux/386" @@ -173,7 +173,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 + - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 - uses: ./.github/promci/actions/build with: parallelism: 12 @@ -268,7 +268,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 + - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 - uses: ./.github/promci/actions/publish_main with: docker_hub_login: ${{ secrets.docker_hub_login }} @@ -287,7 +287,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 + - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 - uses: ./.github/promci/actions/publish_release with: docker_hub_login: ${{ secrets.docker_hub_login }} @@ -304,7 +304,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@0de5887ada1e8a8a665d8f619d4dd3afec8ba7e5 # v0.5.0 + - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 - name: Install nodejs uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: From b17349bd56f80101b2cddec5ef6e52941a11e103 Mon Sep 17 00:00:00 2001 From: Jan Fajerski Date: Wed, 19 Nov 2025 12:05:20 +0100 Subject: [PATCH 06/14] chore(deps): bump prometheus/promci from 0.5.1 to 0.5.2 Signed-off-by: Jan Fajerski --- .github/workflows/ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f1e86028a..82f4416c14 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 + - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 - uses: ./.github/promci/actions/setup_environment with: enable_npm: true @@ -37,7 +37,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 + - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 - uses: ./.github/promci/actions/setup_environment - run: go test --tags=dedupelabels ./... - run: go test --tags=slicelabels -race ./cmd/prometheus ./model/textparse ./prompb/... @@ -81,7 +81,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 + - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 - uses: ./.github/promci/actions/setup_environment with: enable_go: false @@ -146,7 +146,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 + - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 - uses: ./.github/promci/actions/build with: promu_opts: "-p linux/amd64 -p windows/amd64 -p linux/arm64 -p darwin/amd64 -p darwin/arm64 -p linux/386" @@ -173,7 +173,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 + - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 - uses: ./.github/promci/actions/build with: parallelism: 12 @@ -268,7 +268,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 + - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 - uses: ./.github/promci/actions/publish_main with: docker_hub_login: ${{ secrets.docker_hub_login }} @@ -287,7 +287,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 + - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 - uses: ./.github/promci/actions/publish_release with: docker_hub_login: ${{ secrets.docker_hub_login }} @@ -304,7 +304,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@c6d50d8e6149e4079661f68b565de32a2053ec5b # v0.5.1 + - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 - name: Install nodejs uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: From 93cde0f9147045d949d51065fbe1c2b80b476e42 Mon Sep 17 00:00:00 2001 From: Jan Fajerski Date: Wed, 19 Nov 2025 20:16:54 +0100 Subject: [PATCH 07/14] chore(deps): bump prometheus/promci from 0.5.2 to 0.5.3 Signed-off-by: Jan Fajerski --- .github/workflows/ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82f4416c14..e4c2fbce18 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 + - uses: prometheus/promci@c0916f0a41f13444612a8f0f5e700ea34edd7c19 # v0.5.3 - uses: ./.github/promci/actions/setup_environment with: enable_npm: true @@ -37,7 +37,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 + - uses: prometheus/promci@c0916f0a41f13444612a8f0f5e700ea34edd7c19 # v0.5.3 - uses: ./.github/promci/actions/setup_environment - run: go test --tags=dedupelabels ./... - run: go test --tags=slicelabels -race ./cmd/prometheus ./model/textparse ./prompb/... @@ -81,7 +81,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 + - uses: prometheus/promci@c0916f0a41f13444612a8f0f5e700ea34edd7c19 # v0.5.3 - uses: ./.github/promci/actions/setup_environment with: enable_go: false @@ -146,7 +146,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 + - uses: prometheus/promci@c0916f0a41f13444612a8f0f5e700ea34edd7c19 # v0.5.3 - uses: ./.github/promci/actions/build with: promu_opts: "-p linux/amd64 -p windows/amd64 -p linux/arm64 -p darwin/amd64 -p darwin/arm64 -p linux/386" @@ -173,7 +173,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 + - uses: prometheus/promci@c0916f0a41f13444612a8f0f5e700ea34edd7c19 # v0.5.3 - uses: ./.github/promci/actions/build with: parallelism: 12 @@ -268,7 +268,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 + - uses: prometheus/promci@c0916f0a41f13444612a8f0f5e700ea34edd7c19 # v0.5.3 - uses: ./.github/promci/actions/publish_main with: docker_hub_login: ${{ secrets.docker_hub_login }} @@ -287,7 +287,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 + - uses: prometheus/promci@c0916f0a41f13444612a8f0f5e700ea34edd7c19 # v0.5.3 - uses: ./.github/promci/actions/publish_release with: docker_hub_login: ${{ secrets.docker_hub_login }} @@ -304,7 +304,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - uses: prometheus/promci@bb1909986b91b37c4104dd742c4684f43cf1b260 # v0.5.2 + - uses: prometheus/promci@c0916f0a41f13444612a8f0f5e700ea34edd7c19 # v0.5.3 - name: Install nodejs uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: From 3bcc88b053e7d772b8c8d7e38745c10ceb42a985 Mon Sep 17 00:00:00 2001 From: Bartlomiej Plotka Date: Mon, 17 Nov 2025 15:59:40 +0100 Subject: [PATCH 08/14] prw2: Move Remote Write 2.0 CT to be per Sample; Rename to ST (start timestamp) (#17411) Relates to https://github.com/prometheus/prometheus/issues/16944#issuecomment-3164760343 Signed-off-by: bwplotka (cherry picked from commit cefefc689766827a8c933e3181e9dd548656e71a) --- prompb/io/prometheus/write/v2/custom.go | 5 - prompb/io/prometheus/write/v2/types.pb.go | 302 +++++++++++------- prompb/io/prometheus/write/v2/types.proto | 74 +++-- storage/remote/codec_test.go | 6 +- .../prometheusremotewrite/histograms.go | 4 +- storage/remote/write_handler.go | 49 ++- storage/remote/write_handler_test.go | 20 +- 7 files changed, 263 insertions(+), 197 deletions(-) diff --git a/prompb/io/prometheus/write/v2/custom.go b/prompb/io/prometheus/write/v2/custom.go index 3aa778eb60..5721aec532 100644 --- a/prompb/io/prometheus/write/v2/custom.go +++ b/prompb/io/prometheus/write/v2/custom.go @@ -80,11 +80,6 @@ func (m *TimeSeries) OptimizedMarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } - if m.CreatedTimestamp != 0 { - i = encodeVarintTypes(dAtA, i, uint64(m.CreatedTimestamp)) - i-- - dAtA[i] = 0x30 - } { size, err := m.Metadata.MarshalToSizedBuffer(dAtA[:i]) if err != nil { diff --git a/prompb/io/prometheus/write/v2/types.pb.go b/prompb/io/prometheus/write/v2/types.pb.go index 1419de217e..a726efb5b5 100644 --- a/prompb/io/prometheus/write/v2/types.pb.go +++ b/prompb/io/prometheus/write/v2/types.pb.go @@ -106,6 +106,8 @@ func (Histogram_ResetHint) EnumDescriptor() ([]byte, []int) { // The canonical Content-Type request header value for this message is // "application/x-protobuf;proto=io.prometheus.write.v2.Request" // +// Version: v2.0-rc.4 +// // NOTE: gogoproto options might change in future for this file, they // are not part of the spec proto (they only modify the generated Go code, not // the serialized message). See: https://github.com/prometheus/prometheus/issues/11908 @@ -181,7 +183,7 @@ type TimeSeries struct { // // Note that there might be multiple TimeSeries objects in the same // Requests with the same labels e.g. for different exemplars, metadata - // or created timestamp. + // or start timestamp. LabelsRefs []uint32 `protobuf:"varint,1,rep,packed,name=labels_refs,json=labelsRefs,proto3" json:"labels_refs,omitempty"` // Timeseries messages can either specify samples or (native) histogram samples // (histogram field), but not both. For a typical sender (real-time metric @@ -193,24 +195,7 @@ type TimeSeries struct { // exemplars represents an optional set of exemplars attached to this series' samples. Exemplars []Exemplar `protobuf:"bytes,4,rep,name=exemplars,proto3" json:"exemplars"` // metadata represents the metadata associated with the given series' samples. - Metadata Metadata `protobuf:"bytes,5,opt,name=metadata,proto3" json:"metadata"` - // created_timestamp represents an optional created timestamp associated with - // this series' samples in ms format, typically for counter or histogram type - // metrics. Created timestamp represents the time when the counter started - // counting (sometimes referred to as start timestamp), which can increase - // the accuracy of query results. - // - // Note that some receivers might require this and in return fail to - // ingest such samples within the Request. - // - // For Go, see github.com/prometheus/prometheus/model/timestamp/timestamp.go - // for conversion from/to time.Time to Prometheus timestamp. - // - // Note that the "optional" keyword is omitted due to - // https://cloud.google.com/apis/design/design_patterns.md#optional_primitive_fields - // Zero value means value not set. If you need to use exactly zero value for - // the timestamp, use 1 millisecond before or after. - CreatedTimestamp int64 `protobuf:"varint,6,opt,name=created_timestamp,json=createdTimestamp,proto3" json:"created_timestamp,omitempty"` + Metadata Metadata `protobuf:"bytes,5,opt,name=metadata,proto3" json:"metadata"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -284,13 +269,6 @@ func (m *TimeSeries) GetMetadata() Metadata { return Metadata{} } -func (m *TimeSeries) GetCreatedTimestamp() int64 { - if m != nil { - return m.CreatedTimestamp - } - return 0 -} - // Exemplar is an additional information attached to some series' samples. // It is typically used to attach an example trace or request ID associated with // the metric changes. @@ -375,7 +353,27 @@ type Sample struct { // // For Go, see github.com/prometheus/prometheus/model/timestamp/timestamp.go // for conversion from/to time.Time to Prometheus timestamp. - Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // start_timestamp represents an optional start timestamp for the sample, + // in ms format. This information is typically used for counter, histogram (cumulative) + // or delta type metrics. + // + // For cumulative metrics, the start timestamp represents the time when the + // counter started counting (sometimes referred to as start timestamp), which + // can increase the accuracy of certain processing and query semantics (e.g. rates). + // + // Note: + // * That some receivers might require start timestamps for certain metric + // types; rejecting such samples within the Request as a result. + // * start timestamp is the same as "created timestamp" name Prometheus used in the past. + // + // For Go, see github.com/prometheus/prometheus/model/timestamp/timestamp.go + // for conversion from/to time.Time to Prometheus timestamp. + // + // Note that the "optional" keyword is omitted due to efficiency and consistency. + // Zero value means value not set. If you need to use exactly zero value for + // the timestamp, use 1 millisecond before or after. + StartTimestamp int64 `protobuf:"varint,3,opt,name=start_timestamp,json=startTimestamp,proto3" json:"start_timestamp,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -428,6 +426,13 @@ func (m *Sample) GetTimestamp() int64 { return 0 } +func (m *Sample) GetStartTimestamp() int64 { + if m != nil { + return m.StartTimestamp + } + return 0 +} + // Metadata represents the metadata associated with the given series' samples. type Metadata struct { Type Metadata_MetricType `protobuf:"varint,1,opt,name=type,proto3,enum=io.prometheus.write.v2.Metadata_MetricType" json:"type,omitempty"` @@ -498,12 +503,11 @@ func (m *Metadata) GetUnitRef() uint32 { return 0 } -// A native histogram, also known as a sparse histogram. -// Original design doc: -// https://docs.google.com/document/d/1cLNv3aufPZb3fNfaJgdaRBZsInZKKIHo9E6HinJVbpM/edit -// The appendix of this design doc also explains the concept of float -// histograms. This Histogram message can represent both, the usual -// integer histogram as well as a float histogram. +// A native histogram message, supporting +// * sparse exponential bucketing, custom bucketing. +// * float or integer histograms. +// +// See the full spec: https://prometheus.io/docs/specs/native_histograms/ type Histogram struct { // Types that are valid to be assigned to Count: // @@ -581,10 +585,27 @@ type Histogram struct { // // The last element is not only the upper inclusive bound of the last regular // bucket, but implicitly the lower exclusive bound of the +Inf bucket. - CustomValues []float64 `protobuf:"fixed64,16,rep,packed,name=custom_values,json=customValues,proto3" json:"custom_values,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + CustomValues []float64 `protobuf:"fixed64,16,rep,packed,name=custom_values,json=customValues,proto3" json:"custom_values,omitempty"` + // start_timestamp represents an optional start timestamp for the histogram sample, + // in ms format. The start timestamp represents the time when the histogram + // started counting, which can increase the accuracy of certain processing and + // query semantics (e.g. rates). + // + // Note: + // * That some receivers might require start timestamps for certain metric + // types; rejecting such samples within the Request as a result. + // * start timestamp is the same as "created timestamp" name Prometheus used in the past. + // + // For Go, see github.com/prometheus/prometheus/model/timestamp/timestamp.go + // for conversion from/to time.Time to Prometheus timestamp. + // + // Note that the "optional" keyword is omitted due to efficiency and consistency. + // Zero value means value not set. If you need to use exactly zero value for + // the timestamp, use 1 millisecond before or after. + StartTimestamp int64 `protobuf:"varint,17,opt,name=start_timestamp,json=startTimestamp,proto3" json:"start_timestamp,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *Histogram) Reset() { *m = Histogram{} } @@ -774,6 +795,13 @@ func (m *Histogram) GetCustomValues() []float64 { return nil } +func (m *Histogram) GetStartTimestamp() int64 { + if m != nil { + return m.StartTimestamp + } + return 0 +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*Histogram) XXX_OneofWrappers() []interface{} { return []interface{}{ @@ -861,65 +889,66 @@ func init() { } var fileDescriptor_f139519efd9fa8d7 = []byte{ - // 926 bytes of a gzipped FileDescriptorProto + // 931 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0x5d, 0x6f, 0xe3, 0x44, - 0x14, 0xed, 0xc4, 0x69, 0x3e, 0x6e, 0x9a, 0xac, 0x33, 0xb4, 0x5d, 0x6f, 0x81, 0x6c, 0xd6, 0x08, - 0x88, 0x58, 0x29, 0x91, 0xc2, 0xeb, 0x0a, 0xd4, 0xb4, 0x6e, 0x93, 0x95, 0x92, 0xac, 0x26, 0x2e, - 0x52, 0x79, 0xb1, 0xdc, 0x64, 0x92, 0x58, 0xd8, 0xb1, 0xf1, 0x4c, 0x02, 0xe5, 0xf7, 0xf1, 0xb0, - 0x8f, 0xfc, 0x01, 0x10, 0xf4, 0x9d, 0xff, 0x80, 0x66, 0xfc, 0xd9, 0x42, 0xbb, 0xe2, 0x6d, 0xe6, - 0xdc, 0x73, 0xee, 0x3d, 0xb9, 0xbe, 0x77, 0x02, 0xba, 0xe3, 0xf7, 0x82, 0xd0, 0xf7, 0x28, 0x5f, - 0xd3, 0x2d, 0xeb, 0xfd, 0x14, 0x3a, 0x9c, 0xf6, 0x76, 0xfd, 0x1e, 0xbf, 0x0d, 0x28, 0xeb, 0x06, - 0xa1, 0xcf, 0x7d, 0x7c, 0xec, 0xf8, 0xdd, 0x8c, 0xd3, 0x95, 0x9c, 0xee, 0xae, 0x7f, 0x72, 0xb8, - 0xf2, 0x57, 0xbe, 0xa4, 0xf4, 0xc4, 0x29, 0x62, 0xeb, 0x0c, 0xca, 0x84, 0xfe, 0xb8, 0xa5, 0x8c, - 0x63, 0x0d, 0xca, 0xec, 0xd6, 0xbb, 0xf1, 0x5d, 0xa6, 0x15, 0xdb, 0x4a, 0xa7, 0x4a, 0x92, 0x2b, - 0x1e, 0x02, 0x70, 0xc7, 0xa3, 0x8c, 0x86, 0x0e, 0x65, 0xda, 0x7e, 0x5b, 0xe9, 0xd4, 0xfa, 0x7a, - 0xf7, 0xbf, 0xeb, 0x74, 0x4d, 0xc7, 0xa3, 0x33, 0xc9, 0x1c, 0x14, 0xdf, 0xff, 0xf1, 0x72, 0x8f, - 0xe4, 0xb4, 0x6f, 0x8b, 0x15, 0xa4, 0x16, 0xf5, 0xbf, 0x0b, 0x00, 0x19, 0x0d, 0xbf, 0x84, 0x9a, - 0x6b, 0xdf, 0x50, 0x97, 0x59, 0x21, 0x5d, 0x32, 0x0d, 0xb5, 0x95, 0x4e, 0x9d, 0x40, 0x04, 0x11, - 0xba, 0x64, 0xf8, 0x1b, 0x28, 0x33, 0xdb, 0x0b, 0x5c, 0xca, 0xb4, 0x82, 0x2c, 0xde, 0x7a, 0xac, - 0xf8, 0x4c, 0xd2, 0xe2, 0xc2, 0x89, 0x08, 0x5f, 0x02, 0xac, 0x1d, 0xc6, 0xfd, 0x55, 0x68, 0x7b, - 0x4c, 0x53, 0x64, 0x8a, 0x57, 0x8f, 0xa5, 0x18, 0x26, 0xcc, 0xc4, 0x7e, 0x26, 0xc5, 0xe7, 0x50, - 0xa5, 0x3f, 0x53, 0x2f, 0x70, 0xed, 0x30, 0x6a, 0x52, 0xad, 0xdf, 0x7e, 0x2c, 0x8f, 0x11, 0x13, - 0xe3, 0x34, 0x99, 0x10, 0x0f, 0xa0, 0xe2, 0x51, 0x6e, 0x2f, 0x6c, 0x6e, 0x6b, 0xfb, 0x6d, 0xf4, - 0x54, 0x92, 0x71, 0xcc, 0x8b, 0x93, 0xa4, 0x3a, 0xfc, 0x1a, 0x9a, 0xf3, 0x90, 0xda, 0x9c, 0x2e, - 0x2c, 0xd9, 0x5e, 0x6e, 0x7b, 0x81, 0x56, 0x6a, 0xa3, 0x8e, 0x42, 0xd4, 0x38, 0x60, 0x26, 0xb8, - 0x6e, 0x41, 0x25, 0x71, 0xf3, 0xe1, 0x66, 0x1f, 0xc2, 0xfe, 0xce, 0x76, 0xb7, 0x54, 0x2b, 0xb4, - 0x51, 0x07, 0x91, 0xe8, 0x82, 0x3f, 0x81, 0x6a, 0x56, 0x47, 0x91, 0x75, 0x32, 0x40, 0x7f, 0x03, - 0xa5, 0xa8, 0xf3, 0x99, 0x1a, 0x3d, 0xaa, 0x2e, 0x3c, 0x54, 0xff, 0x55, 0x80, 0x4a, 0xf2, 0x43, - 0xf1, 0xb7, 0x50, 0x14, 0xd3, 0x2c, 0xf5, 0x8d, 0xfe, 0xeb, 0x0f, 0x35, 0x46, 0x1c, 0x42, 0x67, - 0x6e, 0xde, 0x06, 0x94, 0x48, 0x21, 0x7e, 0x01, 0x95, 0x35, 0x75, 0x03, 0xf1, 0xf3, 0xa4, 0xd1, - 0x3a, 0x29, 0x8b, 0x3b, 0xa1, 0x4b, 0x11, 0xda, 0x6e, 0x1c, 0x2e, 0x43, 0xc5, 0x28, 0x24, 0xee, - 0x84, 0x2e, 0xf5, 0xdf, 0x11, 0x40, 0x96, 0x0a, 0x7f, 0x0c, 0xcf, 0xc7, 0x86, 0x49, 0x46, 0x67, - 0x96, 0x79, 0xfd, 0xce, 0xb0, 0xae, 0x26, 0xb3, 0x77, 0xc6, 0xd9, 0xe8, 0x62, 0x64, 0x9c, 0xab, - 0x7b, 0xf8, 0x39, 0x7c, 0x94, 0x0f, 0x9e, 0x4d, 0xaf, 0x26, 0xa6, 0x41, 0x54, 0x84, 0x8f, 0xa0, - 0x99, 0x0f, 0x5c, 0x9e, 0x5e, 0x5d, 0x1a, 0x6a, 0x01, 0xbf, 0x80, 0xa3, 0x3c, 0x3c, 0x1c, 0xcd, - 0xcc, 0xe9, 0x25, 0x39, 0x1d, 0xab, 0x0a, 0x6e, 0xc1, 0xc9, 0xbf, 0x14, 0x59, 0xbc, 0xf8, 0xb0, - 0xd4, 0xec, 0x6a, 0x3c, 0x3e, 0x25, 0xd7, 0xea, 0x3e, 0x3e, 0x04, 0x35, 0x1f, 0x18, 0x4d, 0x2e, - 0xa6, 0x6a, 0x09, 0x6b, 0x70, 0x78, 0x8f, 0x6e, 0x9e, 0x9a, 0xc6, 0xcc, 0x30, 0xd5, 0xb2, 0xfe, - 0x6b, 0x09, 0xaa, 0xe9, 0x64, 0xe3, 0x4f, 0xa1, 0x3a, 0xf7, 0xb7, 0x1b, 0x6e, 0x39, 0x1b, 0x2e, - 0x3b, 0x5d, 0x1c, 0xee, 0x91, 0x8a, 0x84, 0x46, 0x1b, 0x8e, 0x5f, 0x41, 0x2d, 0x0a, 0x2f, 0x5d, - 0xdf, 0xe6, 0xd1, 0x20, 0x0c, 0xf7, 0x08, 0x48, 0xf0, 0x42, 0x60, 0x58, 0x05, 0x85, 0x6d, 0x3d, - 0xd9, 0x60, 0x44, 0xc4, 0x11, 0x1f, 0x43, 0x89, 0xcd, 0xd7, 0xd4, 0xb3, 0x65, 0x6b, 0x9b, 0x24, - 0xbe, 0xe1, 0xcf, 0xa1, 0xf1, 0x0b, 0x0d, 0x7d, 0x8b, 0xaf, 0x43, 0xca, 0xd6, 0xbe, 0xbb, 0x90, - 0x33, 0x8f, 0x48, 0x5d, 0xa0, 0x66, 0x02, 0xe2, 0x2f, 0x62, 0x5a, 0xe6, 0xab, 0x24, 0x7d, 0x21, - 0x72, 0x20, 0xf0, 0xb3, 0xc4, 0xdb, 0x57, 0xa0, 0xe6, 0x78, 0x91, 0xc1, 0xb2, 0x34, 0x88, 0x48, - 0x23, 0x65, 0x46, 0x26, 0xa7, 0xd0, 0xd8, 0xd0, 0x95, 0xcd, 0x9d, 0x1d, 0xb5, 0x58, 0x60, 0x6f, - 0x98, 0x56, 0x79, 0xfa, 0xed, 0x1a, 0x6c, 0xe7, 0x3f, 0x50, 0x3e, 0x0b, 0xec, 0x4d, 0xbc, 0x70, - 0xf5, 0x44, 0x2f, 0x30, 0x86, 0xbf, 0x84, 0x67, 0x69, 0xc2, 0x05, 0x75, 0xb9, 0xcd, 0xb4, 0x6a, - 0x5b, 0xe9, 0x60, 0x92, 0xd6, 0x39, 0x97, 0xe8, 0x3d, 0xa2, 0x74, 0xca, 0x34, 0x68, 0x2b, 0x1d, - 0x94, 0x11, 0xa5, 0x4d, 0x26, 0x2c, 0x06, 0x3e, 0x73, 0x72, 0x16, 0x6b, 0xff, 0xd7, 0x62, 0xa2, - 0x4f, 0x2d, 0xa6, 0x09, 0x63, 0x8b, 0x07, 0x91, 0xc5, 0x04, 0xce, 0x2c, 0xa6, 0xc4, 0xd8, 0x62, - 0x3d, 0xb2, 0x98, 0xc0, 0xb1, 0xc5, 0xb7, 0x00, 0x21, 0x65, 0x94, 0x5b, 0x6b, 0xf1, 0x55, 0x1a, - 0x4f, 0xef, 0x65, 0x3a, 0x63, 0x5d, 0x22, 0x34, 0x43, 0x67, 0xc3, 0x49, 0x35, 0x4c, 0x8e, 0xf7, - 0x1f, 0x82, 0x67, 0x0f, 0x1e, 0x02, 0xfc, 0x19, 0xd4, 0xe7, 0x5b, 0xc6, 0x7d, 0xcf, 0x92, 0xcf, - 0x06, 0xd3, 0x54, 0x69, 0xe8, 0x20, 0x02, 0xbf, 0x93, 0x98, 0xbe, 0x80, 0x6a, 0x9a, 0x1a, 0x9f, - 0xc0, 0x31, 0x11, 0x13, 0x6e, 0x0d, 0x47, 0x13, 0xf3, 0xc1, 0x9a, 0x62, 0x68, 0xe4, 0x62, 0xd7, - 0xc6, 0x4c, 0x45, 0xb8, 0x09, 0xf5, 0x1c, 0x36, 0x99, 0xaa, 0x05, 0xb1, 0x49, 0x39, 0x28, 0xda, - 0x59, 0x65, 0x50, 0x86, 0x7d, 0xd9, 0x94, 0xc1, 0x01, 0x40, 0x36, 0x6f, 0xfa, 0x1b, 0x80, 0xec, - 0x03, 0x88, 0x91, 0xf7, 0x97, 0x4b, 0x46, 0xa3, 0x1d, 0x6a, 0x92, 0xf8, 0x26, 0x70, 0x97, 0x6e, - 0x56, 0x7c, 0x2d, 0x57, 0xa7, 0x4e, 0xe2, 0xdb, 0xe0, 0xe8, 0xfd, 0x5d, 0x0b, 0xfd, 0x76, 0xd7, - 0x42, 0x7f, 0xde, 0xb5, 0xd0, 0xf7, 0x65, 0xd9, 0xb4, 0x5d, 0xff, 0xa6, 0x24, 0xff, 0x8a, 0xbf, - 0xfe, 0x27, 0x00, 0x00, 0xff, 0xff, 0x3e, 0xfc, 0x93, 0x1c, 0xde, 0x07, 0x00, 0x00, + 0x14, 0xed, 0xc4, 0xf9, 0xbc, 0x69, 0xb2, 0xce, 0xd0, 0x76, 0xbd, 0x05, 0xb2, 0xd9, 0x20, 0x20, + 0x02, 0x29, 0x91, 0xc2, 0x2b, 0x02, 0x35, 0xad, 0xdb, 0xa4, 0x52, 0x92, 0xd5, 0xc4, 0x45, 0x2a, + 0x2f, 0x96, 0x9b, 0x4e, 0x12, 0x0b, 0x3b, 0x36, 0x9e, 0x49, 0xa0, 0xfc, 0x40, 0xb4, 0x8f, 0xfc, + 0x01, 0x10, 0xf4, 0x9d, 0xff, 0x80, 0x66, 0xfc, 0xd9, 0xd0, 0x76, 0xb5, 0x6f, 0x33, 0xe7, 0x9e, + 0x73, 0xef, 0xc9, 0xf5, 0xbd, 0x13, 0x68, 0xdb, 0x5e, 0xcf, 0x0f, 0x3c, 0x97, 0xf2, 0x15, 0xdd, + 0xb0, 0xde, 0x2f, 0x81, 0xcd, 0x69, 0x6f, 0xdb, 0xef, 0xf1, 0x3b, 0x9f, 0xb2, 0xae, 0x1f, 0x78, + 0xdc, 0xc3, 0x47, 0xb6, 0xd7, 0x4d, 0x39, 0x5d, 0xc9, 0xe9, 0x6e, 0xfb, 0xc7, 0x07, 0x4b, 0x6f, + 0xe9, 0x49, 0x4a, 0x4f, 0x9c, 0x42, 0x76, 0x9b, 0x41, 0x89, 0xd0, 0x9f, 0x37, 0x94, 0x71, 0xac, + 0x41, 0x89, 0xdd, 0xb9, 0x37, 0x9e, 0xc3, 0xb4, 0x7c, 0x4b, 0xe9, 0x54, 0x48, 0x7c, 0xc5, 0x43, + 0x00, 0x6e, 0xbb, 0x94, 0xd1, 0xc0, 0xa6, 0x4c, 0x2b, 0xb4, 0x94, 0x4e, 0xb5, 0xdf, 0xee, 0x3e, + 0x5e, 0xa7, 0x6b, 0xd8, 0x2e, 0x9d, 0x49, 0xe6, 0x20, 0xff, 0xee, 0xaf, 0xd7, 0x7b, 0x24, 0xa3, + 0xbd, 0xcc, 0x97, 0x91, 0x9a, 0x6f, 0xff, 0x9e, 0x03, 0x48, 0x69, 0xf8, 0x35, 0x54, 0x1d, 0xeb, + 0x86, 0x3a, 0xcc, 0x0c, 0xe8, 0x82, 0x69, 0xa8, 0xa5, 0x74, 0x6a, 0x04, 0x42, 0x88, 0xd0, 0x05, + 0xc3, 0xdf, 0x41, 0x89, 0x59, 0xae, 0xef, 0x50, 0xa6, 0xe5, 0x64, 0xf1, 0xe6, 0x53, 0xc5, 0x67, + 0x92, 0x16, 0x15, 0x8e, 0x45, 0xf8, 0x02, 0x60, 0x65, 0x33, 0xee, 0x2d, 0x03, 0xcb, 0x65, 0x9a, + 0x22, 0x53, 0xbc, 0x79, 0x2a, 0xc5, 0x30, 0x66, 0xc6, 0xf6, 0x53, 0x29, 0x3e, 0x83, 0x0a, 0xfd, + 0x95, 0xba, 0xbe, 0x63, 0x05, 0x61, 0x93, 0xaa, 0xfd, 0xd6, 0x53, 0x79, 0xf4, 0x88, 0x18, 0xa5, + 0x49, 0x85, 0x78, 0x00, 0x65, 0x97, 0x72, 0xeb, 0xd6, 0xe2, 0x96, 0x56, 0x68, 0xa1, 0xe7, 0x92, + 0x8c, 0x23, 0x5e, 0x94, 0x24, 0xd1, 0x5d, 0xe6, 0xcb, 0x45, 0xb5, 0xd4, 0x36, 0xa1, 0x1c, 0x97, + 0x79, 0x7f, 0x17, 0x0f, 0xa0, 0xb0, 0xb5, 0x9c, 0x0d, 0xd5, 0x72, 0x2d, 0xd4, 0x41, 0x24, 0xbc, + 0xe0, 0x4f, 0xa0, 0x22, 0xbf, 0x0f, 0xb7, 0x5c, 0x5f, 0x53, 0x5a, 0xa8, 0xa3, 0x90, 0x14, 0x68, + 0x53, 0x28, 0x86, 0x2d, 0x4d, 0xd5, 0xe8, 0x49, 0x75, 0x6e, 0x47, 0x8d, 0xbf, 0x84, 0x17, 0x8c, + 0x5b, 0x01, 0x37, 0x77, 0x2b, 0xd4, 0x25, 0x6c, 0x24, 0x65, 0xfe, 0xc9, 0x41, 0x39, 0xfe, 0xa9, + 0xf8, 0x7b, 0xc8, 0x8b, 0x79, 0x96, 0x85, 0xea, 0xfd, 0xaf, 0xdf, 0xd7, 0x1a, 0x71, 0x08, 0xec, + 0xb9, 0x71, 0xe7, 0x53, 0x22, 0x85, 0xf8, 0x15, 0x94, 0x57, 0xd4, 0xf1, 0x45, 0x1f, 0x64, 0xbd, + 0x1a, 0x29, 0x89, 0x3b, 0xa1, 0x0b, 0x11, 0xda, 0xac, 0x6d, 0x2e, 0x43, 0xf9, 0x30, 0x24, 0xee, + 0x84, 0x2e, 0xda, 0x7f, 0x22, 0x80, 0x34, 0x15, 0xfe, 0x18, 0x5e, 0x8e, 0x75, 0x83, 0x8c, 0x4e, + 0x4d, 0xe3, 0xfa, 0xad, 0x6e, 0x5e, 0x4d, 0x66, 0x6f, 0xf5, 0xd3, 0xd1, 0xf9, 0x48, 0x3f, 0x53, + 0xf7, 0xf0, 0x4b, 0xf8, 0x28, 0x1b, 0x3c, 0x9d, 0x5e, 0x4d, 0x0c, 0x9d, 0xa8, 0x08, 0x1f, 0x42, + 0x23, 0x1b, 0xb8, 0x38, 0xb9, 0xba, 0xd0, 0xd5, 0x1c, 0x7e, 0x05, 0x87, 0x59, 0x78, 0x38, 0x9a, + 0x19, 0xd3, 0x0b, 0x72, 0x32, 0x56, 0x15, 0xdc, 0x84, 0xe3, 0xff, 0x29, 0xd2, 0x78, 0x7e, 0xb7, + 0xd4, 0xec, 0x6a, 0x3c, 0x3e, 0x21, 0xd7, 0x6a, 0x01, 0x1f, 0x80, 0x9a, 0x0d, 0x8c, 0x26, 0xe7, + 0x53, 0xb5, 0x88, 0x35, 0x38, 0x78, 0x40, 0x37, 0x4e, 0x0c, 0x7d, 0xa6, 0x1b, 0x6a, 0xa9, 0xfd, + 0x6f, 0x11, 0x2a, 0xc9, 0x6c, 0xe3, 0x4f, 0xa1, 0x32, 0xf7, 0x36, 0x6b, 0x6e, 0xda, 0x6b, 0x2e, + 0x3b, 0x9d, 0x1f, 0xee, 0x91, 0xb2, 0x84, 0x46, 0x6b, 0x8e, 0xdf, 0x40, 0x35, 0x0c, 0x2f, 0x1c, + 0xcf, 0xe2, 0xe1, 0xc4, 0x0c, 0xf7, 0x08, 0x48, 0xf0, 0x5c, 0x60, 0x58, 0x05, 0x85, 0x6d, 0x5c, + 0xd9, 0x60, 0x44, 0xc4, 0x11, 0x1f, 0x41, 0x91, 0xcd, 0x57, 0xd4, 0xb5, 0x64, 0x6b, 0x1b, 0x24, + 0xba, 0xe1, 0xcf, 0xa1, 0xfe, 0x1b, 0x0d, 0x3c, 0x93, 0xaf, 0x02, 0xca, 0x56, 0x9e, 0x73, 0x2b, + 0xa7, 0x1e, 0x91, 0x9a, 0x40, 0x8d, 0x18, 0xc4, 0x5f, 0x44, 0xb4, 0xd4, 0x57, 0x51, 0xfa, 0x42, + 0x64, 0x5f, 0xe0, 0xa7, 0xb1, 0xb7, 0xaf, 0x40, 0xcd, 0xf0, 0x42, 0x83, 0x25, 0x69, 0x10, 0x91, + 0x7a, 0xc2, 0x0c, 0x4d, 0x4e, 0xa1, 0xbe, 0xa6, 0x4b, 0x8b, 0xdb, 0x5b, 0x6a, 0x32, 0xdf, 0x5a, + 0x33, 0xad, 0xfc, 0xfc, 0xeb, 0x35, 0xd8, 0xcc, 0x7f, 0xa2, 0x7c, 0xe6, 0x5b, 0xeb, 0x68, 0xe5, + 0x6a, 0xb1, 0x5e, 0x60, 0x4c, 0x8c, 0x74, 0x92, 0xf0, 0x96, 0x3a, 0xdc, 0x62, 0x5a, 0xa5, 0xa5, + 0x74, 0x30, 0x49, 0xea, 0x9c, 0x49, 0xf4, 0x01, 0x51, 0x3a, 0x65, 0x1a, 0xb4, 0x94, 0x0e, 0x4a, + 0x89, 0xd2, 0x26, 0x13, 0x16, 0x7d, 0x8f, 0xd9, 0x19, 0x8b, 0xd5, 0x0f, 0xb5, 0x18, 0xeb, 0x13, + 0x8b, 0x49, 0xc2, 0xc8, 0xe2, 0x7e, 0x68, 0x31, 0x86, 0x53, 0x8b, 0x09, 0x31, 0xb2, 0x58, 0x0b, + 0x2d, 0xc6, 0x70, 0x64, 0xf1, 0x12, 0x20, 0xa0, 0x8c, 0x72, 0x73, 0x25, 0xbe, 0x4a, 0xfd, 0xf9, + 0xbd, 0x4c, 0x66, 0xac, 0x4b, 0x84, 0x66, 0x68, 0xaf, 0x39, 0xa9, 0x04, 0xf1, 0xf1, 0xe1, 0x8b, + 0xf1, 0x62, 0xf7, 0xc5, 0xf8, 0x0c, 0x6a, 0xf3, 0x0d, 0xe3, 0x9e, 0x6b, 0xca, 0xf7, 0x85, 0x69, + 0xaa, 0x34, 0xb4, 0x1f, 0x82, 0x3f, 0x48, 0xec, 0xb1, 0x67, 0xa5, 0xf1, 0xe8, 0xb3, 0x72, 0x0b, + 0x95, 0xc4, 0x03, 0x3e, 0x86, 0x23, 0x22, 0x56, 0xc1, 0x1c, 0x8e, 0x26, 0xc6, 0xce, 0x3e, 0x63, + 0xa8, 0x67, 0x62, 0xd7, 0xfa, 0x4c, 0x45, 0xb8, 0x01, 0xb5, 0x0c, 0x36, 0x99, 0xaa, 0x39, 0xb1, + 0x72, 0x19, 0x28, 0x5c, 0x6e, 0x65, 0x50, 0x82, 0x82, 0xec, 0xde, 0x60, 0x1f, 0x20, 0x1d, 0xcc, + 0xf6, 0xb7, 0x00, 0xe9, 0x97, 0x12, 0xbb, 0xe1, 0x2d, 0x16, 0x8c, 0x86, 0xcb, 0xd6, 0x20, 0xd1, + 0x4d, 0xe0, 0x0e, 0x5d, 0x2f, 0xf9, 0x4a, 0xee, 0x58, 0x8d, 0x44, 0xb7, 0xc1, 0xe1, 0xbb, 0xfb, + 0x26, 0xfa, 0xe3, 0xbe, 0x89, 0xfe, 0xbe, 0x6f, 0xa2, 0x1f, 0x4b, 0xb2, 0xbb, 0xdb, 0xfe, 0x4d, + 0x51, 0xfe, 0x6b, 0x7f, 0xf3, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x62, 0x8f, 0x36, 0x4b, 0x09, + 0x08, 0x00, 0x00, } func (m *Request) Marshal() (dAtA []byte, err error) { @@ -996,11 +1025,6 @@ func (m *TimeSeries) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } - if m.CreatedTimestamp != 0 { - i = encodeVarintTypes(dAtA, i, uint64(m.CreatedTimestamp)) - i-- - dAtA[i] = 0x30 - } { size, err := m.Metadata.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -1154,6 +1178,11 @@ func (m *Sample) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.StartTimestamp != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.StartTimestamp)) + i-- + dAtA[i] = 0x18 + } if m.Timestamp != 0 { i = encodeVarintTypes(dAtA, i, uint64(m.Timestamp)) i-- @@ -1234,6 +1263,13 @@ func (m *Histogram) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.StartTimestamp != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.StartTimestamp)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x88 + } if len(m.CustomValues) > 0 { for iNdEx := len(m.CustomValues) - 1; iNdEx >= 0; iNdEx-- { f6 := math.Float64bits(float64(m.CustomValues[iNdEx])) @@ -1535,9 +1571,6 @@ func (m *TimeSeries) Size() (n int) { } l = m.Metadata.Size() n += 1 + l + sovTypes(uint64(l)) - if m.CreatedTimestamp != 0 { - n += 1 + sovTypes(uint64(m.CreatedTimestamp)) - } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -1581,6 +1614,9 @@ func (m *Sample) Size() (n int) { if m.Timestamp != 0 { n += 1 + sovTypes(uint64(m.Timestamp)) } + if m.StartTimestamp != 0 { + n += 1 + sovTypes(uint64(m.StartTimestamp)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -1670,6 +1706,9 @@ func (m *Histogram) Size() (n int) { if len(m.CustomValues) > 0 { n += 2 + sovTypes(uint64(len(m.CustomValues)*8)) + len(m.CustomValues)*8 } + if m.StartTimestamp != 0 { + n += 2 + sovTypes(uint64(m.StartTimestamp)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -2093,25 +2132,6 @@ func (m *TimeSeries) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field CreatedTimestamp", wireType) - } - m.CreatedTimestamp = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.CreatedTimestamp |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -2350,6 +2370,25 @@ func (m *Sample) Unmarshal(dAtA []byte) error { break } } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field StartTimestamp", wireType) + } + m.StartTimestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.StartTimestamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -3038,6 +3077,25 @@ func (m *Histogram) Unmarshal(dAtA []byte) error { } else { return fmt.Errorf("proto: wrong wireType = %d for field CustomValues", wireType) } + case 17: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field StartTimestamp", wireType) + } + m.StartTimestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.StartTimestamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) diff --git a/prompb/io/prometheus/write/v2/types.proto b/prompb/io/prometheus/write/v2/types.proto index ff6c4936bb..c1ae04d206 100644 --- a/prompb/io/prometheus/write/v2/types.proto +++ b/prompb/io/prometheus/write/v2/types.proto @@ -14,6 +14,7 @@ // NOTE: This file is also available on https://buf.build/prometheus/prometheus/docs/main:io.prometheus.write.v2 syntax = "proto3"; + package io.prometheus.write.v2; option go_package = "writev2"; @@ -27,6 +28,8 @@ import "gogoproto/gogo.proto"; // The canonical Content-Type request header value for this message is // "application/x-protobuf;proto=io.prometheus.write.v2.Request" // +// Version: v2.0-rc.4 +// // NOTE: gogoproto options might change in future for this file, they // are not part of the spec proto (they only modify the generated Go code, not // the serialized message). See: https://github.com/prometheus/prometheus/issues/11908 @@ -59,7 +62,7 @@ message TimeSeries { // // Note that there might be multiple TimeSeries objects in the same // Requests with the same labels e.g. for different exemplars, metadata - // or created timestamp. + // or start timestamp. repeated uint32 labels_refs = 1; // Timeseries messages can either specify samples or (native) histogram samples @@ -76,23 +79,9 @@ message TimeSeries { // metadata represents the metadata associated with the given series' samples. Metadata metadata = 5 [(gogoproto.nullable) = false]; - // created_timestamp represents an optional created timestamp associated with - // this series' samples in ms format, typically for counter or histogram type - // metrics. Created timestamp represents the time when the counter started - // counting (sometimes referred to as start timestamp), which can increase - // the accuracy of query results. - // - // Note that some receivers might require this and in return fail to - // ingest such samples within the Request. - // - // For Go, see github.com/prometheus/prometheus/model/timestamp/timestamp.go - // for conversion from/to time.Time to Prometheus timestamp. - // - // Note that the "optional" keyword is omitted due to - // https://cloud.google.com/apis/design/design_patterns.md#optional_primitive_fields - // Zero value means value not set. If you need to use exactly zero value for - // the timestamp, use 1 millisecond before or after. - int64 created_timestamp = 6; + // This field is reserved for backward compatibility with the deprecated fields; + // previously present in the experimental remote write period. + reserved 6; } // Exemplar is an additional information attached to some series' samples. @@ -123,6 +112,26 @@ message Sample { // For Go, see github.com/prometheus/prometheus/model/timestamp/timestamp.go // for conversion from/to time.Time to Prometheus timestamp. int64 timestamp = 2; + // start_timestamp represents an optional start timestamp for the sample, + // in ms format. This information is typically used for counter, histogram (cumulative) + // or delta type metrics. + // + // For cumulative metrics, the start timestamp represents the time when the + // counter started counting (sometimes referred to as start timestamp), which + // can increase the accuracy of certain processing and query semantics (e.g. rates). + // + // Note: + // * That some receivers might require start timestamps for certain metric + // types; rejecting such samples within the Request as a result. + // * start timestamp is the same as "created timestamp" name Prometheus used in the past. + // + // For Go, see github.com/prometheus/prometheus/model/timestamp/timestamp.go + // for conversion from/to time.Time to Prometheus timestamp. + // + // Note that the "optional" keyword is omitted due to efficiency and consistency. + // Zero value means value not set. If you need to use exactly zero value for + // the timestamp, use 1 millisecond before or after. + int64 start_timestamp = 3; } // Metadata represents the metadata associated with the given series' samples. @@ -148,12 +157,11 @@ message Metadata { uint32 unit_ref = 4; } -// A native histogram, also known as a sparse histogram. -// Original design doc: -// https://docs.google.com/document/d/1cLNv3aufPZb3fNfaJgdaRBZsInZKKIHo9E6HinJVbpM/edit -// The appendix of this design doc also explains the concept of float -// histograms. This Histogram message can represent both, the usual -// integer histogram as well as a float histogram. +// A native histogram message, supporting +// * sparse exponential bucketing, custom bucketing. +// * float or integer histograms. +// +// See the full spec: https://prometheus.io/docs/specs/native_histograms/ message Histogram { enum ResetHint { RESET_HINT_UNSPECIFIED = 0; // Need to test for a counter reset explicitly. @@ -242,6 +250,24 @@ message Histogram { // The last element is not only the upper inclusive bound of the last regular // bucket, but implicitly the lower exclusive bound of the +Inf bucket. repeated double custom_values = 16; + + // start_timestamp represents an optional start timestamp for the histogram sample, + // in ms format. The start timestamp represents the time when the histogram + // started counting, which can increase the accuracy of certain processing and + // query semantics (e.g. rates). + // + // Note: + // * That some receivers might require start timestamps for certain metric + // types; rejecting such samples within the Request as a result. + // * start timestamp is the same as "created timestamp" name Prometheus used in the past. + // + // For Go, see github.com/prometheus/prometheus/model/timestamp/timestamp.go + // for conversion from/to time.Time to Prometheus timestamp. + // + // Note that the "optional" keyword is omitted due to efficiency and consistency. + // Zero value means value not set. If you need to use exactly zero value for + // the timestamp, use 1 millisecond before or after. + int64 start_timestamp = 17; } // A BucketSpan defines a number of consecutive buckets with their diff --git a/storage/remote/codec_test.go b/storage/remote/codec_test.go index ddf8f76cf6..ce3a09b878 100644 --- a/storage/remote/codec_test.go +++ b/storage/remote/codec_test.go @@ -114,7 +114,7 @@ var ( HelpRef: 15, // Symbolized writeV2RequestSeries1Metadata.Help. UnitRef: 16, // Symbolized writeV2RequestSeries1Metadata.Unit. }, - Samples: []writev2.Sample{{Value: 1, Timestamp: 10}}, + Samples: []writev2.Sample{{Value: 1, Timestamp: 10, StartTimestamp: 1}}, // ST needs to be lower than the sample's timestamp. Exemplars: []writev2.Exemplar{{LabelsRefs: []uint32{11, 12}, Value: 1, Timestamp: 10}}, Histograms: []writev2.Histogram{ writev2.FromIntHistogram(10, &testHistogram), @@ -122,7 +122,6 @@ var ( writev2.FromIntHistogram(30, &testHistogramCustomBuckets), writev2.FromFloatHistogram(40, testHistogramCustomBuckets.ToFloat(nil)), }, - CreatedTimestamp: 1, // CT needs to be lower than the sample's timestamp. }, { LabelsRefs: []uint32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, // Same series as first. @@ -182,7 +181,7 @@ func TestWriteV2RequestFixture(t *testing.T) { HelpRef: st.Symbolize(writeV2RequestSeries1Metadata.Help), UnitRef: st.Symbolize(writeV2RequestSeries1Metadata.Unit), }, - Samples: []writev2.Sample{{Value: 1, Timestamp: 10}}, + Samples: []writev2.Sample{{Value: 1, Timestamp: 10, StartTimestamp: 1}}, Exemplars: []writev2.Exemplar{{LabelsRefs: exemplar1LabelRefs, Value: 1, Timestamp: 10}}, Histograms: []writev2.Histogram{ writev2.FromIntHistogram(10, &testHistogram), @@ -190,7 +189,6 @@ func TestWriteV2RequestFixture(t *testing.T) { writev2.FromIntHistogram(30, &testHistogramCustomBuckets), writev2.FromFloatHistogram(40, testHistogramCustomBuckets.ToFloat(nil)), }, - CreatedTimestamp: 1, }, { LabelsRefs: labelRefs, diff --git a/storage/remote/otlptranslator/prometheusremotewrite/histograms.go b/storage/remote/otlptranslator/prometheusremotewrite/histograms.go index 0bc8a876e4..5606fa4d91 100644 --- a/storage/remote/otlptranslator/prometheusremotewrite/histograms.go +++ b/storage/remote/otlptranslator/prometheusremotewrite/histograms.go @@ -106,7 +106,7 @@ func exponentialToNativeHistogram(p pmetric.ExponentialHistogramDataPoint, tempo // Sending a sample that triggers counter reset but with ResetHint==NO // would lead to Prometheus panic as it does not double check the hint. // Thus we're explicitly saying UNKNOWN here, which is always safe. - // TODO: using created time stamp should be accurate, but we + // TODO: using start timestamp should be accurate, but we // need to know here if it was used for the detection. // Ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/28663#issuecomment-1810577303 // Counter reset detection in Prometheus: https://github.com/prometheus/prometheus/blob/f997c72f294c0f18ca13fa06d51889af04135195/tsdb/chunkenc/histogram.go#L232 @@ -312,7 +312,7 @@ func explicitHistogramToCustomBucketsHistogram(p pmetric.HistogramDataPoint, tem // Sending a sample that triggers counter reset but with ResetHint==NO // would lead to Prometheus panic as it does not double check the hint. // Thus we're explicitly saying UNKNOWN here, which is always safe. - // TODO: using created time stamp should be accurate, but we + // TODO: using start timestamp should be accurate, but we // need to know here if it was used for the detection. // Ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/28663#issuecomment-1810577303 // Counter reset detection in Prometheus: https://github.com/prometheus/prometheus/blob/f997c72f294c0f18ca13fa06d51889af04135195/tsdb/chunkenc/histogram.go#L232 diff --git a/storage/remote/write_handler.go b/storage/remote/write_handler.go index e8559dd00e..f8296b4a80 100644 --- a/storage/remote/write_handler.go +++ b/storage/remote/write_handler.go @@ -353,20 +353,18 @@ func (h *writeHandler) appendV2(app storage.Appender, req *writev2.Request, rs * allSamplesSoFar := rs.AllSamples() var ref storage.SeriesRef - - // Samples. - if h.ingestCTZeroSample && len(ts.Samples) > 0 && ts.Samples[0].Timestamp != 0 && ts.CreatedTimestamp != 0 { - // CT only needs to be ingested for the first sample, it will be considered - // out of order for the rest. - ref, err = app.AppendCTZeroSample(ref, ls, ts.Samples[0].Timestamp, ts.CreatedTimestamp) - if err != nil && !errors.Is(err, storage.ErrOutOfOrderCT) { - // Even for the first sample OOO is a common scenario because - // we can't tell if a CT was already ingested in a previous request. - // We ignore the error. - h.logger.Debug("Error when appending CT in remote write request", "err", err, "series", ls.String(), "created_timestamp", ts.CreatedTimestamp, "timestamp", ts.Samples[0].Timestamp) - } - } for _, s := range ts.Samples { + if h.ingestCTZeroSample && s.StartTimestamp != 0 && s.Timestamp != 0 { + ref, err = app.AppendCTZeroSample(ref, ls, s.Timestamp, s.StartTimestamp) + // We treat OOO errors specially as it's a common scenario given: + // * We can't tell if ST was already ingested in a previous request. + // * We don't check if ST changed for stream of samples (we typically have one though), + // as it's checked in the AppendSTZeroSample reliably. + if err != nil && !errors.Is(err, storage.ErrOutOfOrderCT) { + h.logger.Debug("Error when appending ST from remote write request", "err", err, "series", ls.String(), "start_timestamp", s.StartTimestamp, "timestamp", s.Timestamp) + } + } + ref, err = app.Append(ref, ls, s.GetTimestamp(), s.GetValue()) if err == nil { rs.Samples++ @@ -387,15 +385,14 @@ func (h *writeHandler) appendV2(app storage.Appender, req *writev2.Request, rs * // Native Histograms. for _, hp := range ts.Histograms { - if h.ingestCTZeroSample && hp.Timestamp != 0 && ts.CreatedTimestamp != 0 { - // Differently from samples, we need to handle CT for each histogram instead of just the first one. - // This is because histograms and float histograms are stored separately, even if they have the same labels. - ref, err = h.handleHistogramZeroSample(app, ref, ls, hp, ts.CreatedTimestamp) + if h.ingestCTZeroSample && hp.StartTimestamp != 0 && hp.Timestamp != 0 { + ref, err = h.handleHistogramZeroSample(app, ref, ls, hp, hp.StartTimestamp) + // We treat OOO errors specially as it's a common scenario given: + // * We can't tell if ST was already ingested in a previous request. + // * We don't check if ST changed for stream of samples (we typically have one though), + // as it's checked in the ingestSTZeroSample reliably. if err != nil && !errors.Is(err, storage.ErrOutOfOrderCT) { - // Even for the first sample OOO is a common scenario because - // we can't tell if a CT was already ingested in a previous request. - // We ignore the error. - h.logger.Debug("Error when appending CT in remote write request", "err", err, "series", ls.String(), "created_timestamp", ts.CreatedTimestamp, "timestamp", hp.Timestamp) + h.logger.Debug("Error when appending ST from remote write request", "err", err, "series", ls.String(), "start_timestamp", hp.StartTimestamp, "timestamp", hp.Timestamp) } } if hp.IsFloatHistogram() { @@ -474,14 +471,14 @@ func (h *writeHandler) appendV2(app storage.Appender, req *writev2.Request, rs * return samplesWithoutMetadata, http.StatusBadRequest, errors.Join(badRequestErrs...) } -// handleHistogramZeroSample appends CT as a zero-value sample with CT value as the sample timestamp. -// It doesn't return errors in case of out of order CT. -func (*writeHandler) handleHistogramZeroSample(app storage.Appender, ref storage.SeriesRef, l labels.Labels, hist writev2.Histogram, ct int64) (storage.SeriesRef, error) { +// handleHistogramZeroSample appends ST as a zero-value sample with st value as the sample timestamp. +// It doesn't return errors in case of out of order ST. +func (*writeHandler) handleHistogramZeroSample(app storage.Appender, ref storage.SeriesRef, l labels.Labels, hist writev2.Histogram, st int64) (storage.SeriesRef, error) { var err error if hist.IsFloatHistogram() { - ref, err = app.AppendHistogramCTZeroSample(ref, l, hist.Timestamp, ct, nil, hist.ToFloatHistogram()) + ref, err = app.AppendHistogramCTZeroSample(ref, l, hist.Timestamp, st, nil, hist.ToFloatHistogram()) } else { - ref, err = app.AppendHistogramCTZeroSample(ref, l, hist.Timestamp, ct, hist.ToIntHistogram(), nil) + ref, err = app.AppendHistogramCTZeroSample(ref, l, hist.Timestamp, st, hist.ToIntHistogram(), nil) } return ref, err } diff --git a/storage/remote/write_handler_test.go b/storage/remote/write_handler_test.go index 536fba63cd..f1c064c64d 100644 --- a/storage/remote/write_handler_test.go +++ b/storage/remote/write_handler_test.go @@ -752,14 +752,12 @@ func TestRemoteWriteHandler_V2Message(t *testing.T) { i, j, k, m int ) for _, ts := range writeV2RequestFixture.Timeseries { - zeroHistogramIngested := false - zeroFloatHistogramIngested := false ls, err := ts.ToLabels(&b, writeV2RequestFixture.Symbols) require.NoError(t, err) for _, s := range ts.Samples { - if ts.CreatedTimestamp != 0 && tc.ingestCTZeroSample { - requireEqual(t, mockSample{ls, ts.CreatedTimestamp, 0}, appendable.samples[i]) + if s.StartTimestamp != 0 && tc.ingestCTZeroSample { + requireEqual(t, mockSample{ls, s.StartTimestamp, 0}, appendable.samples[i]) i++ } requireEqual(t, mockSample{ls, s.Timestamp, s.Value}, appendable.samples[i]) @@ -768,27 +766,21 @@ func TestRemoteWriteHandler_V2Message(t *testing.T) { for _, hp := range ts.Histograms { if hp.IsFloatHistogram() { fh := hp.ToFloatHistogram() - if !zeroFloatHistogramIngested && ts.CreatedTimestamp != 0 && tc.ingestCTZeroSample { - requireEqual(t, mockHistogram{ls, ts.CreatedTimestamp, nil, &histogram.FloatHistogram{}}, appendable.histograms[k]) + if hp.StartTimestamp != 0 && tc.ingestCTZeroSample { + requireEqual(t, mockHistogram{ls, hp.StartTimestamp, nil, &histogram.FloatHistogram{}}, appendable.histograms[k]) k++ - zeroFloatHistogramIngested = true } requireEqual(t, mockHistogram{ls, hp.Timestamp, nil, fh}, appendable.histograms[k]) } else { h := hp.ToIntHistogram() - if !zeroHistogramIngested && ts.CreatedTimestamp != 0 && tc.ingestCTZeroSample { - requireEqual(t, mockHistogram{ls, ts.CreatedTimestamp, &histogram.Histogram{}, nil}, appendable.histograms[k]) + if hp.StartTimestamp != 0 && tc.ingestCTZeroSample { + requireEqual(t, mockHistogram{ls, hp.StartTimestamp, &histogram.Histogram{}, nil}, appendable.histograms[k]) k++ - zeroHistogramIngested = true } requireEqual(t, mockHistogram{ls, hp.Timestamp, h, nil}, appendable.histograms[k]) } k++ } - if ts.CreatedTimestamp != 0 && tc.ingestCTZeroSample { - require.True(t, zeroHistogramIngested) - require.True(t, zeroFloatHistogramIngested) - } if tc.appendExemplarErr == nil { for _, e := range ts.Exemplars { ex, err := e.ToExemplar(&b, writeV2RequestFixture.Symbols) From 48645e1d697befff82ac2dc883084b99ec6b123a Mon Sep 17 00:00:00 2001 From: bwplotka Date: Thu, 20 Nov 2025 08:39:29 +0000 Subject: [PATCH 09/14] chore: prepare 3.8.0-rc.1 entry Signed-off-by: bwplotka --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07b6e1d74b..b35e0d4e50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## main / unreleased +## 3.8.0-rc.1 / 2025-11-20 + +* [CHANGE] Remote-write (receiving): Updated experimental Remote Write implementation to [2.0-rc.4 spec](https://github.com/prometheus/docs/blob/60c24e450010df38cfcb4f65df874f6f9b26dbcb/docs/specs/prw/remote_write_spec_2_0.md); notably "created timestamp" (CT) is now called "start timestamp" (ST) and it's moved from TimeSeries message to Sample message. #17411 +* ## 3.8.0-rc.0 / 2025-11-07 * [CHANGE] TSDB: Native Histogram Custom Bounds with a NaN threshold are now rejected. #17287 From 5cc29813c260184db966f9f042cd6c04b0c06574 Mon Sep 17 00:00:00 2001 From: Jorge Turrado Date: Wed, 19 Nov 2025 13:10:10 +0100 Subject: [PATCH 10/14] [chore]: bump common dep to support RFC7523 3.1 Signed-off-by: Jorge Turrado --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 55b8d2ce1f..864388bfab 100644 --- a/go.mod +++ b/go.mod @@ -58,7 +58,7 @@ require ( github.com/prometheus/client_golang v1.23.2 github.com/prometheus/client_golang/exp v0.0.0-20250914183048-a974e0d45e0a github.com/prometheus/client_model v0.6.2 - github.com/prometheus/common v0.67.2 + github.com/prometheus/common v0.67.3 github.com/prometheus/common/assets v0.2.0 github.com/prometheus/exporter-toolkit v0.15.0 github.com/prometheus/sigv4 v0.3.0 diff --git a/go.sum b/go.sum index 2c0042edbb..244268ae75 100644 --- a/go.sum +++ b/go.sum @@ -447,8 +447,8 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8= -github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko= +github.com/prometheus/common v0.67.3 h1:shd26MlnwTw5jksTDhC7rTQIteBxy+ZZDr3t7F2xN2Q= +github.com/prometheus/common v0.67.3/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI= github.com/prometheus/common/assets v0.2.0 h1:0P5OrzoHrYBOSM1OigWL3mY8ZvV2N4zIE/5AahrSrfM= github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI= github.com/prometheus/exporter-toolkit v0.15.0 h1:Pcle5sSViwR1x0gdPd0wtYrPQENBieQAM7TmT0qtb2U= From b415208a9089f6da4ffc140929eaabea0cad9e18 Mon Sep 17 00:00:00 2001 From: Ben Kochie Date: Fri, 21 Nov 2025 11:34:19 +0100 Subject: [PATCH 11/14] Update Prometheus Agent doc (#17591) * Add a nav title to fix docs website generator. * Make it more clear that "Prometheus Agent" is a mode, not a seaparate service. * Add to index. * Cleanup some wording. * Add a downsides section. Signed-off-by: SuperQ (cherry picked from commit d0d2699dc5f454ebca53e56247281447f8dd8c5a) --- docs/index.md | 1 + docs/prometheus_agent.md | 23 +++++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/docs/index.md b/docs/index.md index d9d4d2b152..fff28fa54a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,6 +13,7 @@ The documentation is available alongside all the project documentation at - [Getting started](getting_started.md) - [Installation](installation.md) +- [Agent Mode](prometheus_agent.md) - [Configuration](configuration/configuration.md) - [Querying](querying/basics.md) - [Storage](storage.md) diff --git a/docs/prometheus_agent.md b/docs/prometheus_agent.md index 9e2d922b10..468b5565d1 100644 --- a/docs/prometheus_agent.md +++ b/docs/prometheus_agent.md @@ -1,8 +1,11 @@ --- -# todo: internal +title: Prometheus Agent Mode +nav_title: Agent Mode +sort_rank: 4 --- -## Prometheus Agent +## Prometheus Agent Mode + The Prometheus Agent is an operational mode built into the Prometheus binary with the same scraping APIs, semantics, configuration, and discovery mechanism; this agent mode disables some of Prometheus' usual features(TSDB, alerting, and rule evaluations) and optimizes the binary for scraping and remote writing to remote locations. The Prometheus Remote Write protocol forwards(streams) all or a subset of metrics collected by Prometheus to a remote location; you can configure Prometheus to forward some metrics (if you want, with all metadata and exemplars!) to one or more locations that support the Remote Write API. @@ -15,11 +18,19 @@ The Agent mode optimizes Prometheus for the remote write use case. It disables q In essence, it looks like this: ![Prometheus Agent Remote Write](./images/prometheus_agent.png) -### Benefits of The Prometheus Agent -- First of all, efficiency; The customized Agent TSDB WAL removes the data immediately after successful writes. If it cannot reach the remote endpoint, it persists the data temporarily on the disk until the remote endpoint is back online. This is currently limited to a two-hour buffer only, similar to non-agent Prometheus. This means that we don't need to build chunks of data in memory. We don't need to maintain a full index for querying purposes. Essentially the Agent mode uses a fraction of the resources that a normal Prometheus server would use in a similar situation. -- Secondly, the benefit of the Agent mode is that it enables easier [horizontal scalability for ingestion](https://prometheus.io/blog/2021/11/16/agent/#the-dream-auto-scalable-metric-ingestion). +### Benefits of agent mode + +- Improved efficency. The customized Agent TSDB WAL removes the data immediately after successful writes. If it cannot reach the remote endpoint, it persists the data temporarily on the disk until the remote endpoint is back online. This is currently limited to a two-hour buffer only, similar to non-agent Prometheus. This means that there is no need to build chunks of data in memory or maintain a full index for querying purposes. Essentially the Agent mode uses a fraction of the resources that a normal Prometheus server would use in a similar situation. +- Agent mode eables easier [horizontal scalability for ingestion](https://prometheus.io/blog/2021/11/16/agent/#the-dream-auto-scalable-metric-ingestion). + +### Downsides of agent mode + +- No local queries. You can not query the local Prometheus instance. +- Recording rules are not possible. You can not pre-summarize data for sending to remote write. Rules must be done remotely. +- No alerting. All alerting must be done by the remote system. ### How to Use Agent Mode in Detail + If you show the help output of Prometheus (--help flag), you should see more or less the following: ``` @@ -40,4 +51,4 @@ Flags: Use the `--agent` flag to run Prometheus in the Agent mode. The rest of the flags are either for both server and Agent or only for a specific mode. You can see which flag is for which mode by checking the last sentence of a flag's help string. "Use with server mode only" means it's only for server mode. If you don't see any mention like this, it means the flag is shared. -The Agent mode accepts the same scrape configuration with the same discovery options and remote write options. It also exposes a web UI on port 9095 with disabled query capabilities but shows build info, configuration, targets, and service discovery information as in a normal Prometheus server. \ No newline at end of file +The Agent mode accepts the same scrape configuration with the same discovery options and remote write options. It also exposes a web UI on port 9095 with disabled query capabilities but shows build info, configuration, targets, and service discovery information as in a normal Prometheus server. From 591b484a6ae6b42b09145399a6104aed46fdd05b Mon Sep 17 00:00:00 2001 From: Jan Fajerski Date: Fri, 21 Nov 2025 16:10:48 +0100 Subject: [PATCH 12/14] chore(deps): bump github.com/prometheus/common from 0.67.3 to 0.67.4 (#17594) Signed-off-by: Jan Fajerski --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 864388bfab..9cf136eb39 100644 --- a/go.mod +++ b/go.mod @@ -58,7 +58,7 @@ require ( github.com/prometheus/client_golang v1.23.2 github.com/prometheus/client_golang/exp v0.0.0-20250914183048-a974e0d45e0a github.com/prometheus/client_model v0.6.2 - github.com/prometheus/common v0.67.3 + github.com/prometheus/common v0.67.4 github.com/prometheus/common/assets v0.2.0 github.com/prometheus/exporter-toolkit v0.15.0 github.com/prometheus/sigv4 v0.3.0 diff --git a/go.sum b/go.sum index 244268ae75..579e86ca58 100644 --- a/go.sum +++ b/go.sum @@ -447,8 +447,8 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.67.3 h1:shd26MlnwTw5jksTDhC7rTQIteBxy+ZZDr3t7F2xN2Q= -github.com/prometheus/common v0.67.3/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI= +github.com/prometheus/common v0.67.4 h1:yR3NqWO1/UyO1w2PhUvXlGQs/PtFmoveVO0KZ4+Lvsc= +github.com/prometheus/common v0.67.4/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI= github.com/prometheus/common/assets v0.2.0 h1:0P5OrzoHrYBOSM1OigWL3mY8ZvV2N4zIE/5AahrSrfM= github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI= github.com/prometheus/exporter-toolkit v0.15.0 h1:Pcle5sSViwR1x0gdPd0wtYrPQENBieQAM7TmT0qtb2U= From f1b0dd2cdd7786d465c6f8683de017b14a94d9c4 Mon Sep 17 00:00:00 2001 From: Jan Fajerski Date: Fri, 21 Nov 2025 11:32:01 +0100 Subject: [PATCH 13/14] prepare release v3.8.0-rc.1 Signed-off-by: Jan Fajerski --- CHANGELOG.md | 7 ++++--- VERSION | 2 +- web/ui/mantine-ui/package.json | 4 ++-- web/ui/module/codemirror-promql/package.json | 4 ++-- web/ui/module/lezer-promql/package.json | 2 +- web/ui/package-lock.json | 14 +++++++------- web/ui/package.json | 2 +- 7 files changed, 18 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b35e0d4e50..37db23b1a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,11 @@ ## main / unreleased -## 3.8.0-rc.1 / 2025-11-20 +## 3.8.0-rc.1 / 2025-11-21 + +* [CHANGE] Remote-write 2 (receiving): Update to [2.0-rc.4 spec](https://github.com/prometheus/docs/blob/60c24e450010df38cfcb4f65df874f6f9b26dbcb/docs/specs/prw/remote_write_spec_2_0.md). "created timestamp" (CT) is now called "start timestamp" (ST). #17411 +* [FEATURE] OAuth2: support jwt-bearer grant-type (RFC7523 3.1). #17592 -* [CHANGE] Remote-write (receiving): Updated experimental Remote Write implementation to [2.0-rc.4 spec](https://github.com/prometheus/docs/blob/60c24e450010df38cfcb4f65df874f6f9b26dbcb/docs/specs/prw/remote_write_spec_2_0.md); notably "created timestamp" (CT) is now called "start timestamp" (ST) and it's moved from TimeSeries message to Sample message. #17411 -* ## 3.8.0-rc.0 / 2025-11-07 * [CHANGE] TSDB: Native Histogram Custom Bounds with a NaN threshold are now rejected. #17287 diff --git a/VERSION b/VERSION index 100ac3dfd6..493bf7002c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.8.0-rc.0 +3.8.0-rc.1 diff --git a/web/ui/mantine-ui/package.json b/web/ui/mantine-ui/package.json index 1f10e4b620..b35ebf8f92 100644 --- a/web/ui/mantine-ui/package.json +++ b/web/ui/mantine-ui/package.json @@ -1,7 +1,7 @@ { "name": "@prometheus-io/mantine-ui", "private": true, - "version": "0.308.0-rc.0", + "version": "0.308.0-rc.1", "type": "module", "scripts": { "start": "vite", @@ -28,7 +28,7 @@ "@microsoft/fetch-event-source": "^2.0.1", "@nexucis/fuzzy": "^0.5.1", "@nexucis/kvsearch": "^0.9.1", - "@prometheus-io/codemirror-promql": "0.308.0-rc.0", + "@prometheus-io/codemirror-promql": "0.308.0-rc.1", "@reduxjs/toolkit": "^2.10.1", "@tabler/icons-react": "^3.35.0", "@tanstack/react-query": "^5.90.7", diff --git a/web/ui/module/codemirror-promql/package.json b/web/ui/module/codemirror-promql/package.json index b32fd59d19..5a23ead1f0 100644 --- a/web/ui/module/codemirror-promql/package.json +++ b/web/ui/module/codemirror-promql/package.json @@ -1,6 +1,6 @@ { "name": "@prometheus-io/codemirror-promql", - "version": "0.308.0-rc.0", + "version": "0.308.0-rc.1", "description": "a CodeMirror mode for the PromQL language", "types": "dist/esm/index.d.ts", "module": "dist/esm/index.js", @@ -29,7 +29,7 @@ }, "homepage": "https://github.com/prometheus/prometheus/blob/main/web/ui/module/codemirror-promql/README.md", "dependencies": { - "@prometheus-io/lezer-promql": "0.308.0-rc.0", + "@prometheus-io/lezer-promql": "0.308.0-rc.1", "lru-cache": "^11.2.2" }, "devDependencies": { diff --git a/web/ui/module/lezer-promql/package.json b/web/ui/module/lezer-promql/package.json index d86f1a1e7a..f6152a35b7 100644 --- a/web/ui/module/lezer-promql/package.json +++ b/web/ui/module/lezer-promql/package.json @@ -1,6 +1,6 @@ { "name": "@prometheus-io/lezer-promql", - "version": "0.308.0-rc.0", + "version": "0.308.0-rc.1", "description": "lezer-based PromQL grammar", "main": "dist/index.cjs", "type": "module", diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json index a9a75a131a..e2271f2977 100644 --- a/web/ui/package-lock.json +++ b/web/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "prometheus-io", - "version": "0.308.0-rc.0", + "version": "0.308.0-rc.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "prometheus-io", - "version": "0.308.0-rc.0", + "version": "0.308.0-rc.1", "workspaces": [ "mantine-ui", "module/*" @@ -24,7 +24,7 @@ }, "mantine-ui": { "name": "@prometheus-io/mantine-ui", - "version": "0.308.0-rc.0", + "version": "0.308.0-rc.1", "dependencies": { "@codemirror/autocomplete": "^6.19.1", "@codemirror/language": "^6.11.3", @@ -42,7 +42,7 @@ "@microsoft/fetch-event-source": "^2.0.1", "@nexucis/fuzzy": "^0.5.1", "@nexucis/kvsearch": "^0.9.1", - "@prometheus-io/codemirror-promql": "0.308.0-rc.0", + "@prometheus-io/codemirror-promql": "0.308.0-rc.1", "@reduxjs/toolkit": "^2.10.1", "@tabler/icons-react": "^3.35.0", "@tanstack/react-query": "^5.90.7", @@ -88,10 +88,10 @@ }, "module/codemirror-promql": { "name": "@prometheus-io/codemirror-promql", - "version": "0.308.0-rc.0", + "version": "0.308.0-rc.1", "license": "Apache-2.0", "dependencies": { - "@prometheus-io/lezer-promql": "0.308.0-rc.0", + "@prometheus-io/lezer-promql": "0.308.0-rc.1", "lru-cache": "^11.2.2" }, "devDependencies": { @@ -121,7 +121,7 @@ }, "module/lezer-promql": { "name": "@prometheus-io/lezer-promql", - "version": "0.308.0-rc.0", + "version": "0.308.0-rc.1", "license": "Apache-2.0", "devDependencies": { "@lezer/generator": "^1.8.0", diff --git a/web/ui/package.json b/web/ui/package.json index d8f2c712ff..2cf4a6819f 100644 --- a/web/ui/package.json +++ b/web/ui/package.json @@ -1,7 +1,7 @@ { "name": "prometheus-io", "description": "Monorepo for the Prometheus UI", - "version": "0.308.0-rc.0", + "version": "0.308.0-rc.1", "private": true, "scripts": { "build": "bash build_ui.sh --all", From 73b1fda131d7d4aa94160ad1f788e0f13d7e6a02 Mon Sep 17 00:00:00 2001 From: Jan Fajerski Date: Fri, 28 Nov 2025 09:12:04 +0100 Subject: [PATCH 14/14] prepare release v3.8.0 Signed-off-by: Jan Fajerski --- CHANGELOG.md | 7 ++----- VERSION | 2 +- web/ui/mantine-ui/package.json | 4 ++-- web/ui/module/codemirror-promql/package.json | 4 ++-- web/ui/module/lezer-promql/package.json | 2 +- web/ui/package-lock.json | 14 +++++++------- web/ui/package.json | 2 +- 7 files changed, 16 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37db23b1a7..3304339867 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,11 @@ ## main / unreleased -## 3.8.0-rc.1 / 2025-11-21 +## 3.8.0 / 2025-11-28 * [CHANGE] Remote-write 2 (receiving): Update to [2.0-rc.4 spec](https://github.com/prometheus/docs/blob/60c24e450010df38cfcb4f65df874f6f9b26dbcb/docs/specs/prw/remote_write_spec_2_0.md). "created timestamp" (CT) is now called "start timestamp" (ST). #17411 -* [FEATURE] OAuth2: support jwt-bearer grant-type (RFC7523 3.1). #17592 - -## 3.8.0-rc.0 / 2025-11-07 - * [CHANGE] TSDB: Native Histogram Custom Bounds with a NaN threshold are now rejected. #17287 +* [FEATURE] OAuth2: support jwt-bearer grant-type (RFC7523 3.1). #17592 * [FEATURE] Dockerfile: Add OpenContainers spec labels to Dockerfile. #16483 * [FEATURE] SD: Add unified AWS service discovery for ec2, lightsail and ecs services. #17046 * [FEATURE] Native histograms are now a stable, but optional feature, use the `scrape_native_histogram` config setting. #17232 #17315 diff --git a/VERSION b/VERSION index 493bf7002c..19811903a7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.8.0-rc.1 +3.8.0 diff --git a/web/ui/mantine-ui/package.json b/web/ui/mantine-ui/package.json index b35ebf8f92..7ec13b1b8d 100644 --- a/web/ui/mantine-ui/package.json +++ b/web/ui/mantine-ui/package.json @@ -1,7 +1,7 @@ { "name": "@prometheus-io/mantine-ui", "private": true, - "version": "0.308.0-rc.1", + "version": "0.308.0", "type": "module", "scripts": { "start": "vite", @@ -28,7 +28,7 @@ "@microsoft/fetch-event-source": "^2.0.1", "@nexucis/fuzzy": "^0.5.1", "@nexucis/kvsearch": "^0.9.1", - "@prometheus-io/codemirror-promql": "0.308.0-rc.1", + "@prometheus-io/codemirror-promql": "0.308.0", "@reduxjs/toolkit": "^2.10.1", "@tabler/icons-react": "^3.35.0", "@tanstack/react-query": "^5.90.7", diff --git a/web/ui/module/codemirror-promql/package.json b/web/ui/module/codemirror-promql/package.json index 5a23ead1f0..ee7bcc045f 100644 --- a/web/ui/module/codemirror-promql/package.json +++ b/web/ui/module/codemirror-promql/package.json @@ -1,6 +1,6 @@ { "name": "@prometheus-io/codemirror-promql", - "version": "0.308.0-rc.1", + "version": "0.308.0", "description": "a CodeMirror mode for the PromQL language", "types": "dist/esm/index.d.ts", "module": "dist/esm/index.js", @@ -29,7 +29,7 @@ }, "homepage": "https://github.com/prometheus/prometheus/blob/main/web/ui/module/codemirror-promql/README.md", "dependencies": { - "@prometheus-io/lezer-promql": "0.308.0-rc.1", + "@prometheus-io/lezer-promql": "0.308.0", "lru-cache": "^11.2.2" }, "devDependencies": { diff --git a/web/ui/module/lezer-promql/package.json b/web/ui/module/lezer-promql/package.json index f6152a35b7..034ead9741 100644 --- a/web/ui/module/lezer-promql/package.json +++ b/web/ui/module/lezer-promql/package.json @@ -1,6 +1,6 @@ { "name": "@prometheus-io/lezer-promql", - "version": "0.308.0-rc.1", + "version": "0.308.0", "description": "lezer-based PromQL grammar", "main": "dist/index.cjs", "type": "module", diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json index e2271f2977..7f2961784b 100644 --- a/web/ui/package-lock.json +++ b/web/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "prometheus-io", - "version": "0.308.0-rc.1", + "version": "0.308.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "prometheus-io", - "version": "0.308.0-rc.1", + "version": "0.308.0", "workspaces": [ "mantine-ui", "module/*" @@ -24,7 +24,7 @@ }, "mantine-ui": { "name": "@prometheus-io/mantine-ui", - "version": "0.308.0-rc.1", + "version": "0.308.0", "dependencies": { "@codemirror/autocomplete": "^6.19.1", "@codemirror/language": "^6.11.3", @@ -42,7 +42,7 @@ "@microsoft/fetch-event-source": "^2.0.1", "@nexucis/fuzzy": "^0.5.1", "@nexucis/kvsearch": "^0.9.1", - "@prometheus-io/codemirror-promql": "0.308.0-rc.1", + "@prometheus-io/codemirror-promql": "0.308.0", "@reduxjs/toolkit": "^2.10.1", "@tabler/icons-react": "^3.35.0", "@tanstack/react-query": "^5.90.7", @@ -88,10 +88,10 @@ }, "module/codemirror-promql": { "name": "@prometheus-io/codemirror-promql", - "version": "0.308.0-rc.1", + "version": "0.308.0", "license": "Apache-2.0", "dependencies": { - "@prometheus-io/lezer-promql": "0.308.0-rc.1", + "@prometheus-io/lezer-promql": "0.308.0", "lru-cache": "^11.2.2" }, "devDependencies": { @@ -121,7 +121,7 @@ }, "module/lezer-promql": { "name": "@prometheus-io/lezer-promql", - "version": "0.308.0-rc.1", + "version": "0.308.0", "license": "Apache-2.0", "devDependencies": { "@lezer/generator": "^1.8.0", diff --git a/web/ui/package.json b/web/ui/package.json index 2cf4a6819f..5023d1d21b 100644 --- a/web/ui/package.json +++ b/web/ui/package.json @@ -1,7 +1,7 @@ { "name": "prometheus-io", "description": "Monorepo for the Prometheus UI", - "version": "0.308.0-rc.1", + "version": "0.308.0", "private": true, "scripts": { "build": "bash build_ui.sh --all",