github.com/aristanetworks/goarista@v0.0.0-20240514173732-cca2755bbd44/monitor/stats/tracker.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 "math" 27 "sync" 28 "time" 29 ) 30 31 // Tracker is a min/max value tracker that keeps track of its min/max values 32 // over a given period of time, and with a given resolution. The initial min 33 // and max values are math.MaxInt64 and math.MinInt64 respectively. 34 type Tracker struct { 35 mu sync.RWMutex 36 min, max int64 // All time min/max. 37 minTS, maxTS [3]*timeseries 38 lastUpdate time.Time 39 } 40 41 // newTracker returns a new Tracker. 42 func newTracker() *Tracker { 43 now := TimeNow() 44 t := &Tracker{} 45 t.minTS[hour] = newTimeSeries(now, time.Hour, time.Minute) 46 t.minTS[tenminutes] = newTimeSeries(now, 10*time.Minute, 10*time.Second) 47 t.minTS[minute] = newTimeSeries(now, time.Minute, time.Second) 48 t.maxTS[hour] = newTimeSeries(now, time.Hour, time.Minute) 49 t.maxTS[tenminutes] = newTimeSeries(now, 10*time.Minute, 10*time.Second) 50 t.maxTS[minute] = newTimeSeries(now, time.Minute, time.Second) 51 t.init() 52 return t 53 } 54 55 func (t *Tracker) init() { 56 t.min = math.MaxInt64 57 t.max = math.MinInt64 58 for _, ts := range t.minTS { 59 ts.set(math.MaxInt64) 60 } 61 for _, ts := range t.maxTS { 62 ts.set(math.MinInt64) 63 } 64 } 65 66 func (t *Tracker) advance() time.Time { 67 now := TimeNow() 68 for _, ts := range t.minTS { 69 ts.advanceTimeWithFill(now, math.MaxInt64) 70 } 71 for _, ts := range t.maxTS { 72 ts.advanceTimeWithFill(now, math.MinInt64) 73 } 74 return now 75 } 76 77 // LastUpdate returns the last update time of the range. 78 func (t *Tracker) LastUpdate() time.Time { 79 t.mu.RLock() 80 defer t.mu.RUnlock() 81 return t.lastUpdate 82 } 83 84 // Push adds a new value if it is a new minimum or maximum. 85 func (t *Tracker) Push(value int64) { 86 t.mu.Lock() 87 defer t.mu.Unlock() 88 t.lastUpdate = t.advance() 89 if t.min > value { 90 t.min = value 91 } 92 if t.max < value { 93 t.max = value 94 } 95 for _, ts := range t.minTS { 96 if ts.headValue() > value { 97 ts.set(value) 98 } 99 } 100 for _, ts := range t.maxTS { 101 if ts.headValue() < value { 102 ts.set(value) 103 } 104 } 105 } 106 107 // Min returns the minimum value of the tracker 108 func (t *Tracker) Min() int64 { 109 t.mu.RLock() 110 defer t.mu.RUnlock() 111 return t.min 112 } 113 114 // Max returns the maximum value of the tracker. 115 func (t *Tracker) Max() int64 { 116 t.mu.RLock() 117 defer t.mu.RUnlock() 118 return t.max 119 } 120 121 // Min1h returns the minimum value for the last hour. 122 func (t *Tracker) Min1h() int64 { 123 t.mu.Lock() 124 defer t.mu.Unlock() 125 t.advance() 126 return t.minTS[hour].min() 127 } 128 129 // Max1h returns the maximum value for the last hour. 130 func (t *Tracker) Max1h() int64 { 131 t.mu.Lock() 132 defer t.mu.Unlock() 133 t.advance() 134 return t.maxTS[hour].max() 135 } 136 137 // Min10m returns the minimum value for the last 10 minutes. 138 func (t *Tracker) Min10m() int64 { 139 t.mu.Lock() 140 defer t.mu.Unlock() 141 t.advance() 142 return t.minTS[tenminutes].min() 143 } 144 145 // Max10m returns the maximum value for the last 10 minutes. 146 func (t *Tracker) Max10m() int64 { 147 t.mu.Lock() 148 defer t.mu.Unlock() 149 t.advance() 150 return t.maxTS[tenminutes].max() 151 } 152 153 // Min1m returns the minimum value for the last 1 minute. 154 func (t *Tracker) Min1m() int64 { 155 t.mu.Lock() 156 defer t.mu.Unlock() 157 t.advance() 158 return t.minTS[minute].min() 159 } 160 161 // Max1m returns the maximum value for the last 1 minute. 162 func (t *Tracker) Max1m() int64 { 163 t.mu.Lock() 164 defer t.mu.Unlock() 165 t.advance() 166 return t.maxTS[minute].max() 167 } 168 169 // Reset resets the range to an empty state. 170 func (t *Tracker) Reset() { 171 t.mu.Lock() 172 defer t.mu.Unlock() 173 now := TimeNow() 174 for _, ts := range t.minTS { 175 ts.reset(now) 176 } 177 for _, ts := range t.maxTS { 178 ts.reset(now) 179 } 180 t.init() 181 }