mirror of
https://github.com/prometheus/prometheus.git
synced 2026-02-03 20:39:32 -05:00
Merge pull request #17988 from roidelapluie/roidelapluie/fixsmoothing
promql: fix smoothed interpolation across counter resets
This commit is contained in:
commit
717d37bbca
4 changed files with 20 additions and 17 deletions
|
|
@ -1667,7 +1667,7 @@ func (ev *evaluator) smoothSeries(series []storage.Series, offset time.Duration)
|
|||
// Interpolate between prev and next.
|
||||
// TODO: detect if the sample is a counter, based on __type__ or metadata.
|
||||
prev, next := floats[i-1], floats[i]
|
||||
val := interpolate(prev, next, ts, false, false)
|
||||
val := interpolate(prev, next, ts, false)
|
||||
ss.Floats = append(ss.Floats, FPoint{F: val, T: ts})
|
||||
|
||||
case i > 0:
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ func funcTime(_ []Vector, _ Matrix, _ parser.Expressions, enh *EvalNodeHelper) (
|
|||
// it returns the interpolated value at the left boundary; otherwise, it returns the first sample's value.
|
||||
func pickOrInterpolateLeft(floats []FPoint, first int, rangeStart int64, smoothed, isCounter bool) float64 {
|
||||
if smoothed && floats[first].T < rangeStart {
|
||||
return interpolate(floats[first], floats[first+1], rangeStart, isCounter, true)
|
||||
return interpolate(floats[first], floats[first+1], rangeStart, isCounter)
|
||||
}
|
||||
return floats[first].F
|
||||
}
|
||||
|
|
@ -80,25 +80,20 @@ func pickOrInterpolateLeft(floats []FPoint, first int, rangeStart int64, smoothe
|
|||
// it returns the interpolated value at the right boundary; otherwise, it returns the last sample's value.
|
||||
func pickOrInterpolateRight(floats []FPoint, last int, rangeEnd int64, smoothed, isCounter bool) float64 {
|
||||
if smoothed && last > 0 && floats[last].T > rangeEnd {
|
||||
return interpolate(floats[last-1], floats[last], rangeEnd, isCounter, false)
|
||||
return interpolate(floats[last-1], floats[last], rangeEnd, isCounter)
|
||||
}
|
||||
return floats[last].F
|
||||
}
|
||||
|
||||
// interpolate performs linear interpolation between two points.
|
||||
// If isCounter is true and there is a counter reset:
|
||||
// - on the left edge, it sets the value to 0.
|
||||
// - on the right edge, it adds the left value to the right value.
|
||||
// If isCounter is true and there is a counter reset, it models the counter
|
||||
// as starting from 0 (post-reset) by setting y1 to 0.
|
||||
// It then calculates the interpolated value at the given timestamp.
|
||||
func interpolate(p1, p2 FPoint, t int64, isCounter, leftEdge bool) float64 {
|
||||
func interpolate(p1, p2 FPoint, t int64, isCounter bool) float64 {
|
||||
y1 := p1.F
|
||||
y2 := p2.F
|
||||
if isCounter && y2 < y1 {
|
||||
if leftEdge {
|
||||
y1 = 0
|
||||
} else {
|
||||
y2 += y1
|
||||
}
|
||||
y1 = 0
|
||||
}
|
||||
|
||||
return y1 + (y2-y1)*float64(t-p1.T)/float64(p2.T-p1.T)
|
||||
|
|
|
|||
|
|
@ -108,13 +108,13 @@ func TestInterpolate(t *testing.T) {
|
|||
{FPoint{T: 1, F: 100}, FPoint{T: 2, F: 200}, 1, false, 100},
|
||||
{FPoint{T: 0, F: 100}, FPoint{T: 2, F: 200}, 1, false, 150},
|
||||
{FPoint{T: 0, F: 200}, FPoint{T: 2, F: 100}, 1, false, 150},
|
||||
{FPoint{T: 0, F: 200}, FPoint{T: 2, F: 0}, 1, true, 200},
|
||||
{FPoint{T: 0, F: 200}, FPoint{T: 2, F: 100}, 1, true, 250},
|
||||
{FPoint{T: 0, F: 500}, FPoint{T: 2, F: 100}, 1, true, 550},
|
||||
{FPoint{T: 0, F: 500}, FPoint{T: 10, F: 0}, 1, true, 500},
|
||||
{FPoint{T: 0, F: 200}, FPoint{T: 2, F: 0}, 1, true, 0},
|
||||
{FPoint{T: 0, F: 200}, FPoint{T: 2, F: 100}, 1, true, 50},
|
||||
{FPoint{T: 0, F: 500}, FPoint{T: 2, F: 100}, 1, true, 50},
|
||||
{FPoint{T: 0, F: 500}, FPoint{T: 10, F: 0}, 1, true, 0},
|
||||
}
|
||||
for _, test := range tests {
|
||||
result := interpolate(test.p1, test.p2, test.t, test.isCounter, false)
|
||||
result := interpolate(test.p1, test.p2, test.t, test.isCounter)
|
||||
require.Equal(t, test.expected, result)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -358,6 +358,14 @@ load 1m
|
|||
eval instant at 2m15s increase(metric[2m] smoothed)
|
||||
{} 12
|
||||
|
||||
# Smoothed rate interpolation across a counter reset.
|
||||
clear
|
||||
load 15s
|
||||
metric 100 10
|
||||
|
||||
eval instant at 12s rate(metric[10s] smoothed)
|
||||
{} 0.666666666666667
|
||||
|
||||
clear
|
||||
eval instant at 1m deriv(foo[3m] smoothed)
|
||||
expect fail msg: smoothed modifier can only be used with: delta, increase, rate - not with deriv
|
||||
|
|
|
|||
Loading…
Reference in a new issue