diff --git a/metrics/expvar/expvar_test.go b/metrics/expvar/expvar_test.go index 34dc918..b6e3bf4 100644 --- a/metrics/expvar/expvar_test.go +++ b/metrics/expvar/expvar_test.go @@ -1,6 +1,8 @@ package expvar_test import ( + stdexpvar "expvar" + "fmt" "testing" "github.com/peterbourgon/gokit/metrics/expvar" @@ -16,3 +18,12 @@ teststat.PopulateNormalHistogram(t, h, seed, mean, stdev) teststat.AssertExpvarNormalHistogram(t, metricName, mean, stdev, quantiles) } + +func TestCallbackGauge(t *testing.T) { + value := 42.43 + metricName := "foo" + expvar.PublishCallbackGauge(metricName, func() float64 { return value }) + if want, have := fmt.Sprint(value), stdexpvar.Get(metricName).String(); want != have { + t.Errorf("want %q, have %q", want, have) + } +} diff --git a/metrics/prometheus/prometheus_test.go b/metrics/prometheus/prometheus_test.go index a92a046..b6058cf 100644 --- a/metrics/prometheus/prometheus_test.go +++ b/metrics/prometheus/prometheus_test.go @@ -66,6 +66,19 @@ } } +func TestPrometheusCallbackGauge(t *testing.T) { + value := 123.456 + cb := func() float64 { return value } + prometheus.RegisterCallbackGauge("test", "prometheus_gauge", "bazbaz", "Help string.", cb) + if want, have := strings.Join([]string{ + `# HELP test_prometheus_gauge_bazbaz Help string.`, + `# TYPE test_prometheus_gauge_bazbaz gauge`, + `test_prometheus_gauge_bazbaz 123.456`, + }, "\n"), teststat.ScrapePrometheus(t); !strings.Contains(have, want) { + t.Errorf("metric stanza not found or incorrect\n%s", have) + } +} + func TestPrometheusHistogram(t *testing.T) { h := prometheus.NewHistogram("test", "prometheus_histogram", "foobar", "Qwerty asdf.", []string{}) diff --git a/metrics/statsd/statsd.go b/metrics/statsd/statsd.go index 9146f25..6b7faf9 100644 --- a/metrics/statsd/statsd.go +++ b/metrics/statsd/statsd.go @@ -78,16 +78,17 @@ // It collects values every scrape interval from the callback. Values are // buffered for the report interval or until the buffer exceeds a max packet // size, whichever comes first. The report and scrape intervals may be the -// same. Fields are ignored. +// same. The callback determines the value, and fields are ignored, so +// NewCallbackGauge returns nothing. func NewCallbackGauge(w io.Writer, key string, reportInterval, scrapeInterval time.Duration, callback func() float64) { go fwd(w, key, reportInterval, emitEvery(scrapeInterval, callback)) } -func emitEvery(d time.Duration, f func() float64) <-chan string { +func emitEvery(d time.Duration, callback func() float64) <-chan string { c := make(chan string) go func() { - for range time.Tick(d) { - c <- fmt.Sprintf("%f|g", f()) + for range tick(d) { + c <- fmt.Sprintf("%f|g", callback()) } }() return c diff --git a/metrics/statsd/statsd_test.go b/metrics/statsd/statsd_test.go index 46a2380..351e871 100644 --- a/metrics/statsd/statsd_test.go +++ b/metrics/statsd/statsd_test.go @@ -4,6 +4,7 @@ import ( "bytes" + "fmt" "runtime" "testing" "time" @@ -38,31 +39,54 @@ buf := &bytes.Buffer{} g := NewGauge(buf, "test_statsd_gauge", time.Second) - g.Add(1) // send command + delta := 1.0 + g.Add(delta) // send command runtime.Gosched() // yield to buffer write ch <- time.Now() // signal flush runtime.Gosched() // yield to flush - if want, have := "test_statsd_gauge:+1.000000|g\n", buf.String(); want != have { + if want, have := fmt.Sprintf("test_statsd_gauge:+%f|g\n", delta), buf.String(); want != have { t.Errorf("want %q, have %q", want, have) } buf.Reset() - g.Add(-2) + delta = -2.0 + g.Add(delta) runtime.Gosched() ch <- time.Now() runtime.Gosched() - if want, have := "test_statsd_gauge:-2.000000|g\n", buf.String(); want != have { + if want, have := fmt.Sprintf("test_statsd_gauge:%f|g\n", delta), buf.String(); want != have { t.Errorf("want %q, have %q", want, have) } buf.Reset() - g.Set(3) + value := 3.0 + g.Set(value) runtime.Gosched() ch <- time.Now() runtime.Gosched() - if want, have := "test_statsd_gauge:3.000000|g\n", buf.String(); want != have { + if want, have := fmt.Sprintf("test_statsd_gauge:%f|g\n", value), buf.String(); want != have { + t.Errorf("want %q, have %q", want, have) + } +} + +func TestCallbackGauge(t *testing.T) { + ch := make(chan time.Time) + tick = func(time.Duration) <-chan time.Time { return ch } + defer func() { tick = time.Tick }() + + buf := &bytes.Buffer{} + value := 55.55 + cb := func() float64 { return value } + NewCallbackGauge(buf, "test_statsd_callback_gauge", time.Second, time.Nanosecond, cb) + + ch <- time.Now() // signal emitter + runtime.Gosched() // yield to emitter + ch <- time.Now() // signal flush + runtime.Gosched() // yield to flush + + if want, have := fmt.Sprintf("test_statsd_callback_gauge:%f|g\n", value), buf.String(); want != have { t.Errorf("want %q, have %q", want, have) } }