Skip to content

Commit

Permalink
interface polish
Browse files Browse the repository at this point in the history
  • Loading branch information
tbg committed Dec 28, 2015
1 parent c26a3c3 commit 457b692
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 31 deletions.
42 changes: 42 additions & 0 deletions util/metric/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package metric

import (
"encoding/json"
"fmt"
"sync"
"time"

Expand Down Expand Up @@ -77,6 +78,20 @@ type Histogram struct {
nextT time.Time
}

// NewHistogram creates a new windowed HDRHistogram with the given parameters.
// Data is kept in the active window for approximately the given duration.
// See the the documentation for hdrhistogram.WindowedHistogram for details.
func NewHistogram(duration time.Duration, maxVal int64, sigFigs int) *Histogram {
const n = 4
h := &Histogram{}
h.maxVal = int64(maxVal)
h.interval = duration / n
h.nextT = time.Now()

h.windowed = hdrhistogram.NewWindowed(n, 0, h.maxVal, sigFigs)
return h
}

func (h *Histogram) tick() {
h.nextT = h.nextT.Add(h.interval)
h.windowed.Rotate()
Expand Down Expand Up @@ -127,6 +142,11 @@ type Counter struct {
metrics.Counter
}

// NewCounter creates a counter.
func NewCounter() *Counter {
return &Counter{metrics.NewCounter()}
}

// Each calls the given closure with the empty string and itself.
func (c *Counter) Each(f func(string, interface{})) { f("", c) }

Expand All @@ -140,6 +160,12 @@ type Gauge struct {
metrics.Gauge
}

// NewGauge creates a Gauge.
func NewGauge() *Gauge {
g := &Gauge{metrics.NewGauge()}
return g
}

// Each calls the given closure with the empty string and itself.
func (g *Gauge) Each(f func(string, interface{})) { f("", g) }

Expand All @@ -157,6 +183,22 @@ type Rate struct {
nextT time.Time
}

// NewRate creates an EWMA rate on the given timescale. Timescales at
// or below 2s are illegal and will cause a panic.
func NewRate(timescale time.Duration) *Rate {
const tickInterval = time.Second
if timescale <= 2*time.Second {
panic(fmt.Sprintf("EWMA with per-second ticks makes no sense on timescale %s", timescale))
}
avgAge := float64(timescale) / float64(2*tickInterval)

return &Rate{
interval: tickInterval,
nextT: time.Now(),
wrapped: ewma.NewMovingAverage(avgAge),
}
}

func (e *Rate) nextTick() time.Time {
return e.nextT
}
Expand Down
45 changes: 14 additions & 31 deletions util/metric/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ import (
"fmt"
"sync"
"time"

"github.com/VividCortex/ewma"
"github.com/codahale/hdrhistogram"
"github.com/rcrowley/go-metrics"
)

// A Registry bundles up various iterables (i.e. typically metrics or other
Expand All @@ -46,6 +42,9 @@ func NewRegistry() *Registry {
// string. The individual items in the registry will be formatted via
// fmt.Sprintf(format, <name>). As a special case, *Registry implements
// Iterable and can thus be added.
// Metric types in this package have helpers that allow them to be created
// and registered in a single step. Add is called manually only when adding
// a registry to another, or when integrating metrics defined elsewhere.
func (r *Registry) Add(format string, item Iterable) error {
r.Lock()
defer r.Unlock()
Expand Down Expand Up @@ -87,17 +86,11 @@ func (r *Registry) MarshalJSON() ([]byte, error) {
return json.Marshal(m)
}

// Histogram registers a new windowed HDRHistogram with the given
// parameters. Data is kept in the active window for approximately the given
// duration.
func (r *Registry) Histogram(name string, duration time.Duration, maxVal int64, sigFigs int) *Histogram {
const n = 4
h := &Histogram{}
h.maxVal = int64(maxVal)
h.interval = duration / n
h.nextT = time.Now()

h.windowed = hdrhistogram.NewWindowed(n, 0, h.maxVal, sigFigs)
// Histogram registers a new windowed HDRHistogram with the given parameters.
// Data is kept in the active window for approximately the given duration.
func (r *Registry) Histogram(name string, duration time.Duration, maxVal int64,
sigFigs int) *Histogram {
h := NewHistogram(duration, maxVal, sigFigs)
r.MustAdd(name, h)
return h
}
Expand All @@ -117,34 +110,24 @@ func (r *Registry) Latency(prefix string) Histograms {
return hs
}

// Counter registers a new counter under the given name.
// Counter registers new counter to the registry.
func (r *Registry) Counter(name string) *Counter {
c := &Counter{metrics.NewCounter()}
c := NewCounter()
r.MustAdd(name, c)
return c
}

// Gauge registers a new Gauge with the given name.
func (r *Registry) Gauge(name string) *Gauge {
g := &Gauge{metrics.NewGauge()}
g := NewGauge()
r.MustAdd(name, g)
return g
}

// Rate registers an EWMA rate over the given timescale. Timescales at
// or below 2s are illegal and will cause a panic.
// Rate creates an EWMA rate over the given timescale. The comments on NewRate
// apply.
func (r *Registry) Rate(name string, timescale time.Duration) *Rate {
const tickInterval = time.Second
if timescale <= 2*time.Second {
panic(fmt.Sprintf("EWMA with per-second ticks makes no sense on timescale %s", timescale))
}
avgAge := float64(timescale) / float64(2*tickInterval)

e := &Rate{
interval: tickInterval,
nextT: time.Now(),
wrapped: ewma.NewMovingAverage(avgAge),
}
e := NewRate(timescale)
r.MustAdd(name, e)
return e
}
Expand Down

0 comments on commit 457b692

Please sign in to comment.