Merge pull request #276 from prometheus/fix/delta-noncounter-resets

Fix handling of negative deltas for non-counter values.
This commit is contained in:
juliusv 2013-05-29 02:26:20 -07:00
commit d828b9c835
3 changed files with 30 additions and 11 deletions

View file

@ -72,14 +72,14 @@ func timeImpl(timestamp time.Time, view *viewAdapter, args []Node) interface{} {
// === delta(matrix MatrixNode, isCounter ScalarNode) Vector === // === delta(matrix MatrixNode, isCounter ScalarNode) Vector ===
func deltaImpl(timestamp time.Time, view *viewAdapter, args []Node) interface{} { func deltaImpl(timestamp time.Time, view *viewAdapter, args []Node) interface{} {
matrixNode := args[0].(MatrixNode) matrixNode := args[0].(MatrixNode)
isCounter := int(args[1].(ScalarNode).Eval(timestamp, view)) isCounter := args[1].(ScalarNode).Eval(timestamp, view) > 0
resultVector := Vector{} resultVector := Vector{}
// If we treat these metrics as counters, we need to fetch all values // If we treat these metrics as counters, we need to fetch all values
// in the interval to find breaks in the timeseries' monotonicity. // in the interval to find breaks in the timeseries' monotonicity.
// I.e. if a counter resets, we want to ignore that reset. // I.e. if a counter resets, we want to ignore that reset.
var matrixValue Matrix var matrixValue Matrix
if isCounter > 0 { if isCounter {
matrixValue = matrixNode.Eval(timestamp, view) matrixValue = matrixNode.Eval(timestamp, view)
} else { } else {
matrixValue = matrixNode.EvalBoundaries(timestamp, view) matrixValue = matrixNode.EvalBoundaries(timestamp, view)
@ -95,7 +95,7 @@ func deltaImpl(timestamp time.Time, view *viewAdapter, args []Node) interface{}
lastValue := model.SampleValue(0) lastValue := model.SampleValue(0)
for _, sample := range samples.Values { for _, sample := range samples.Values {
currentValue := sample.Value currentValue := sample.Value
if currentValue < lastValue { if isCounter && currentValue < lastValue {
counterCorrection += lastValue - currentValue counterCorrection += lastValue - currentValue
} }
lastValue = currentValue lastValue = currentValue

View file

@ -145,13 +145,20 @@ var testMatrix = ast.Matrix{
}, },
Values: getTestValueStream(0, 100, 10, testStartTime), Values: getTestValueStream(0, 100, 10, testStartTime),
}, },
// Counter resets. // Counter reset in the middle of range.
{ {
Metric: model.Metric{ Metric: model.Metric{
model.MetricNameLabel: "testcounter", model.MetricNameLabel: "testcounter_reset_middle",
}, },
Values: append(getTestValueStream(0, 40, 10, testStartTime), getTestValueStream(0, 50, 10, testStartTime.Add(testSampleInterval*5))...), Values: append(getTestValueStream(0, 40, 10, testStartTime), getTestValueStream(0, 50, 10, testStartTime.Add(testSampleInterval*5))...),
}, },
// Counter reset at the end of range.
{
Metric: model.Metric{
model.MetricNameLabel: "testcounter_reset_end",
},
Values: append(getTestValueStream(0, 90, 10, testStartTime), getTestValueStream(0, 0, 10, testStartTime.Add(testSampleInterval*10))...),
},
} }
var testVector = getTestVectorFromTestMatrix(testMatrix) var testVector = getTestVectorFromTestMatrix(testMatrix)

View file

@ -319,15 +319,27 @@ func TestExpressions(t *testing.T) {
fullRanges: 1, fullRanges: 1,
intervalRanges: 0, intervalRanges: 0,
}, { }, {
// Counter resets are ignored by delta() if counter == 1. // Counter resets in middle of range are ignored by delta() if counter == 1.
expr: "delta(testcounter[50m], 1)", expr: "delta(testcounter_reset_middle[50m], 1)",
output: []string{"testcounter{} => 90 @[%v]"}, output: []string{"testcounter_reset_middle{} => 90 @[%v]"},
fullRanges: 1, fullRanges: 1,
intervalRanges: 0, intervalRanges: 0,
}, { }, {
// Counter resets are not ignored by delta() if counter == 0. // Counter resets in middle of range are not ignored by delta() if counter == 0.
expr: "delta(testcounter[50m], 0)", expr: "delta(testcounter_reset_middle[50m], 0)",
output: []string{"testcounter{} => 50 @[%v]"}, output: []string{"testcounter_reset_middle{} => 50 @[%v]"},
fullRanges: 1,
intervalRanges: 0,
}, {
// Counter resets at end of range are ignored by delta() if counter == 1.
expr: "delta(testcounter_reset_end[5m], 1)",
output: []string{"testcounter_reset_end{} => 0 @[%v]"},
fullRanges: 1,
intervalRanges: 0,
}, {
// Counter resets at end of range are not ignored by delta() if counter == 0.
expr: "delta(testcounter_reset_end[5m], 0)",
output: []string{"testcounter_reset_end{} => -90 @[%v]"},
fullRanges: 1, fullRanges: 1,
intervalRanges: 0, intervalRanges: 0,
}, { }, {