From 7ee52bfb86c9e14299d103fe14cd870d6af81e18 Mon Sep 17 00:00:00 2001 From: Matthew Date: Mon, 15 Nov 2021 18:03:22 -0500 Subject: [PATCH] feat: linreg => slope 0 for const values (#9728) * feat: linreg => slope 0 for const values Signed-off-by: mtfoley --- promql/functions.go | 17 +++++++++++++++-- promql/functions_test.go | 10 ++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/promql/functions.go b/promql/functions.go index a0258bd78..fbafc7864 100644 --- a/promql/functions.go +++ b/promql/functions.go @@ -716,8 +716,16 @@ func linearRegression(samples []Point, interceptTime int64) (slope, intercept fl sumY, cY float64 sumXY, cXY float64 sumX2, cX2 float64 + initY float64 + constY bool ) - for _, sample := range samples { + initY = samples[0].V + constY = true + for i, sample := range samples { + // Set constY to false if any new y values are encountered. + if constY && i > 0 && sample.V != initY { + constY = false + } n += 1.0 x := float64(sample.T-interceptTime) / 1e3 sumX, cX = kahanSumInc(x, sumX, cX) @@ -725,7 +733,12 @@ func linearRegression(samples []Point, interceptTime int64) (slope, intercept fl sumXY, cXY = kahanSumInc(x*sample.V, sumXY, cXY) sumX2, cX2 = kahanSumInc(x*x, sumX2, cX2) } - + if constY { + if math.IsInf(initY, 0) { + return math.NaN(), math.NaN() + } + return 0, initY + } sumX = sumX + cX sumY = sumY + cY sumXY = sumXY + cXY diff --git a/promql/functions_test.go b/promql/functions_test.go index 589afc5fd..cde14461f 100644 --- a/promql/functions_test.go +++ b/promql/functions_test.go @@ -44,8 +44,14 @@ func TestDeriv(t *testing.T) { a := storage.Appender(context.Background()) metric := labels.FromStrings("__name__", "foo") - a.Append(0, metric, 1493712816939, 1.0) - a.Append(0, metric, 1493712846939, 1.0) + start := 1493712816939 + interval := 30 * 1000 + // Introduce some timestamp jitter to test 0 slope case. + // https://github.com/prometheus/prometheus/issues/7180 + for i := 0; i < 15; i++ { + jitter := 12 * i % 2 + a.Append(0, metric, int64(start+interval*i+jitter), 1) + } require.NoError(t, a.Commit())