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  }