Return NaN when summaries have no observations yet.

Also, properly handle decay upon Write().

This fixes https://github.com/prometheus/client_golang/issues/85 .
This commit is contained in:
beorn7 2015-03-15 13:58:14 +01:00
parent 7af92a21b3
commit 715be73ac9
2 changed files with 21 additions and 5 deletions

View File

@ -16,6 +16,7 @@ package prometheus
import (
"fmt"
"hash/fnv"
"math"
"sort"
"sync"
"time"
@ -277,10 +278,8 @@ func (s *summary) Write(out *dto.Metric) error {
s.bufMtx.Lock()
s.mtx.Lock()
if len(s.hotBuf) != 0 {
s.swapBufs(time.Now())
}
// Swap bufs even if hotBuf is empty to set new hotBufExpTime.
s.swapBufs(time.Now())
s.bufMtx.Unlock()
s.flushColdBuf()
@ -288,9 +287,15 @@ func (s *summary) Write(out *dto.Metric) error {
sum.SampleSum = proto.Float64(s.sum)
for _, rank := range s.sortedObjectives {
var q float64
if s.headStream.Count() == 0 {
q = math.NaN()
} else {
q = s.headStream.Query(rank)
}
qs = append(qs, &dto.Quantile{
Quantile: proto.Float64(rank),
Value: proto.Float64(s.headStream.Query(rank)),
Value: proto.Float64(q),
})
}

View File

@ -289,6 +289,11 @@ func TestSummaryVecConcurrency(t *testing.T) {
}
func TestSummaryDecay(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode.")
// More because it depends on timing than because it is particularly long...
}
sum := NewSummary(SummaryOpts{
Name: "test_summary",
Help: "helpless",
@ -315,6 +320,12 @@ func TestSummaryDecay(t *testing.T) {
}
}
tick.Stop()
// Wait for MaxAge without observations and make sure quantiles are NaN.
time.Sleep(100 * time.Millisecond)
sum.Write(m)
if got := *m.Summary.Quantile[0].Value; !math.IsNaN(got) {
t.Errorf("got %f, want NaN after expiration", got)
}
}
func getBounds(vars []float64, q, ε float64) (min, max float64) {