|
|
@@ -1,7 +1,9 @@
|
|
|
package metrics
|
|
|
|
|
|
import (
|
|
|
+ "math"
|
|
|
"sync"
|
|
|
+ "sync/atomic"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
@@ -62,7 +64,7 @@ func NewRegisteredMeter(name string, r Registry) Meter {
|
|
|
// MeterSnapshot is a read-only copy of another Meter.
|
|
|
type MeterSnapshot struct {
|
|
|
count int64
|
|
|
- rate1, rate5, rate15, rateMean float64
|
|
|
+ rate1, rate5, rate15, rateMean uint64
|
|
|
}
|
|
|
|
|
|
// Count returns the count of events at the time the snapshot was taken.
|
|
|
@@ -75,19 +77,19 @@ func (*MeterSnapshot) Mark(n int64) {
|
|
|
|
|
|
// Rate1 returns the one-minute moving average rate of events per second at the
|
|
|
// time the snapshot was taken.
|
|
|
-func (m *MeterSnapshot) Rate1() float64 { return m.rate1 }
|
|
|
+func (m *MeterSnapshot) Rate1() float64 { return math.Float64frombits(m.rate1) }
|
|
|
|
|
|
// Rate5 returns the five-minute moving average rate of events per second at
|
|
|
// the time the snapshot was taken.
|
|
|
-func (m *MeterSnapshot) Rate5() float64 { return m.rate5 }
|
|
|
+func (m *MeterSnapshot) Rate5() float64 { return math.Float64frombits(m.rate5) }
|
|
|
|
|
|
// Rate15 returns the fifteen-minute moving average rate of events per second
|
|
|
// at the time the snapshot was taken.
|
|
|
-func (m *MeterSnapshot) Rate15() float64 { return m.rate15 }
|
|
|
+func (m *MeterSnapshot) Rate15() float64 { return math.Float64frombits(m.rate15) }
|
|
|
|
|
|
// RateMean returns the meter's mean rate of events per second at the time the
|
|
|
// snapshot was taken.
|
|
|
-func (m *MeterSnapshot) RateMean() float64 { return m.rateMean }
|
|
|
+func (m *MeterSnapshot) RateMean() float64 { return math.Float64frombits(m.rateMean) }
|
|
|
|
|
|
// Snapshot returns the snapshot.
|
|
|
func (m *MeterSnapshot) Snapshot() Meter { return m }
|
|
|
@@ -124,11 +126,12 @@ func (NilMeter) Stop() {}
|
|
|
|
|
|
// StandardMeter is the standard implementation of a Meter.
|
|
|
type StandardMeter struct {
|
|
|
- lock sync.RWMutex
|
|
|
+ // Only used on stop.
|
|
|
+ lock sync.Mutex
|
|
|
snapshot *MeterSnapshot
|
|
|
a1, a5, a15 EWMA
|
|
|
startTime time.Time
|
|
|
- stopped bool
|
|
|
+ stopped uint32
|
|
|
}
|
|
|
|
|
|
func newStandardMeter() *StandardMeter {
|
|
|
@@ -145,9 +148,9 @@ func newStandardMeter() *StandardMeter {
|
|
|
func (m *StandardMeter) Stop() {
|
|
|
m.lock.Lock()
|
|
|
stopped := m.stopped
|
|
|
- m.stopped = true
|
|
|
+ m.stopped = 1
|
|
|
m.lock.Unlock()
|
|
|
- if !stopped {
|
|
|
+ if stopped != 1 {
|
|
|
arbiter.Lock()
|
|
|
delete(arbiter.meters, m)
|
|
|
arbiter.Unlock()
|
|
|
@@ -156,20 +159,17 @@ func (m *StandardMeter) Stop() {
|
|
|
|
|
|
// Count returns the number of events recorded.
|
|
|
func (m *StandardMeter) Count() int64 {
|
|
|
- m.lock.RLock()
|
|
|
- count := m.snapshot.count
|
|
|
- m.lock.RUnlock()
|
|
|
- return count
|
|
|
+ return atomic.LoadInt64(&m.snapshot.count)
|
|
|
}
|
|
|
|
|
|
// Mark records the occurance of n events.
|
|
|
func (m *StandardMeter) Mark(n int64) {
|
|
|
- m.lock.Lock()
|
|
|
- defer m.lock.Unlock()
|
|
|
- if m.stopped {
|
|
|
+ if atomic.LoadUint32(&m.stopped) == 1 {
|
|
|
return
|
|
|
}
|
|
|
- m.snapshot.count += n
|
|
|
+
|
|
|
+ atomic.AddInt64(&m.snapshot.count, n)
|
|
|
+
|
|
|
m.a1.Update(n)
|
|
|
m.a5.Update(n)
|
|
|
m.a15.Update(n)
|
|
|
@@ -178,56 +178,49 @@ func (m *StandardMeter) Mark(n int64) {
|
|
|
|
|
|
// Rate1 returns the one-minute moving average rate of events per second.
|
|
|
func (m *StandardMeter) Rate1() float64 {
|
|
|
- m.lock.RLock()
|
|
|
- rate1 := m.snapshot.rate1
|
|
|
- m.lock.RUnlock()
|
|
|
- return rate1
|
|
|
+ return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rate1))
|
|
|
}
|
|
|
|
|
|
// Rate5 returns the five-minute moving average rate of events per second.
|
|
|
func (m *StandardMeter) Rate5() float64 {
|
|
|
- m.lock.RLock()
|
|
|
- rate5 := m.snapshot.rate5
|
|
|
- m.lock.RUnlock()
|
|
|
- return rate5
|
|
|
+ return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rate5))
|
|
|
}
|
|
|
|
|
|
// Rate15 returns the fifteen-minute moving average rate of events per second.
|
|
|
func (m *StandardMeter) Rate15() float64 {
|
|
|
- m.lock.RLock()
|
|
|
- rate15 := m.snapshot.rate15
|
|
|
- m.lock.RUnlock()
|
|
|
- return rate15
|
|
|
+ return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rate15))
|
|
|
}
|
|
|
|
|
|
// RateMean returns the meter's mean rate of events per second.
|
|
|
func (m *StandardMeter) RateMean() float64 {
|
|
|
- m.lock.RLock()
|
|
|
- rateMean := m.snapshot.rateMean
|
|
|
- m.lock.RUnlock()
|
|
|
- return rateMean
|
|
|
+ return math.Float64frombits(atomic.LoadUint64(&m.snapshot.rateMean))
|
|
|
}
|
|
|
|
|
|
// Snapshot returns a read-only copy of the meter.
|
|
|
func (m *StandardMeter) Snapshot() Meter {
|
|
|
- m.lock.RLock()
|
|
|
- snapshot := *m.snapshot
|
|
|
- m.lock.RUnlock()
|
|
|
- return &snapshot
|
|
|
+ copiedSnapshot := MeterSnapshot{
|
|
|
+ count: atomic.LoadInt64(&m.snapshot.count),
|
|
|
+ rate1: atomic.LoadUint64(&m.snapshot.rate1),
|
|
|
+ rate5: atomic.LoadUint64(&m.snapshot.rate5),
|
|
|
+ rate15: atomic.LoadUint64(&m.snapshot.rate15),
|
|
|
+ rateMean: atomic.LoadUint64(&m.snapshot.rateMean),
|
|
|
+ }
|
|
|
+ return &copiedSnapshot
|
|
|
}
|
|
|
|
|
|
func (m *StandardMeter) updateSnapshot() {
|
|
|
- // should run with write lock held on m.lock
|
|
|
- snapshot := m.snapshot
|
|
|
- snapshot.rate1 = m.a1.Rate()
|
|
|
- snapshot.rate5 = m.a5.Rate()
|
|
|
- snapshot.rate15 = m.a15.Rate()
|
|
|
- snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds()
|
|
|
+ rate1 := math.Float64bits(m.a1.Rate())
|
|
|
+ rate5 := math.Float64bits(m.a5.Rate())
|
|
|
+ rate15 := math.Float64bits(m.a15.Rate())
|
|
|
+ rateMean := math.Float64bits(float64(m.Count()) / time.Since(m.startTime).Seconds())
|
|
|
+
|
|
|
+ atomic.StoreUint64(&m.snapshot.rate1, rate1)
|
|
|
+ atomic.StoreUint64(&m.snapshot.rate5, rate5)
|
|
|
+ atomic.StoreUint64(&m.snapshot.rate15, rate15)
|
|
|
+ atomic.StoreUint64(&m.snapshot.rateMean, rateMean)
|
|
|
}
|
|
|
|
|
|
func (m *StandardMeter) tick() {
|
|
|
- m.lock.Lock()
|
|
|
- defer m.lock.Unlock()
|
|
|
m.a1.Tick()
|
|
|
m.a5.Tick()
|
|
|
m.a15.Tick()
|