From 678e3b376332bb9074c8e01e8b2ba1f971f54370 Mon Sep 17 00:00:00 2001 From: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> Date: Wed, 22 Apr 2026 10:08:23 +0200 Subject: [PATCH] promql: fix spurious reset when prevST is invalid in isStartTimestampReset Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> --- promql/functions.go | 6 ++++++ promql/promqltest/testdata/start_timestamps.test | 16 ++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/promql/functions.go b/promql/functions.go index 7b3fd2d363..6ca32c4a81 100644 --- a/promql/functions.go +++ b/promql/functions.go @@ -447,6 +447,12 @@ func isStartTimestampReset(prevStartTimestamp, prevTimestamp, currStartTimestamp // This should be treated as a reset for deltas, but it is not a reset for cumulative series // with unknown start timestamp. Thus we have to check whether the start timestamp // of the previous datapoint is known. + // + // A previous start timestamp greater than the previous sample timestamp is invalid; treat it + // as unknown to avoid a spurious reset. + if prevStartTimestamp > prevTimestamp { + return false + } return prevStartTimestamp != 0 } diff --git a/promql/promqltest/testdata/start_timestamps.test b/promql/promqltest/testdata/start_timestamps.test index c7148e5cf3..3ad31e85ba 100644 --- a/promql/promqltest/testdata/start_timestamps.test +++ b/promql/promqltest/testdata/start_timestamps.test @@ -94,17 +94,21 @@ clear # Test for cumulative with unknow start timestamp, which is described in OTel spec. It is easy to incorrectly treat # second datapoint in such timeseries as delta, producing incorrect result. These can be distinguished by: -# * ST_curr == T_prev && ST_prev == 0 -> cumulative with unknown start, no reset -# * ST_curr == T_prev && ST_prev != 0 -> delta datapoint, treat as a reset +# * ST_curr == T_prev && ST_prev == 0 -> cumulative with unknown start, no reset +# * ST_curr == T_prev && ST_prev != 0 -> delta datapoint, treat as a reset +# * ST_curr == T_prev && ST_prev > T_prev (invalid) -> must not be mistaken for the delta case above load 1m - series{type="otel_cumulative_unknown_start"}@st _ _ _ -1m - series{type="otel_cumulative_unknown_start"} _ _ 1 1 - series{type="otel_delta"}@st _ _ -1m -1m - series{type="otel_delta"} _ _ 1 1 + series{type="otel_cumulative_unknown_start"}@st _ _ _ -1m + series{type="otel_cumulative_unknown_start"} _ _ 1 1 + series{type="otel_delta"}@st _ _ -1m -1m + series{type="otel_delta"} _ _ 1 1 + series{type="invalid_prev_st"}@st _ _ +1m -1m + series{type="invalid_prev_st"} _ _ 1 1 eval instant at 3m round(increase(series[1m1ms])) {type="otel_cumulative_unknown_start"} 0 {type="otel_delta"} 1 + {type="invalid_prev_st"} 0 clear