github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/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  }