From d53b8cf9561007d9e91c8291684c81d0a12a9c1c Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Sat, 13 Apr 2013 02:45:58 +0200 Subject: [PATCH] Correct delta()/rate() intervals and temporal aliasing. --- rules/ast/functions.go | 18 ++++++++++++++++++ rules/rules_test.go | 6 ++++++ 2 files changed, 24 insertions(+) diff --git a/rules/ast/functions.go b/rules/ast/functions.go index 4af4abcca..66de9de8f 100644 --- a/rules/ast/functions.go +++ b/rules/ast/functions.go @@ -100,6 +100,24 @@ func deltaImpl(timestamp time.Time, view *viewAdapter, args []Node) interface{} lastValue = currentValue } resultValue := lastValue - samples.Values[0].Value + counterCorrection + + targetInterval := args[0].(*MatrixLiteral).interval + sampledInterval := samples.Values[len(samples.Values)-1].Timestamp.Sub(samples.Values[0].Timestamp) + if sampledInterval == 0 { + // Only found one sample. Cannot compute a rate from this. + continue + } + // Correct for differences in target vs. actual delta interval. + // + // Above, we didn't actually calculate the delta for the specified target + // interval, but for an interval between the first and last found samples + // under the target interval, which will usually have less time between + // them. Depending on how many samples are found under a target interval, + // the delta results are distorted and temporal aliasing occurs (ugly + // bumps). This effect is corrected for below. + intervalCorrection := model.SampleValue(targetInterval) / model.SampleValue(sampledInterval) + resultValue *= intervalCorrection + resultSample := model.Sample{ Metric: samples.Metric, Value: resultValue, diff --git a/rules/rules_test.go b/rules/rules_test.go index 68a366abe..b9a1e3b03 100644 --- a/rules/rules_test.go +++ b/rules/rules_test.go @@ -223,6 +223,12 @@ var expressionTests = []struct { output: []string{"http_requests{} => 4950 @[%v]"}, fullRanges: 0, intervalRanges: 8, + }, { + // Deltas should be adjusted for target interval vs. samples under target interval. + expr: "delta(http_requests{group='canary',instance='1',job='app-server'}[18m], 1)", + output: []string{"http_requests{group='canary',instance='1',job='app-server'} => 288 @[%v]"}, + fullRanges: 1, + intervalRanges: 0, }, { // Empty expressions shouldn't parse. expr: "",