github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/utilities/metrics/meter.go (about) 1 package metrics 2 3 import ( 4 "sync" 5 "time" 6 ) 7 8 type Meter interface { 9 Count() int64 10 Mark(int64) 11 Rate1() float64 12 Rate5() float64 13 Rate15() float64 14 RateMean() float64 15 Snapshot() Meter 16 Stop() 17 } 18 19 func GetOrRegisterMeter(name string, r Registry) Meter { 20 if nil == r { 21 r = DefaultRegistry 22 } 23 return r.GetOrRegister(name, NewMeter).(Meter) 24 } 25 26 func NewMeter() Meter { 27 if !Enabled { 28 return NilMeter{} 29 } 30 m := newStandardMeter() 31 arbiter.Lock() 32 defer arbiter.Unlock() 33 arbiter.meters[m] = struct{}{} 34 if !arbiter.started { 35 arbiter.started = true 36 go arbiter.tick() 37 } 38 return m 39 } 40 41 func NewRegisteredMeter(name string, r Registry) Meter { 42 c := NewMeter() 43 if nil == r { 44 r = DefaultRegistry 45 } 46 r.Register(name, c) 47 return c 48 } 49 50 type MeterSnapshot struct { 51 count int64 52 rate1, rate5, rate15, rateMean float64 53 } 54 55 func (m *MeterSnapshot) Count() int64 { return m.count } 56 57 func (*MeterSnapshot) Mark(n int64) { 58 panic("Mark called on a MeterSnapshot") 59 } 60 61 func (m *MeterSnapshot) Rate1() float64 { return m.rate1 } 62 63 func (m *MeterSnapshot) Rate5() float64 { return m.rate5 } 64 65 func (m *MeterSnapshot) Rate15() float64 { return m.rate15 } 66 67 func (m *MeterSnapshot) RateMean() float64 { return m.rateMean } 68 69 func (m *MeterSnapshot) Snapshot() Meter { return m } 70 71 func (m *MeterSnapshot) Stop() {} 72 73 type NilMeter struct{} 74 75 func (NilMeter) Count() int64 { return 0 } 76 77 func (NilMeter) Mark(n int64) {} 78 79 func (NilMeter) Rate1() float64 { return 0.0 } 80 81 func (NilMeter) Rate5() float64 { return 0.0 } 82 83 func (NilMeter) Rate15() float64 { return 0.0 } 84 85 func (NilMeter) RateMean() float64 { return 0.0 } 86 87 func (NilMeter) Snapshot() Meter { return NilMeter{} } 88 89 func (NilMeter) Stop() {} 90 91 type StandardMeter struct { 92 lock sync.RWMutex 93 snapshot *MeterSnapshot 94 a1, a5, a15 EWMA 95 startTime time.Time 96 stopped bool 97 } 98 99 func newStandardMeter() *StandardMeter { 100 return &StandardMeter{ 101 snapshot: &MeterSnapshot{}, 102 a1: NewEWMA1(), 103 a5: NewEWMA5(), 104 a15: NewEWMA15(), 105 startTime: time.Now(), 106 } 107 } 108 109 func (m *StandardMeter) Stop() { 110 m.lock.Lock() 111 stopped := m.stopped 112 m.stopped = true 113 m.lock.Unlock() 114 if !stopped { 115 arbiter.Lock() 116 delete(arbiter.meters, m) 117 arbiter.Unlock() 118 } 119 } 120 121 func (m *StandardMeter) Count() int64 { 122 m.lock.RLock() 123 count := m.snapshot.count 124 m.lock.RUnlock() 125 return count 126 } 127 128 func (m *StandardMeter) Mark(n int64) { 129 m.lock.Lock() 130 defer m.lock.Unlock() 131 if m.stopped { 132 return 133 } 134 m.snapshot.count += n 135 m.a1.Update(n) 136 m.a5.Update(n) 137 m.a15.Update(n) 138 m.updateSnapshot() 139 } 140 141 func (m *StandardMeter) Rate1() float64 { 142 m.lock.RLock() 143 rate1 := m.snapshot.rate1 144 m.lock.RUnlock() 145 return rate1 146 } 147 148 func (m *StandardMeter) Rate5() float64 { 149 m.lock.RLock() 150 rate5 := m.snapshot.rate5 151 m.lock.RUnlock() 152 return rate5 153 } 154 155 func (m *StandardMeter) Rate15() float64 { 156 m.lock.RLock() 157 rate15 := m.snapshot.rate15 158 m.lock.RUnlock() 159 return rate15 160 } 161 162 func (m *StandardMeter) RateMean() float64 { 163 m.lock.RLock() 164 rateMean := m.snapshot.rateMean 165 m.lock.RUnlock() 166 return rateMean 167 } 168 169 func (m *StandardMeter) Snapshot() Meter { 170 m.lock.RLock() 171 snapshot := *m.snapshot 172 m.lock.RUnlock() 173 return &snapshot 174 } 175 176 func (m *StandardMeter) updateSnapshot() { 177 178 snapshot := m.snapshot 179 snapshot.rate1 = m.a1.Rate() 180 snapshot.rate5 = m.a5.Rate() 181 snapshot.rate15 = m.a15.Rate() 182 snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds() 183 } 184 185 func (m *StandardMeter) tick() { 186 m.lock.Lock() 187 defer m.lock.Unlock() 188 m.a1.Tick() 189 m.a5.Tick() 190 m.a15.Tick() 191 m.updateSnapshot() 192 } 193 194 type meterArbiter struct { 195 sync.RWMutex 196 started bool 197 meters map[*StandardMeter]struct{} 198 ticker *time.Ticker 199 } 200 201 var arbiter = meterArbiter{ticker: time.NewTicker(5e9), meters: make(map[*StandardMeter]struct{})} 202 203 func (ma *meterArbiter) tick() { 204 for range ma.ticker.C { 205 ma.tickMeters() 206 } 207 } 208 209 func (ma *meterArbiter) tickMeters() { 210 ma.RLock() 211 defer ma.RUnlock() 212 for meter := range ma.meters { 213 meter.tick() 214 } 215 }