diff --git a/promql/promql_test.go b/promql/promql_test.go index 38dafb61ca..18704fb6b0 100644 --- a/promql/promql_test.go +++ b/promql/promql_test.go @@ -34,3 +34,18 @@ func TestEvaluations(t *testing.T) { }) } } + +func TestOne(t *testing.T) { + files, err := filepath.Glob("testdata/nan.test") + require.NoError(t, err) + + for _, fn := range files { + t.Run(fn, func(t *testing.T) { + test, err := newTestFromFile(t, fn) + require.NoError(t, err) + require.NoError(t, test.Run()) + + test.Close() + }) + } +} diff --git a/promql/quantile.go b/promql/quantile.go index e2de98840c..f4a6fa6a13 100644 --- a/promql/quantile.go +++ b/promql/quantile.go @@ -71,6 +71,9 @@ type metricWithBuckets struct { // // If q>1, +Inf is returned. func bucketQuantile(q float64, buckets buckets) float64 { + if math.IsNaN(q){ + return math.NaN() + } if q < 0 { return math.Inf(-1) } @@ -181,11 +184,11 @@ func ensureMonotonic(buckets buckets) { // quantile calculates the given quantile of a vector of samples. // // The Vector will be sorted. -// If 'values' has zero elements, NaN is returned. +// If 'values' has zero elements or 'q' == NaN, NaN is returned. // If q<0, -Inf is returned. // If q>1, +Inf is returned. func quantile(q float64, values vectorByValueHeap) float64 { - if len(values) == 0 { + if len(values) == 0 || q == math.NaN() { return math.NaN() } if q < 0 { diff --git a/promql/testdata/nan.test b/promql/testdata/nan.test new file mode 100644 index 0000000000..a9583ac9a9 --- /dev/null +++ b/promql/testdata/nan.test @@ -0,0 +1,21 @@ +# Two histograms with 4 buckets each (x_sum and x_count not included, +# only buckets). Lowest bucket for one histogram < 0, for the other > +# 0. They have the same name, just separated by label. Not useful in +# practice, but can happen (if clients change bucketing), and the +# server has to cope with it. + +# Test histogram. +load 5m + testhistogram_bucket{le="0.1", start="positive"} 0+5x10 + testhistogram_bucket{le=".2", start="positive"} 0+7x10 + testhistogram_bucket{le="1e0", start="positive"} 0+11x10 + testhistogram_bucket{le="+Inf", start="positive"} 0+12x10 + testhistogram_bucket{le="-.2", start="negative"} 0+1x10 + testhistogram_bucket{le="-0.1", start="negative"} 0+2x10 + testhistogram_bucket{le="0.3", start="negative"} 0+2x10 + testhistogram_bucket{le="+Inf", start="negative"} 0+3x10 + + +# Quantile value in lowest bucket, which is positive. +eval instant at 50m histogram_quantile(NaN, testhistogram_bucket{start="positive"}) + {start="positive"} 0