Scott Baker | 2d89798 | 2019-09-24 11:50:08 -0700 | [diff] [blame^] | 1 | package metrics |
| 2 | |
| 3 | import ( |
| 4 | "sync" |
| 5 | "time" |
| 6 | ) |
| 7 | |
| 8 | // Timers capture the duration and rate of events. |
| 9 | type Timer interface { |
| 10 | Count() int64 |
| 11 | Max() int64 |
| 12 | Mean() float64 |
| 13 | Min() int64 |
| 14 | Percentile(float64) float64 |
| 15 | Percentiles([]float64) []float64 |
| 16 | Rate1() float64 |
| 17 | Rate5() float64 |
| 18 | Rate15() float64 |
| 19 | RateMean() float64 |
| 20 | Snapshot() Timer |
| 21 | StdDev() float64 |
| 22 | Stop() |
| 23 | Sum() int64 |
| 24 | Time(func()) |
| 25 | Update(time.Duration) |
| 26 | UpdateSince(time.Time) |
| 27 | Variance() float64 |
| 28 | } |
| 29 | |
| 30 | // GetOrRegisterTimer returns an existing Timer or constructs and registers a |
| 31 | // new StandardTimer. |
| 32 | // Be sure to unregister the meter from the registry once it is of no use to |
| 33 | // allow for garbage collection. |
| 34 | func GetOrRegisterTimer(name string, r Registry) Timer { |
| 35 | if nil == r { |
| 36 | r = DefaultRegistry |
| 37 | } |
| 38 | return r.GetOrRegister(name, NewTimer).(Timer) |
| 39 | } |
| 40 | |
| 41 | // NewCustomTimer constructs a new StandardTimer from a Histogram and a Meter. |
| 42 | // Be sure to call Stop() once the timer is of no use to allow for garbage collection. |
| 43 | func NewCustomTimer(h Histogram, m Meter) Timer { |
| 44 | if UseNilMetrics { |
| 45 | return NilTimer{} |
| 46 | } |
| 47 | return &StandardTimer{ |
| 48 | histogram: h, |
| 49 | meter: m, |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | // NewRegisteredTimer constructs and registers a new StandardTimer. |
| 54 | // Be sure to unregister the meter from the registry once it is of no use to |
| 55 | // allow for garbage collection. |
| 56 | func NewRegisteredTimer(name string, r Registry) Timer { |
| 57 | c := NewTimer() |
| 58 | if nil == r { |
| 59 | r = DefaultRegistry |
| 60 | } |
| 61 | r.Register(name, c) |
| 62 | return c |
| 63 | } |
| 64 | |
| 65 | // NewTimer constructs a new StandardTimer using an exponentially-decaying |
| 66 | // sample with the same reservoir size and alpha as UNIX load averages. |
| 67 | // Be sure to call Stop() once the timer is of no use to allow for garbage collection. |
| 68 | func NewTimer() Timer { |
| 69 | if UseNilMetrics { |
| 70 | return NilTimer{} |
| 71 | } |
| 72 | return &StandardTimer{ |
| 73 | histogram: NewHistogram(NewExpDecaySample(1028, 0.015)), |
| 74 | meter: NewMeter(), |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | // NilTimer is a no-op Timer. |
| 79 | type NilTimer struct { |
| 80 | h Histogram |
| 81 | m Meter |
| 82 | } |
| 83 | |
| 84 | // Count is a no-op. |
| 85 | func (NilTimer) Count() int64 { return 0 } |
| 86 | |
| 87 | // Max is a no-op. |
| 88 | func (NilTimer) Max() int64 { return 0 } |
| 89 | |
| 90 | // Mean is a no-op. |
| 91 | func (NilTimer) Mean() float64 { return 0.0 } |
| 92 | |
| 93 | // Min is a no-op. |
| 94 | func (NilTimer) Min() int64 { return 0 } |
| 95 | |
| 96 | // Percentile is a no-op. |
| 97 | func (NilTimer) Percentile(p float64) float64 { return 0.0 } |
| 98 | |
| 99 | // Percentiles is a no-op. |
| 100 | func (NilTimer) Percentiles(ps []float64) []float64 { |
| 101 | return make([]float64, len(ps)) |
| 102 | } |
| 103 | |
| 104 | // Rate1 is a no-op. |
| 105 | func (NilTimer) Rate1() float64 { return 0.0 } |
| 106 | |
| 107 | // Rate5 is a no-op. |
| 108 | func (NilTimer) Rate5() float64 { return 0.0 } |
| 109 | |
| 110 | // Rate15 is a no-op. |
| 111 | func (NilTimer) Rate15() float64 { return 0.0 } |
| 112 | |
| 113 | // RateMean is a no-op. |
| 114 | func (NilTimer) RateMean() float64 { return 0.0 } |
| 115 | |
| 116 | // Snapshot is a no-op. |
| 117 | func (NilTimer) Snapshot() Timer { return NilTimer{} } |
| 118 | |
| 119 | // StdDev is a no-op. |
| 120 | func (NilTimer) StdDev() float64 { return 0.0 } |
| 121 | |
| 122 | // Stop is a no-op. |
| 123 | func (NilTimer) Stop() {} |
| 124 | |
| 125 | // Sum is a no-op. |
| 126 | func (NilTimer) Sum() int64 { return 0 } |
| 127 | |
| 128 | // Time is a no-op. |
| 129 | func (NilTimer) Time(func()) {} |
| 130 | |
| 131 | // Update is a no-op. |
| 132 | func (NilTimer) Update(time.Duration) {} |
| 133 | |
| 134 | // UpdateSince is a no-op. |
| 135 | func (NilTimer) UpdateSince(time.Time) {} |
| 136 | |
| 137 | // Variance is a no-op. |
| 138 | func (NilTimer) Variance() float64 { return 0.0 } |
| 139 | |
| 140 | // StandardTimer is the standard implementation of a Timer and uses a Histogram |
| 141 | // and Meter. |
| 142 | type StandardTimer struct { |
| 143 | histogram Histogram |
| 144 | meter Meter |
| 145 | mutex sync.Mutex |
| 146 | } |
| 147 | |
| 148 | // Count returns the number of events recorded. |
| 149 | func (t *StandardTimer) Count() int64 { |
| 150 | return t.histogram.Count() |
| 151 | } |
| 152 | |
| 153 | // Max returns the maximum value in the sample. |
| 154 | func (t *StandardTimer) Max() int64 { |
| 155 | return t.histogram.Max() |
| 156 | } |
| 157 | |
| 158 | // Mean returns the mean of the values in the sample. |
| 159 | func (t *StandardTimer) Mean() float64 { |
| 160 | return t.histogram.Mean() |
| 161 | } |
| 162 | |
| 163 | // Min returns the minimum value in the sample. |
| 164 | func (t *StandardTimer) Min() int64 { |
| 165 | return t.histogram.Min() |
| 166 | } |
| 167 | |
| 168 | // Percentile returns an arbitrary percentile of the values in the sample. |
| 169 | func (t *StandardTimer) Percentile(p float64) float64 { |
| 170 | return t.histogram.Percentile(p) |
| 171 | } |
| 172 | |
| 173 | // Percentiles returns a slice of arbitrary percentiles of the values in the |
| 174 | // sample. |
| 175 | func (t *StandardTimer) Percentiles(ps []float64) []float64 { |
| 176 | return t.histogram.Percentiles(ps) |
| 177 | } |
| 178 | |
| 179 | // Rate1 returns the one-minute moving average rate of events per second. |
| 180 | func (t *StandardTimer) Rate1() float64 { |
| 181 | return t.meter.Rate1() |
| 182 | } |
| 183 | |
| 184 | // Rate5 returns the five-minute moving average rate of events per second. |
| 185 | func (t *StandardTimer) Rate5() float64 { |
| 186 | return t.meter.Rate5() |
| 187 | } |
| 188 | |
| 189 | // Rate15 returns the fifteen-minute moving average rate of events per second. |
| 190 | func (t *StandardTimer) Rate15() float64 { |
| 191 | return t.meter.Rate15() |
| 192 | } |
| 193 | |
| 194 | // RateMean returns the meter's mean rate of events per second. |
| 195 | func (t *StandardTimer) RateMean() float64 { |
| 196 | return t.meter.RateMean() |
| 197 | } |
| 198 | |
| 199 | // Snapshot returns a read-only copy of the timer. |
| 200 | func (t *StandardTimer) Snapshot() Timer { |
| 201 | t.mutex.Lock() |
| 202 | defer t.mutex.Unlock() |
| 203 | return &TimerSnapshot{ |
| 204 | histogram: t.histogram.Snapshot().(*HistogramSnapshot), |
| 205 | meter: t.meter.Snapshot().(*MeterSnapshot), |
| 206 | } |
| 207 | } |
| 208 | |
| 209 | // StdDev returns the standard deviation of the values in the sample. |
| 210 | func (t *StandardTimer) StdDev() float64 { |
| 211 | return t.histogram.StdDev() |
| 212 | } |
| 213 | |
| 214 | // Stop stops the meter. |
| 215 | func (t *StandardTimer) Stop() { |
| 216 | t.meter.Stop() |
| 217 | } |
| 218 | |
| 219 | // Sum returns the sum in the sample. |
| 220 | func (t *StandardTimer) Sum() int64 { |
| 221 | return t.histogram.Sum() |
| 222 | } |
| 223 | |
| 224 | // Record the duration of the execution of the given function. |
| 225 | func (t *StandardTimer) Time(f func()) { |
| 226 | ts := time.Now() |
| 227 | f() |
| 228 | t.Update(time.Since(ts)) |
| 229 | } |
| 230 | |
| 231 | // Record the duration of an event. |
| 232 | func (t *StandardTimer) Update(d time.Duration) { |
| 233 | t.mutex.Lock() |
| 234 | defer t.mutex.Unlock() |
| 235 | t.histogram.Update(int64(d)) |
| 236 | t.meter.Mark(1) |
| 237 | } |
| 238 | |
| 239 | // Record the duration of an event that started at a time and ends now. |
| 240 | func (t *StandardTimer) UpdateSince(ts time.Time) { |
| 241 | t.mutex.Lock() |
| 242 | defer t.mutex.Unlock() |
| 243 | t.histogram.Update(int64(time.Since(ts))) |
| 244 | t.meter.Mark(1) |
| 245 | } |
| 246 | |
| 247 | // Variance returns the variance of the values in the sample. |
| 248 | func (t *StandardTimer) Variance() float64 { |
| 249 | return t.histogram.Variance() |
| 250 | } |
| 251 | |
| 252 | // TimerSnapshot is a read-only copy of another Timer. |
| 253 | type TimerSnapshot struct { |
| 254 | histogram *HistogramSnapshot |
| 255 | meter *MeterSnapshot |
| 256 | } |
| 257 | |
| 258 | // Count returns the number of events recorded at the time the snapshot was |
| 259 | // taken. |
| 260 | func (t *TimerSnapshot) Count() int64 { return t.histogram.Count() } |
| 261 | |
| 262 | // Max returns the maximum value at the time the snapshot was taken. |
| 263 | func (t *TimerSnapshot) Max() int64 { return t.histogram.Max() } |
| 264 | |
| 265 | // Mean returns the mean value at the time the snapshot was taken. |
| 266 | func (t *TimerSnapshot) Mean() float64 { return t.histogram.Mean() } |
| 267 | |
| 268 | // Min returns the minimum value at the time the snapshot was taken. |
| 269 | func (t *TimerSnapshot) Min() int64 { return t.histogram.Min() } |
| 270 | |
| 271 | // Percentile returns an arbitrary percentile of sampled values at the time the |
| 272 | // snapshot was taken. |
| 273 | func (t *TimerSnapshot) Percentile(p float64) float64 { |
| 274 | return t.histogram.Percentile(p) |
| 275 | } |
| 276 | |
| 277 | // Percentiles returns a slice of arbitrary percentiles of sampled values at |
| 278 | // the time the snapshot was taken. |
| 279 | func (t *TimerSnapshot) Percentiles(ps []float64) []float64 { |
| 280 | return t.histogram.Percentiles(ps) |
| 281 | } |
| 282 | |
| 283 | // Rate1 returns the one-minute moving average rate of events per second at the |
| 284 | // time the snapshot was taken. |
| 285 | func (t *TimerSnapshot) Rate1() float64 { return t.meter.Rate1() } |
| 286 | |
| 287 | // Rate5 returns the five-minute moving average rate of events per second at |
| 288 | // the time the snapshot was taken. |
| 289 | func (t *TimerSnapshot) Rate5() float64 { return t.meter.Rate5() } |
| 290 | |
| 291 | // Rate15 returns the fifteen-minute moving average rate of events per second |
| 292 | // at the time the snapshot was taken. |
| 293 | func (t *TimerSnapshot) Rate15() float64 { return t.meter.Rate15() } |
| 294 | |
| 295 | // RateMean returns the meter's mean rate of events per second at the time the |
| 296 | // snapshot was taken. |
| 297 | func (t *TimerSnapshot) RateMean() float64 { return t.meter.RateMean() } |
| 298 | |
| 299 | // Snapshot returns the snapshot. |
| 300 | func (t *TimerSnapshot) Snapshot() Timer { return t } |
| 301 | |
| 302 | // StdDev returns the standard deviation of the values at the time the snapshot |
| 303 | // was taken. |
| 304 | func (t *TimerSnapshot) StdDev() float64 { return t.histogram.StdDev() } |
| 305 | |
| 306 | // Stop is a no-op. |
| 307 | func (t *TimerSnapshot) Stop() {} |
| 308 | |
| 309 | // Sum returns the sum at the time the snapshot was taken. |
| 310 | func (t *TimerSnapshot) Sum() int64 { return t.histogram.Sum() } |
| 311 | |
| 312 | // Time panics. |
| 313 | func (*TimerSnapshot) Time(func()) { |
| 314 | panic("Time called on a TimerSnapshot") |
| 315 | } |
| 316 | |
| 317 | // Update panics. |
| 318 | func (*TimerSnapshot) Update(time.Duration) { |
| 319 | panic("Update called on a TimerSnapshot") |
| 320 | } |
| 321 | |
| 322 | // UpdateSince panics. |
| 323 | func (*TimerSnapshot) UpdateSince(time.Time) { |
| 324 | panic("UpdateSince called on a TimerSnapshot") |
| 325 | } |
| 326 | |
| 327 | // Variance returns the variance of the values at the time the snapshot was |
| 328 | // taken. |
| 329 | func (t *TimerSnapshot) Variance() float64 { return t.histogram.Variance() } |