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