github.com/aristanetworks/goarista@v0.0.0-20240514173732-cca2755bbd44/monitor/stats/counter.go (about) 1 /* 2 * 3 * Copyright 2017 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 // Copyright (c) 2015 Arista Networks, Inc. 20 // Use of this source code is governed by the Apache License 2.0 21 // that can be found in the COPYING file. 22 23 package stats 24 25 import ( 26 "sync" 27 "time" 28 ) 29 30 var ( 31 // TimeNow is used for testing. 32 TimeNow = time.Now 33 ) 34 35 const ( 36 hour = 0 37 tenminutes = 1 38 minute = 2 39 ) 40 41 // Counter is a counter that keeps track of its recent values over a given 42 // period of time, and with a given resolution. Use newCounter() to instantiate. 43 type Counter struct { 44 mu sync.RWMutex 45 ts [3]*timeseries 46 lastUpdate time.Time 47 } 48 49 // newCounter returns a new Counter. 50 func newCounter() *Counter { 51 now := TimeNow() 52 c := &Counter{} 53 c.ts[hour] = newTimeSeries(now, time.Hour, time.Minute) 54 c.ts[tenminutes] = newTimeSeries(now, 10*time.Minute, 10*time.Second) 55 c.ts[minute] = newTimeSeries(now, time.Minute, time.Second) 56 return c 57 } 58 59 func (c *Counter) advance() time.Time { 60 now := TimeNow() 61 for _, ts := range c.ts { 62 ts.advanceTime(now) 63 } 64 return now 65 } 66 67 // Value returns the current value of the counter. 68 func (c *Counter) Value() int64 { 69 c.mu.RLock() 70 defer c.mu.RUnlock() 71 return c.ts[minute].headValue() 72 } 73 74 // LastUpdate returns the last update time of the counter. 75 func (c *Counter) LastUpdate() time.Time { 76 c.mu.RLock() 77 defer c.mu.RUnlock() 78 return c.lastUpdate 79 } 80 81 // Set updates the current value of the counter. 82 func (c *Counter) Set(value int64) { 83 c.mu.Lock() 84 defer c.mu.Unlock() 85 c.lastUpdate = c.advance() 86 for _, ts := range c.ts { 87 ts.set(value) 88 } 89 } 90 91 // Incr increments the current value of the counter by 'delta'. 92 func (c *Counter) Incr(delta int64) { 93 c.mu.Lock() 94 defer c.mu.Unlock() 95 c.lastUpdate = c.advance() 96 for _, ts := range c.ts { 97 ts.incr(delta) 98 } 99 } 100 101 // Delta1h returns the delta for the last hour. 102 func (c *Counter) Delta1h() int64 { 103 c.mu.RLock() 104 defer c.mu.RUnlock() 105 c.advance() 106 return c.ts[hour].delta() 107 } 108 109 // Delta10m returns the delta for the last 10 minutes. 110 func (c *Counter) Delta10m() int64 { 111 c.mu.RLock() 112 defer c.mu.RUnlock() 113 c.advance() 114 return c.ts[tenminutes].delta() 115 } 116 117 // Delta1m returns the delta for the last minute. 118 func (c *Counter) Delta1m() int64 { 119 c.mu.RLock() 120 defer c.mu.RUnlock() 121 c.advance() 122 return c.ts[minute].delta() 123 } 124 125 // Rate1h returns the rate of change of the counter in the last hour. 126 func (c *Counter) Rate1h() float64 { 127 c.mu.RLock() 128 defer c.mu.RUnlock() 129 c.advance() 130 return c.ts[hour].rate() 131 } 132 133 // Rate10m returns the rate of change of the counter in the last 10 minutes. 134 func (c *Counter) Rate10m() float64 { 135 c.mu.RLock() 136 defer c.mu.RUnlock() 137 c.advance() 138 return c.ts[tenminutes].rate() 139 } 140 141 // Rate1m returns the rate of change of the counter in the last minute. 142 func (c *Counter) Rate1m() float64 { 143 c.mu.RLock() 144 defer c.mu.RUnlock() 145 c.advance() 146 return c.ts[minute].rate() 147 } 148 149 // Reset resets the counter to an empty state. 150 func (c *Counter) Reset() { 151 c.mu.Lock() 152 defer c.mu.Unlock() 153 now := TimeNow() 154 for _, ts := range c.ts { 155 ts.reset(now) 156 } 157 }