github.com/Psiphon-Labs/goarista@v0.0.0-20160825065156-d002785f4c67/monitor/stats/counter.go (about) 1 package stats 2 3 import ( 4 "sync" 5 "time" 6 ) 7 8 var ( 9 // TimeNow is used for testing. 10 TimeNow = time.Now 11 ) 12 13 const ( 14 hour = 0 15 tenminutes = 1 16 minute = 2 17 ) 18 19 // Counter is a counter that keeps track of its recent values over a given 20 // period of time, and with a given resolution. Use newCounter() to instantiate. 21 type Counter struct { 22 mu sync.RWMutex 23 ts [3]*timeseries 24 lastUpdate time.Time 25 } 26 27 // newCounter returns a new Counter. 28 func newCounter() *Counter { 29 now := TimeNow() 30 c := &Counter{} 31 c.ts[hour] = newTimeSeries(now, time.Hour, time.Minute) 32 c.ts[tenminutes] = newTimeSeries(now, 10*time.Minute, 10*time.Second) 33 c.ts[minute] = newTimeSeries(now, time.Minute, time.Second) 34 return c 35 } 36 37 func (c *Counter) advance() time.Time { 38 now := TimeNow() 39 for _, ts := range c.ts { 40 ts.advanceTime(now) 41 } 42 return now 43 } 44 45 // Value returns the current value of the counter. 46 func (c *Counter) Value() int64 { 47 c.mu.RLock() 48 defer c.mu.RUnlock() 49 return c.ts[minute].headValue() 50 } 51 52 // LastUpdate returns the last update time of the counter. 53 func (c *Counter) LastUpdate() time.Time { 54 c.mu.RLock() 55 defer c.mu.RUnlock() 56 return c.lastUpdate 57 } 58 59 // Set updates the current value of the counter. 60 func (c *Counter) Set(value int64) { 61 c.mu.Lock() 62 defer c.mu.Unlock() 63 c.lastUpdate = c.advance() 64 for _, ts := range c.ts { 65 ts.set(value) 66 } 67 } 68 69 // Incr increments the current value of the counter by 'delta'. 70 func (c *Counter) Incr(delta int64) { 71 c.mu.Lock() 72 defer c.mu.Unlock() 73 c.lastUpdate = c.advance() 74 for _, ts := range c.ts { 75 ts.incr(delta) 76 } 77 } 78 79 // Delta1h returns the delta for the last hour. 80 func (c *Counter) Delta1h() int64 { 81 c.mu.RLock() 82 defer c.mu.RUnlock() 83 c.advance() 84 return c.ts[hour].delta() 85 } 86 87 // Delta10m returns the delta for the last 10 minutes. 88 func (c *Counter) Delta10m() int64 { 89 c.mu.RLock() 90 defer c.mu.RUnlock() 91 c.advance() 92 return c.ts[tenminutes].delta() 93 } 94 95 // Delta1m returns the delta for the last minute. 96 func (c *Counter) Delta1m() int64 { 97 c.mu.RLock() 98 defer c.mu.RUnlock() 99 c.advance() 100 return c.ts[minute].delta() 101 } 102 103 // Rate1h returns the rate of change of the counter in the last hour. 104 func (c *Counter) Rate1h() float64 { 105 c.mu.RLock() 106 defer c.mu.RUnlock() 107 c.advance() 108 return c.ts[hour].rate() 109 } 110 111 // Rate10m returns the rate of change of the counter in the last 10 minutes. 112 func (c *Counter) Rate10m() float64 { 113 c.mu.RLock() 114 defer c.mu.RUnlock() 115 c.advance() 116 return c.ts[tenminutes].rate() 117 } 118 119 // Rate1m returns the rate of change of the counter in the last minute. 120 func (c *Counter) Rate1m() float64 { 121 c.mu.RLock() 122 defer c.mu.RUnlock() 123 c.advance() 124 return c.ts[minute].rate() 125 } 126 127 // Reset resets the counter to an empty state. 128 func (c *Counter) Reset() { 129 c.mu.Lock() 130 defer c.mu.Unlock() 131 now := TimeNow() 132 for _, ts := range c.ts { 133 ts.reset(now) 134 } 135 }