mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-15 00:13:30 +01:00
app/vmselect/promql: properly handle corner cases for rollup functions
This commit is contained in:
parent
f696cc503a
commit
1b5b9ced27
@ -615,10 +615,15 @@ func rollupDelta(rfa *rollupFuncArg) float64 {
|
|||||||
if len(values) == 0 {
|
if len(values) == 0 {
|
||||||
return nan
|
return nan
|
||||||
}
|
}
|
||||||
|
if len(values) == 1 {
|
||||||
|
// Assume that the previous non-existing value was 0.
|
||||||
|
return values[0]
|
||||||
|
}
|
||||||
prevValue = values[0]
|
prevValue = values[0]
|
||||||
values = values[1:]
|
values = values[1:]
|
||||||
}
|
}
|
||||||
if len(values) == 0 {
|
if len(values) == 0 {
|
||||||
|
// Assume that the value didn't change on the given interval.
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return values[len(values)-1] - prevValue
|
return values[len(values)-1] - prevValue
|
||||||
@ -632,6 +637,7 @@ func rollupIdelta(rfa *rollupFuncArg) float64 {
|
|||||||
if math.IsNaN(rfa.prevValue) {
|
if math.IsNaN(rfa.prevValue) {
|
||||||
return nan
|
return nan
|
||||||
}
|
}
|
||||||
|
// Assume that the value didn't change on the given interval.
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
lastValue := values[len(values)-1]
|
lastValue := values[len(values)-1]
|
||||||
@ -639,7 +645,8 @@ func rollupIdelta(rfa *rollupFuncArg) float64 {
|
|||||||
if len(values) == 0 {
|
if len(values) == 0 {
|
||||||
prevValue := rfa.prevValue
|
prevValue := rfa.prevValue
|
||||||
if math.IsNaN(prevValue) {
|
if math.IsNaN(prevValue) {
|
||||||
return 0
|
// Assume that the previous non-existing value was 0.
|
||||||
|
return lastValue
|
||||||
}
|
}
|
||||||
return lastValue - prevValue
|
return lastValue - prevValue
|
||||||
}
|
}
|
||||||
@ -661,7 +668,8 @@ func rollupDerivFast(rfa *rollupFuncArg) float64 {
|
|||||||
prevValue := rfa.prevValue
|
prevValue := rfa.prevValue
|
||||||
prevTimestamp := rfa.prevTimestamp
|
prevTimestamp := rfa.prevTimestamp
|
||||||
if math.IsNaN(prevValue) {
|
if math.IsNaN(prevValue) {
|
||||||
if len(values) == 0 {
|
if len(values) < 2 {
|
||||||
|
// It is impossible to calculate derivative on 0 or 1 values.
|
||||||
return nan
|
return nan
|
||||||
}
|
}
|
||||||
prevValue = values[0]
|
prevValue = values[0]
|
||||||
@ -670,6 +678,7 @@ func rollupDerivFast(rfa *rollupFuncArg) float64 {
|
|||||||
timestamps = timestamps[1:]
|
timestamps = timestamps[1:]
|
||||||
}
|
}
|
||||||
if len(values) == 0 {
|
if len(values) == 0 {
|
||||||
|
// Assume that the value didn't change on the given interval.
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
vEnd := values[len(values)-1]
|
vEnd := values[len(values)-1]
|
||||||
@ -684,11 +693,12 @@ func rollupIderiv(rfa *rollupFuncArg) float64 {
|
|||||||
// before calling rollup funcs.
|
// before calling rollup funcs.
|
||||||
values := rfa.values
|
values := rfa.values
|
||||||
timestamps := rfa.timestamps
|
timestamps := rfa.timestamps
|
||||||
if len(values) == 0 {
|
if len(values) < 2 {
|
||||||
if math.IsNaN(rfa.prevValue) {
|
if len(values) == 0 || math.IsNaN(rfa.prevValue) {
|
||||||
|
// It is impossible to calculate derivative on 0 or 1 values.
|
||||||
return nan
|
return nan
|
||||||
}
|
}
|
||||||
return 0
|
return (values[0] - rfa.prevValue) / float64(timestamps[0]-rfa.prevTimestamp)
|
||||||
}
|
}
|
||||||
vEnd := values[len(values)-1]
|
vEnd := values[len(values)-1]
|
||||||
tEnd := timestamps[len(timestamps)-1]
|
tEnd := timestamps[len(timestamps)-1]
|
||||||
|
@ -45,8 +45,19 @@ func TestRollupIderivDuplicateTimestamps(t *testing.T) {
|
|||||||
timestamps: []int64{100},
|
timestamps: []int64{100},
|
||||||
}
|
}
|
||||||
n = rollupIderiv(rfa)
|
n = rollupIderiv(rfa)
|
||||||
if n != 0 {
|
if !math.IsNaN(n) {
|
||||||
t.Fatalf("unexpected value; got %v; want %v", n, 0)
|
t.Fatalf("unexpected value; got %v; want %v", n, nan)
|
||||||
|
}
|
||||||
|
|
||||||
|
rfa = &rollupFuncArg{
|
||||||
|
prevTimestamp: 90,
|
||||||
|
prevValue: 10,
|
||||||
|
values: []float64{15},
|
||||||
|
timestamps: []int64{100},
|
||||||
|
}
|
||||||
|
n = rollupIderiv(rfa)
|
||||||
|
if n != 0.5 {
|
||||||
|
t.Fatalf("unexpected value; got %v; want %v", n, 0.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
rfa = &rollupFuncArg{
|
rfa = &rollupFuncArg{
|
||||||
@ -569,7 +580,7 @@ func TestRollupFuncsNoWindow(t *testing.T) {
|
|||||||
}
|
}
|
||||||
rc.Timestamps = getTimestamps(rc.Start, rc.End, rc.Step)
|
rc.Timestamps = getTimestamps(rc.Start, rc.End, rc.Step)
|
||||||
values := rc.Do(nil, testValues, testTimestamps)
|
values := rc.Do(nil, testValues, testTimestamps)
|
||||||
valuesExpected := []float64{0, 33, -87, 0}
|
valuesExpected := []float64{123, 33, -87, 0}
|
||||||
timestampsExpected := []int64{10, 50, 90, 130}
|
timestampsExpected := []int64{10, 50, 90, 130}
|
||||||
testRowsEqual(t, values, rc.Timestamps, valuesExpected, timestampsExpected)
|
testRowsEqual(t, values, rc.Timestamps, valuesExpected, timestampsExpected)
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user