Skip to content

Commit

Permalink
add Stop() to Meter
Browse files Browse the repository at this point in the history
  • Loading branch information
vetinari committed Feb 8, 2017
1 parent 1f30fe9 commit c83b0ea
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 4 deletions.
34 changes: 31 additions & 3 deletions meter.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Meter interface {
Rate15() float64
RateMean() float64
Snapshot() Meter
Stop()
}

// GetOrRegisterMeter returns an existing Meter or constructs and registers a
Expand All @@ -34,7 +35,8 @@ func NewMeter() Meter {
m := newStandardMeter()
arbiter.Lock()
defer arbiter.Unlock()
arbiter.meters = append(arbiter.meters, m)
m.id = arbiter.newID()
arbiter.meters[m.id] = m
if !arbiter.started {
arbiter.started = true
go arbiter.tick()
Expand Down Expand Up @@ -86,6 +88,9 @@ func (m *MeterSnapshot) RateMean() float64 { return m.rateMean }
// Snapshot returns the snapshot.
func (m *MeterSnapshot) Snapshot() Meter { return m }

// Stop is a no-op.
func (m *MeterSnapshot) Stop() {}

// NilMeter is a no-op Meter.
type NilMeter struct{}

Expand All @@ -110,12 +115,17 @@ func (NilMeter) RateMean() float64 { return 0.0 }
// Snapshot is a no-op.
func (NilMeter) Snapshot() Meter { return NilMeter{} }

// Stop is a no-op.
func (NilMeter) Stop() {}

// StandardMeter is the standard implementation of a Meter.
type StandardMeter struct {
lock sync.RWMutex
snapshot *MeterSnapshot
a1, a5, a15 EWMA
startTime time.Time
stopped bool
id int64
}

func newStandardMeter() *StandardMeter {
Expand All @@ -128,6 +138,14 @@ func newStandardMeter() *StandardMeter {
}
}

// Stop stops the meter, Mark() will panic if you use it after being stopped.
func (m *StandardMeter) Stop() {
arbiter.Lock()
defer arbiter.Unlock()
m.stopped = true
delete(arbiter.meters, m.id)
}

// Count returns the number of events recorded.
func (m *StandardMeter) Count() int64 {
m.lock.RLock()
Expand All @@ -140,6 +158,9 @@ func (m *StandardMeter) Count() int64 {
func (m *StandardMeter) Mark(n int64) {
m.lock.Lock()
defer m.lock.Unlock()
if m.stopped {
panic("Mark called on a stopped Meter")
}
m.snapshot.count += n
m.a1.Update(n)
m.a5.Update(n)
Expand Down Expand Up @@ -208,11 +229,12 @@ func (m *StandardMeter) tick() {
type meterArbiter struct {
sync.RWMutex
started bool
meters []*StandardMeter
meters map[int64]*StandardMeter
ticker *time.Ticker
id int64
}

var arbiter = meterArbiter{ticker: time.NewTicker(5e9)}
var arbiter = meterArbiter{ticker: time.NewTicker(5e9), meters: make(map[int64]*StandardMeter)}

// Ticks meters on the scheduled interval
func (ma *meterArbiter) tick() {
Expand All @@ -224,6 +246,12 @@ func (ma *meterArbiter) tick() {
}
}

// should only be called with Lock() held
func (ma *meterArbiter) newID() int64 {
ma.id++
return ma.id
}

func (ma *meterArbiter) tickMeters() {
ma.RLock()
defer ma.RUnlock()
Expand Down
4 changes: 3 additions & 1 deletion meter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ func TestGetOrRegisterMeter(t *testing.T) {
func TestMeterDecay(t *testing.T) {
ma := meterArbiter{
ticker: time.NewTicker(time.Millisecond),
meters: make(map[int64]*StandardMeter),
}
m := newStandardMeter()
ma.meters = append(ma.meters, m)
m.id = ma.newID()
ma.meters[m.id] = m
go ma.tick()
m.Mark(1)
rateMean := m.RateMean()
Expand Down

0 comments on commit c83b0ea

Please sign in to comment.