浏览代码

Added Timer metrics.

Richard Crowley 14 年之前
父节点
当前提交
c64d95acf6
共有 2 个文件被更改,包括 147 次插入3 次删除
  1. 82 3
      timer.go
  2. 65 0
      timer_test.go

+ 82 - 3
timer.go

@@ -1,8 +1,87 @@
 package metrics
 
+import "time"
+
 type Timer interface {
+	Count() int64
+	Max() int64
+	Mean() float64
+	Min() int64
+	Percentile(float64) float64
+	Percentiles([]float64) []float64
+	Rate1() float64
+	Rate5() float64
+	Rate15() float64
+	RateMean() float64
+	StdDev() float64
+	Time(func())
+	Update(uint64)
+}
+
+type timer struct {
+	h Histogram
+	m Meter
+}
+
+func NewCustomTimer(h Histogram, m Meter) Timer {
+	return &timer{h, m}
+}
+
+func NewTimer() Timer {
+	return &timer{NewHistogram(NewExpDecaySample(1028, 0.015)), NewMeter()}
+}
+
+func (t *timer) Count() int64 {
+	return t.h.Count()
+}
+
+func (t *timer) Max() int64 {
+	return t.h.Max()
+}
+
+func (t *timer) Mean() float64 {
+	return t.h.Mean()
+}
+
+func (t *timer) Min() int64 {
+	return t.h.Min()
+}
+
+func (t *timer) Percentile(p float64) float64 {
+	return t.h.Percentile(p)
+}
+
+func (t *timer) Percentiles(ps []float64) []float64 {
+	return t.h.Percentiles(ps)
+}
+
+func (t *timer) Rate1() float64 {
+	return t.m.Rate1()
+}
+
+func (t *timer) Rate5() float64 {
+	return t.m.Rate5()
+}
+
+func (t *timer) Rate15() float64 {
+	return t.m.Rate15()
+}
+
+func (t *timer) RateMean() float64 {
+	return t.m.RateMean()
+}
+
+func (t *timer) StdDev() float64 {
+	return t.h.StdDev()
+}
+
+func (t *timer) Time(f func()) {
+	ts := time.Nanoseconds()
+	f()
+	t.Update(uint64(time.Nanoseconds() - ts))
 }
 
-// A timer, in Coda-speak, is a meter and a histogram. Sounds like a job for
-//
-// later.
+func (t *timer) Update(duration uint64) {
+	t.h.Update(int64(duration))
+	t.m.Mark(1)
+}

+ 65 - 0
timer_test.go

@@ -0,0 +1,65 @@
+package metrics
+
+import (
+	"math"
+	"testing"
+	"time"
+)
+
+func TestTimerZero(t *testing.T) {
+	tm := NewTimer()
+	if count := tm.Count(); 0 != count {
+		t.Errorf("tm.Count(): 0 != %v\n", count)
+	}
+	if min := tm.Min(); 0 != min {
+		t.Errorf("tm.Min(): 0 != %v\n", min)
+	}
+	if max := tm.Max(); 0 != max {
+		t.Errorf("tm.Max(): 0 != %v\n", max)
+	}
+	if mean := tm.Mean(); 0.0 != mean {
+		t.Errorf("tm.Mean(): 0.0 != %v\n", mean)
+	}
+	if stdDev := tm.StdDev(); 0.0 != stdDev {
+		t.Errorf("tm.StdDev(): 0.0 != %v\n", stdDev)
+	}
+	ps := tm.Percentiles([]float64{0.5, 0.75, 0.99})
+	if 0.0 != ps[0] {
+		t.Errorf("median: 0.0 != %v\n", ps[0])
+	}
+	if 0.0 != ps[1] {
+		t.Errorf("75th percentile: 0.0 != %v\n", ps[1])
+	}
+	if 0.0 != ps[2] {
+		t.Errorf("99th percentile: 0.0 != %v\n", ps[2])
+	}
+	if rate1 := tm.Rate1(); 0.0 != rate1 {
+		t.Errorf("tm.Rate1(): 0.0 != %v\n", rate1)
+	}
+	if rate5 := tm.Rate5(); 0.0 != rate5 {
+		t.Errorf("tm.Rate5(): 0.0 != %v\n", rate5)
+	}
+	if rate15 := tm.Rate15(); 0.0 != rate15 {
+		t.Errorf("tm.Rate15(): 0.0 != %v\n", rate15)
+	}
+	if rateMean := tm.RateMean(); 0.0 != rateMean {
+		t.Errorf("tm.RateMean(): 0.0 != %v\n", rateMean)
+	}
+}
+
+func TestTimerExtremes(t *testing.T) {
+	tm := NewTimer()
+	tm.Update(uint64(math.MaxInt64))
+	tm.Update(0)
+	if stdDev := tm.StdDev(); 6.521908912666392e18 != stdDev {
+		t.Errorf("tm.StdDev(): 6.521908912666392e18 != %v\n", stdDev)
+	}
+}
+
+func TestTimerFunc(t *testing.T) {
+	tm := NewTimer()
+	tm.Time(func() { time.Sleep(50e6) })
+	if max := tm.Max(); 45e6 > max || max > 55e6 {
+		t.Errorf("tm.Max(): 45e6 > %v || %v > 55e6\n", max, max)
+	}
+}