1package metrics 2 3import ( 4 "sync" 5 "time" 6) 7 8// Meters count events to produce exponentially-weighted moving average rates 9// at one-, five-, and fifteen-minutes and a mean rate. 10type Meter interface { 11 Count() int64 12 Mark(int64) 13 Rate1() float64 14 Rate5() float64 15 Rate15() float64 16 RateMean() float64 17 Snapshot() Meter 18} 19 20// GetOrRegisterMeter returns an existing Meter or constructs and registers a 21// new StandardMeter. 22func GetOrRegisterMeter(name string, r Registry) Meter { 23 if nil == r { 24 r = DefaultRegistry 25 } 26 return r.GetOrRegister(name, NewMeter).(Meter) 27} 28 29// NewMeter constructs a new StandardMeter and launches a goroutine. 30func NewMeter() Meter { 31 if UseNilMetrics { 32 return NilMeter{} 33 } 34 m := newStandardMeter() 35 arbiter.Lock() 36 defer arbiter.Unlock() 37 arbiter.meters = append(arbiter.meters, m) 38 if !arbiter.started { 39 arbiter.started = true 40 go arbiter.tick() 41 } 42 return m 43} 44 45// NewMeter constructs and registers a new StandardMeter and launches a 46// goroutine. 47func NewRegisteredMeter(name string, r Registry) Meter { 48 c := NewMeter() 49 if nil == r { 50 r = DefaultRegistry 51 } 52 r.Register(name, c) 53 return c 54} 55 56// MeterSnapshot is a read-only copy of another Meter. 57type MeterSnapshot struct { 58 count int64 59 rate1, rate5, rate15, rateMean float64 60} 61 62// Count returns the count of events at the time the snapshot was taken. 63func (m *MeterSnapshot) Count() int64 { return m.count } 64 65// Mark panics. 66func (*MeterSnapshot) Mark(n int64) { 67 panic("Mark called on a MeterSnapshot") 68} 69 70// Rate1 returns the one-minute moving average rate of events per second at the 71// time the snapshot was taken. 72func (m *MeterSnapshot) Rate1() float64 { return m.rate1 } 73 74// Rate5 returns the five-minute moving average rate of events per second at 75// the time the snapshot was taken. 76func (m *MeterSnapshot) Rate5() float64 { return m.rate5 } 77 78// Rate15 returns the fifteen-minute moving average rate of events per second 79// at the time the snapshot was taken. 80func (m *MeterSnapshot) Rate15() float64 { return m.rate15 } 81 82// RateMean returns the meter's mean rate of events per second at the time the 83// snapshot was taken. 84func (m *MeterSnapshot) RateMean() float64 { return m.rateMean } 85 86// Snapshot returns the snapshot. 87func (m *MeterSnapshot) Snapshot() Meter { return m } 88 89// NilMeter is a no-op Meter. 90type NilMeter struct{} 91 92// Count is a no-op. 93func (NilMeter) Count() int64 { return 0 } 94 95// Mark is a no-op. 96func (NilMeter) Mark(n int64) {} 97 98// Rate1 is a no-op. 99func (NilMeter) Rate1() float64 { return 0.0 } 100 101// Rate5 is a no-op. 102func (NilMeter) Rate5() float64 { return 0.0 } 103 104// Rate15is a no-op. 105func (NilMeter) Rate15() float64 { return 0.0 } 106 107// RateMean is a no-op. 108func (NilMeter) RateMean() float64 { return 0.0 } 109 110// Snapshot is a no-op. 111func (NilMeter) Snapshot() Meter { return NilMeter{} } 112 113// StandardMeter is the standard implementation of a Meter. 114type StandardMeter struct { 115 lock sync.RWMutex 116 snapshot *MeterSnapshot 117 a1, a5, a15 EWMA 118 startTime time.Time 119} 120 121func newStandardMeter() *StandardMeter { 122 return &StandardMeter{ 123 snapshot: &MeterSnapshot{}, 124 a1: NewEWMA1(), 125 a5: NewEWMA5(), 126 a15: NewEWMA15(), 127 startTime: time.Now(), 128 } 129} 130 131// Count returns the number of events recorded. 132func (m *StandardMeter) Count() int64 { 133 m.lock.RLock() 134 count := m.snapshot.count 135 m.lock.RUnlock() 136 return count 137} 138 139// Mark records the occurance of n events. 140func (m *StandardMeter) Mark(n int64) { 141 m.lock.Lock() 142 defer m.lock.Unlock() 143 m.snapshot.count += n 144 m.a1.Update(n) 145 m.a5.Update(n) 146 m.a15.Update(n) 147 m.updateSnapshot() 148} 149 150// Rate1 returns the one-minute moving average rate of events per second. 151func (m *StandardMeter) Rate1() float64 { 152 m.lock.RLock() 153 rate1 := m.snapshot.rate1 154 m.lock.RUnlock() 155 return rate1 156} 157 158// Rate5 returns the five-minute moving average rate of events per second. 159func (m *StandardMeter) Rate5() float64 { 160 m.lock.RLock() 161 rate5 := m.snapshot.rate5 162 m.lock.RUnlock() 163 return rate5 164} 165 166// Rate15 returns the fifteen-minute moving average rate of events per second. 167func (m *StandardMeter) Rate15() float64 { 168 m.lock.RLock() 169 rate15 := m.snapshot.rate15 170 m.lock.RUnlock() 171 return rate15 172} 173 174// RateMean returns the meter's mean rate of events per second. 175func (m *StandardMeter) RateMean() float64 { 176 m.lock.RLock() 177 rateMean := m.snapshot.rateMean 178 m.lock.RUnlock() 179 return rateMean 180} 181 182// Snapshot returns a read-only copy of the meter. 183func (m *StandardMeter) Snapshot() Meter { 184 m.lock.RLock() 185 snapshot := *m.snapshot 186 m.lock.RUnlock() 187 return &snapshot 188} 189 190func (m *StandardMeter) updateSnapshot() { 191 // should run with write lock held on m.lock 192 snapshot := m.snapshot 193 snapshot.rate1 = m.a1.Rate() 194 snapshot.rate5 = m.a5.Rate() 195 snapshot.rate15 = m.a15.Rate() 196 snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds() 197} 198 199func (m *StandardMeter) tick() { 200 m.lock.Lock() 201 defer m.lock.Unlock() 202 m.a1.Tick() 203 m.a5.Tick() 204 m.a15.Tick() 205 m.updateSnapshot() 206} 207 208type meterArbiter struct { 209 sync.RWMutex 210 started bool 211 meters []*StandardMeter 212 ticker *time.Ticker 213} 214 215var arbiter = meterArbiter{ticker: time.NewTicker(5e9)} 216 217// Ticks meters on the scheduled interval 218func (ma *meterArbiter) tick() { 219 for { 220 select { 221 case <-ma.ticker.C: 222 ma.tickMeters() 223 } 224 } 225} 226 227func (ma *meterArbiter) tickMeters() { 228 ma.RLock() 229 defer ma.RUnlock() 230 for _, meter := range ma.meters { 231 meter.tick() 232 } 233} 234