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