meter.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // includes code from
  2. // https://raw.githubusercontent.com/rcrowley/go-metrics/master/sample.go
  3. // Copyright 2012 Richard Crowley. All rights reserved.
  4. package metrics
  5. import (
  6. "sync"
  7. "time"
  8. )
  9. // Meters count events to produce exponentially-weighted moving average rates
  10. // at one-, five-, and fifteen-minutes and a mean rate.
  11. type Meter interface {
  12. Metric
  13. Count() int64
  14. Mark(int64)
  15. Rate1() float64
  16. Rate5() float64
  17. Rate15() float64
  18. RateMean() float64
  19. }
  20. // NewMeter constructs a new StandardMeter and launches a goroutine.
  21. func NewMeter(meta *MetricMeta) Meter {
  22. if UseNilMetrics {
  23. return NilMeter{}
  24. }
  25. m := newStandardMeter(meta)
  26. arbiter.Lock()
  27. defer arbiter.Unlock()
  28. arbiter.meters = append(arbiter.meters, m)
  29. if !arbiter.started {
  30. arbiter.started = true
  31. go arbiter.tick()
  32. }
  33. return m
  34. }
  35. type MeterSnapshot struct {
  36. *MetricMeta
  37. count int64
  38. rate1, rate5, rate15, rateMean float64
  39. }
  40. // Count returns the count of events at the time the snapshot was taken.
  41. func (m *MeterSnapshot) Count() int64 { return m.count }
  42. // Mark panics.
  43. func (*MeterSnapshot) Mark(n int64) {
  44. panic("Mark called on a MeterSnapshot")
  45. }
  46. // Rate1 returns the one-minute moving average rate of events per second at the
  47. // time the snapshot was taken.
  48. func (m *MeterSnapshot) Rate1() float64 { return m.rate1 }
  49. // Rate5 returns the five-minute moving average rate of events per second at
  50. // the time the snapshot was taken.
  51. func (m *MeterSnapshot) Rate5() float64 { return m.rate5 }
  52. // Rate15 returns the fifteen-minute moving average rate of events per second
  53. // at the time the snapshot was taken.
  54. func (m *MeterSnapshot) Rate15() float64 { return m.rate15 }
  55. // RateMean returns the meter's mean rate of events per second at the time the
  56. // snapshot was taken.
  57. func (m *MeterSnapshot) RateMean() float64 { return m.rateMean }
  58. // Snapshot returns the snapshot.
  59. func (m *MeterSnapshot) Snapshot() Metric { return m }
  60. // NilMeter is a no-op Meter.
  61. type NilMeter struct{ *MetricMeta }
  62. // Count is a no-op.
  63. func (NilMeter) Count() int64 { return 0 }
  64. // Mark is a no-op.
  65. func (NilMeter) Mark(n int64) {}
  66. // Rate1 is a no-op.
  67. func (NilMeter) Rate1() float64 { return 0.0 }
  68. // Rate5 is a no-op.
  69. func (NilMeter) Rate5() float64 { return 0.0 }
  70. // Rate15is a no-op.
  71. func (NilMeter) Rate15() float64 { return 0.0 }
  72. // RateMean is a no-op.
  73. func (NilMeter) RateMean() float64 { return 0.0 }
  74. // Snapshot is a no-op.
  75. func (NilMeter) Snapshot() Metric { return NilMeter{} }
  76. // StandardMeter is the standard implementation of a Meter.
  77. type StandardMeter struct {
  78. *MetricMeta
  79. lock sync.RWMutex
  80. snapshot *MeterSnapshot
  81. a1, a5, a15 EWMA
  82. startTime time.Time
  83. }
  84. func newStandardMeter(meta *MetricMeta) *StandardMeter {
  85. return &StandardMeter{
  86. MetricMeta: meta,
  87. snapshot: &MeterSnapshot{MetricMeta: meta},
  88. a1: NewEWMA1(),
  89. a5: NewEWMA5(),
  90. a15: NewEWMA15(),
  91. startTime: time.Now(),
  92. }
  93. }
  94. // Count returns the number of events recorded.
  95. func (m *StandardMeter) Count() int64 {
  96. m.lock.RLock()
  97. count := m.snapshot.count
  98. m.lock.RUnlock()
  99. return count
  100. }
  101. // Mark records the occurance of n events.
  102. func (m *StandardMeter) Mark(n int64) {
  103. m.lock.Lock()
  104. defer m.lock.Unlock()
  105. m.snapshot.count += n
  106. m.a1.Update(n)
  107. m.a5.Update(n)
  108. m.a15.Update(n)
  109. m.updateSnapshot()
  110. }
  111. // Rate1 returns the one-minute moving average rate of events per second.
  112. func (m *StandardMeter) Rate1() float64 {
  113. m.lock.RLock()
  114. rate1 := m.snapshot.rate1
  115. m.lock.RUnlock()
  116. return rate1
  117. }
  118. // Rate5 returns the five-minute moving average rate of events per second.
  119. func (m *StandardMeter) Rate5() float64 {
  120. m.lock.RLock()
  121. rate5 := m.snapshot.rate5
  122. m.lock.RUnlock()
  123. return rate5
  124. }
  125. // Rate15 returns the fifteen-minute moving average rate of events per second.
  126. func (m *StandardMeter) Rate15() float64 {
  127. m.lock.RLock()
  128. rate15 := m.snapshot.rate15
  129. m.lock.RUnlock()
  130. return rate15
  131. }
  132. // RateMean returns the meter's mean rate of events per second.
  133. func (m *StandardMeter) RateMean() float64 {
  134. m.lock.RLock()
  135. rateMean := m.snapshot.rateMean
  136. m.lock.RUnlock()
  137. return rateMean
  138. }
  139. // Snapshot returns a read-only copy of the meter.
  140. func (m *StandardMeter) Snapshot() Metric {
  141. m.lock.RLock()
  142. snapshot := *m.snapshot
  143. m.lock.RUnlock()
  144. return &snapshot
  145. }
  146. func (m *StandardMeter) updateSnapshot() {
  147. // should run with write lock held on m.lock
  148. snapshot := m.snapshot
  149. snapshot.rate1 = m.a1.Rate()
  150. snapshot.rate5 = m.a5.Rate()
  151. snapshot.rate15 = m.a15.Rate()
  152. snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds()
  153. }
  154. func (m *StandardMeter) tick() {
  155. m.lock.Lock()
  156. defer m.lock.Unlock()
  157. m.a1.Tick()
  158. m.a5.Tick()
  159. m.a15.Tick()
  160. m.updateSnapshot()
  161. }
  162. type meterArbiter struct {
  163. sync.RWMutex
  164. started bool
  165. meters []*StandardMeter
  166. ticker *time.Ticker
  167. }
  168. var arbiter = meterArbiter{ticker: time.NewTicker(5e9)}
  169. // Ticks meters on the scheduled interval
  170. func (ma *meterArbiter) tick() {
  171. for {
  172. select {
  173. case <-ma.ticker.C:
  174. ma.tickMeters()
  175. }
  176. }
  177. }
  178. func (ma *meterArbiter) tickMeters() {
  179. ma.RLock()
  180. defer ma.RUnlock()
  181. for _, meter := range ma.meters {
  182. meter.tick()
  183. }
  184. }