github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/rcrowley/go-metrics/meter.go (about)

     1  package metrics
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  )
     7  
     8  // Meters count events to produce exponentially-weighted moving average rates
     9  // at one-, five-, and fifteen-minutes and a mean rate.
    10  type Meter interface {
    11  	Count() int64
    12  	Mark(int64)
    13  	Rate1() float64
    14  	Rate5() float64
    15  	Rate15() float64
    16  	RateMean() float64
    17  	Snapshot() Meter
    18  }
    19  
    20  // GetOrRegisterMeter returns an existing Meter or constructs and registers a
    21  // new StandardMeter.
    22  func GetOrRegisterMeter(name string, r Registry) Meter {
    23  	if nil == r {
    24  		r = DefaultRegistry
    25  	}
    26  	return r.GetOrRegister(name, NewMeter).(Meter)
    27  }
    28  
    29  // NewMeter constructs a new StandardMeter and launches a goroutine.
    30  func NewMeter() Meter {
    31  	if UseNilMetrics {
    32  		return NilMeter{}
    33  	}
    34  	m := newStandardMeter()
    35  	arbiter.Lock()
    36  	defer arbiter.Unlock()
    37  	arbiter.meters = append(arbiter.meters, m)
    38  	if !arbiter.started {
    39  		arbiter.started = true
    40  		go arbiter.tick()
    41  	}
    42  	return m
    43  }
    44  
    45  // NewMeter constructs and registers a new StandardMeter and launches a
    46  // goroutine.
    47  func NewRegisteredMeter(name string, r Registry) Meter {
    48  	c := NewMeter()
    49  	if nil == r {
    50  		r = DefaultRegistry
    51  	}
    52  	r.Register(name, c)
    53  	return c
    54  }
    55  
    56  // MeterSnapshot is a read-only copy of another Meter.
    57  type MeterSnapshot struct {
    58  	count                          int64
    59  	rate1, rate5, rate15, rateMean float64
    60  }
    61  
    62  // Count returns the count of events at the time the snapshot was taken.
    63  func (m *MeterSnapshot) Count() int64 { return m.count }
    64  
    65  // Mark panics.
    66  func (*MeterSnapshot) Mark(n int64) {
    67  	panic("Mark called on a MeterSnapshot")
    68  }
    69  
    70  // Rate1 returns the one-minute moving average rate of events per second at the
    71  // time the snapshot was taken.
    72  func (m *MeterSnapshot) Rate1() float64 { return m.rate1 }
    73  
    74  // Rate5 returns the five-minute moving average rate of events per second at
    75  // the time the snapshot was taken.
    76  func (m *MeterSnapshot) Rate5() float64 { return m.rate5 }
    77  
    78  // Rate15 returns the fifteen-minute moving average rate of events per second
    79  // at the time the snapshot was taken.
    80  func (m *MeterSnapshot) Rate15() float64 { return m.rate15 }
    81  
    82  // RateMean returns the meter's mean rate of events per second at the time the
    83  // snapshot was taken.
    84  func (m *MeterSnapshot) RateMean() float64 { return m.rateMean }
    85  
    86  // Snapshot returns the snapshot.
    87  func (m *MeterSnapshot) Snapshot() Meter { return m }
    88  
    89  // NilMeter is a no-op Meter.
    90  type NilMeter struct{}
    91  
    92  // Count is a no-op.
    93  func (NilMeter) Count() int64 { return 0 }
    94  
    95  // Mark is a no-op.
    96  func (NilMeter) Mark(n int64) {}
    97  
    98  // Rate1 is a no-op.
    99  func (NilMeter) Rate1() float64 { return 0.0 }
   100  
   101  // Rate5 is a no-op.
   102  func (NilMeter) Rate5() float64 { return 0.0 }
   103  
   104  // Rate15is a no-op.
   105  func (NilMeter) Rate15() float64 { return 0.0 }
   106  
   107  // RateMean is a no-op.
   108  func (NilMeter) RateMean() float64 { return 0.0 }
   109  
   110  // Snapshot is a no-op.
   111  func (NilMeter) Snapshot() Meter { return NilMeter{} }
   112  
   113  // StandardMeter is the standard implementation of a Meter.
   114  type StandardMeter struct {
   115  	lock        sync.RWMutex
   116  	snapshot    *MeterSnapshot
   117  	a1, a5, a15 EWMA
   118  	startTime   time.Time
   119  }
   120  
   121  func newStandardMeter() *StandardMeter {
   122  	return &StandardMeter{
   123  		snapshot:  &MeterSnapshot{},
   124  		a1:        NewEWMA1(),
   125  		a5:        NewEWMA5(),
   126  		a15:       NewEWMA15(),
   127  		startTime: time.Now(),
   128  	}
   129  }
   130  
   131  // Count returns the number of events recorded.
   132  func (m *StandardMeter) Count() int64 {
   133  	m.lock.RLock()
   134  	count := m.snapshot.count
   135  	m.lock.RUnlock()
   136  	return count
   137  }
   138  
   139  // Mark records the occurance of n events.
   140  func (m *StandardMeter) Mark(n int64) {
   141  	m.lock.Lock()
   142  	defer m.lock.Unlock()
   143  	m.snapshot.count += n
   144  	m.a1.Update(n)
   145  	m.a5.Update(n)
   146  	m.a15.Update(n)
   147  	m.updateSnapshot()
   148  }
   149  
   150  // Rate1 returns the one-minute moving average rate of events per second.
   151  func (m *StandardMeter) Rate1() float64 {
   152  	m.lock.RLock()
   153  	rate1 := m.snapshot.rate1
   154  	m.lock.RUnlock()
   155  	return rate1
   156  }
   157  
   158  // Rate5 returns the five-minute moving average rate of events per second.
   159  func (m *StandardMeter) Rate5() float64 {
   160  	m.lock.RLock()
   161  	rate5 := m.snapshot.rate5
   162  	m.lock.RUnlock()
   163  	return rate5
   164  }
   165  
   166  // Rate15 returns the fifteen-minute moving average rate of events per second.
   167  func (m *StandardMeter) Rate15() float64 {
   168  	m.lock.RLock()
   169  	rate15 := m.snapshot.rate15
   170  	m.lock.RUnlock()
   171  	return rate15
   172  }
   173  
   174  // RateMean returns the meter's mean rate of events per second.
   175  func (m *StandardMeter) RateMean() float64 {
   176  	m.lock.RLock()
   177  	rateMean := m.snapshot.rateMean
   178  	m.lock.RUnlock()
   179  	return rateMean
   180  }
   181  
   182  // Snapshot returns a read-only copy of the meter.
   183  func (m *StandardMeter) Snapshot() Meter {
   184  	m.lock.RLock()
   185  	snapshot := *m.snapshot
   186  	m.lock.RUnlock()
   187  	return &snapshot
   188  }
   189  
   190  func (m *StandardMeter) updateSnapshot() {
   191  	// should run with write lock held on m.lock
   192  	snapshot := m.snapshot
   193  	snapshot.rate1 = m.a1.Rate()
   194  	snapshot.rate5 = m.a5.Rate()
   195  	snapshot.rate15 = m.a15.Rate()
   196  	snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds()
   197  }
   198  
   199  func (m *StandardMeter) tick() {
   200  	m.lock.Lock()
   201  	defer m.lock.Unlock()
   202  	m.a1.Tick()
   203  	m.a5.Tick()
   204  	m.a15.Tick()
   205  	m.updateSnapshot()
   206  }
   207  
   208  type meterArbiter struct {
   209  	sync.RWMutex
   210  	started bool
   211  	meters  []*StandardMeter
   212  	ticker  *time.Ticker
   213  }
   214  
   215  var arbiter = meterArbiter{ticker: time.NewTicker(5e9)}
   216  
   217  // Ticks meters on the scheduled interval
   218  func (ma *meterArbiter) tick() {
   219  	for {
   220  		select {
   221  		case <-ma.ticker.C:
   222  			ma.tickMeters()
   223  		}
   224  	}
   225  }
   226  
   227  func (ma *meterArbiter) tickMeters() {
   228  	ma.RLock()
   229  	defer ma.RUnlock()
   230  	for _, meter := range ma.meters {
   231  		meter.tick()
   232  	}
   233  }