github.com/theQRL/go-zond@v0.1.1/metrics/resetting_timer.go (about) 1 package metrics 2 3 import ( 4 "sync" 5 "time" 6 ) 7 8 // Initial slice capacity for the values stored in a ResettingTimer 9 const InitialResettingTimerSliceCap = 10 10 11 type ResettingTimerSnapshot interface { 12 Count() int 13 Mean() float64 14 Max() int64 15 Min() int64 16 Percentiles([]float64) []float64 17 } 18 19 // ResettingTimer is used for storing aggregated values for timers, which are reset on every flush interval. 20 type ResettingTimer interface { 21 Snapshot() ResettingTimerSnapshot 22 Time(func()) 23 Update(time.Duration) 24 UpdateSince(time.Time) 25 } 26 27 // GetOrRegisterResettingTimer returns an existing ResettingTimer or constructs and registers a 28 // new StandardResettingTimer. 29 func GetOrRegisterResettingTimer(name string, r Registry) ResettingTimer { 30 if nil == r { 31 r = DefaultRegistry 32 } 33 return r.GetOrRegister(name, NewResettingTimer).(ResettingTimer) 34 } 35 36 // NewRegisteredResettingTimer constructs and registers a new StandardResettingTimer. 37 func NewRegisteredResettingTimer(name string, r Registry) ResettingTimer { 38 c := NewResettingTimer() 39 if nil == r { 40 r = DefaultRegistry 41 } 42 r.Register(name, c) 43 return c 44 } 45 46 // NewResettingTimer constructs a new StandardResettingTimer 47 func NewResettingTimer() ResettingTimer { 48 if !Enabled { 49 return NilResettingTimer{} 50 } 51 return &StandardResettingTimer{ 52 values: make([]int64, 0, InitialResettingTimerSliceCap), 53 } 54 } 55 56 // NilResettingTimer is a no-op ResettingTimer. 57 type NilResettingTimer struct{} 58 59 func (NilResettingTimer) Values() []int64 { return nil } 60 func (n NilResettingTimer) Snapshot() ResettingTimerSnapshot { return n } 61 func (NilResettingTimer) Time(f func()) { f() } 62 func (NilResettingTimer) Update(time.Duration) {} 63 func (NilResettingTimer) Percentiles([]float64) []float64 { return nil } 64 func (NilResettingTimer) Mean() float64 { return 0.0 } 65 func (NilResettingTimer) Max() int64 { return 0 } 66 func (NilResettingTimer) Min() int64 { return 0 } 67 func (NilResettingTimer) UpdateSince(time.Time) {} 68 func (NilResettingTimer) Count() int { return 0 } 69 70 // StandardResettingTimer is the standard implementation of a ResettingTimer. 71 // and Meter. 72 type StandardResettingTimer struct { 73 values []int64 74 sum int64 // sum is a running count of the total sum, used later to calculate mean 75 76 mutex sync.Mutex 77 } 78 79 // Snapshot resets the timer and returns a read-only copy of its contents. 80 func (t *StandardResettingTimer) Snapshot() ResettingTimerSnapshot { 81 t.mutex.Lock() 82 defer t.mutex.Unlock() 83 snapshot := &resettingTimerSnapshot{} 84 if len(t.values) > 0 { 85 snapshot.mean = float64(t.sum) / float64(len(t.values)) 86 snapshot.values = t.values 87 t.values = make([]int64, 0, InitialResettingTimerSliceCap) 88 } 89 t.sum = 0 90 return snapshot 91 } 92 93 // Record the duration of the execution of the given function. 94 func (t *StandardResettingTimer) Time(f func()) { 95 ts := time.Now() 96 f() 97 t.Update(time.Since(ts)) 98 } 99 100 // Record the duration of an event. 101 func (t *StandardResettingTimer) Update(d time.Duration) { 102 t.mutex.Lock() 103 defer t.mutex.Unlock() 104 t.values = append(t.values, int64(d)) 105 t.sum += int64(d) 106 } 107 108 // Record the duration of an event that started at a time and ends now. 109 func (t *StandardResettingTimer) UpdateSince(ts time.Time) { 110 t.Update(time.Since(ts)) 111 } 112 113 // resettingTimerSnapshot is a point-in-time copy of another ResettingTimer. 114 type resettingTimerSnapshot struct { 115 values []int64 116 mean float64 117 max int64 118 min int64 119 thresholdBoundaries []float64 120 calculated bool 121 } 122 123 // Count return the length of the values from snapshot. 124 func (t *resettingTimerSnapshot) Count() int { 125 return len(t.values) 126 } 127 128 // Percentiles returns the boundaries for the input percentiles. 129 // note: this method is not thread safe 130 func (t *resettingTimerSnapshot) Percentiles(percentiles []float64) []float64 { 131 t.calc(percentiles) 132 return t.thresholdBoundaries 133 } 134 135 // Mean returns the mean of the snapshotted values 136 // note: this method is not thread safe 137 func (t *resettingTimerSnapshot) Mean() float64 { 138 if !t.calculated { 139 t.calc(nil) 140 } 141 142 return t.mean 143 } 144 145 // Max returns the max of the snapshotted values 146 // note: this method is not thread safe 147 func (t *resettingTimerSnapshot) Max() int64 { 148 if !t.calculated { 149 t.calc(nil) 150 } 151 return t.max 152 } 153 154 // Min returns the min of the snapshotted values 155 // note: this method is not thread safe 156 func (t *resettingTimerSnapshot) Min() int64 { 157 if !t.calculated { 158 t.calc(nil) 159 } 160 return t.min 161 } 162 163 func (t *resettingTimerSnapshot) calc(percentiles []float64) { 164 scores := CalculatePercentiles(t.values, percentiles) 165 t.thresholdBoundaries = scores 166 if len(t.values) == 0 { 167 return 168 } 169 t.min = t.values[0] 170 t.max = t.values[len(t.values)-1] 171 }