vitess.io/vitess@v0.16.2/go/stats/counter.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package stats 18 19 import ( 20 "strconv" 21 "time" 22 23 "vitess.io/vitess/go/sync2" 24 "vitess.io/vitess/go/vt/logutil" 25 ) 26 27 // logCounterNegative is for throttling adding a negative value to a counter messages in logs 28 var logCounterNegative = logutil.NewThrottledLogger("StatsCounterNegative", 1*time.Minute) 29 30 // Counter tracks a cumulative count of a metric. 31 // For a one-dimensional or multi-dimensional counter, please use 32 // CountersWithSingleLabel or CountersWithMultiLabels instead. 33 type Counter struct { 34 i sync2.AtomicInt64 35 help string 36 } 37 38 // NewCounter returns a new Counter. 39 func NewCounter(name string, help string) *Counter { 40 v := &Counter{help: help} 41 if name != "" { 42 publish(name, v) 43 } 44 return v 45 } 46 47 // Add adds the provided value to the Counter. 48 func (v *Counter) Add(delta int64) { 49 if delta < 0 { 50 logCounterNegative.Warningf("Adding a negative value to a counter, %v should be a gauge instead", v) 51 } 52 v.i.Add(delta) 53 } 54 55 // Set overwrites the current value. 56 // This should be used with caution for Counter values 57 // only when we are certain that the underlying value we are setting 58 // is increment only 59 func (v *Counter) Set(value int64) { 60 v.i.Set(value) 61 } 62 63 // Reset resets the counter value to 0. 64 func (v *Counter) Reset() { 65 v.i.Set(int64(0)) 66 } 67 68 // Get returns the value. 69 func (v *Counter) Get() int64 { 70 return v.i.Get() 71 } 72 73 // String implements the expvar.Var interface. 74 func (v *Counter) String() string { 75 return strconv.FormatInt(v.i.Get(), 10) 76 } 77 78 // Help returns the help string. 79 func (v *Counter) Help() string { 80 return v.help 81 } 82 83 // CounterFunc allows to provide the counter value via a custom function. 84 // For implementations that differentiate between Counters/Gauges, 85 // CounterFunc's values only go up (or are reset to 0). 86 type CounterFunc struct { 87 F func() int64 88 help string 89 } 90 91 // NewCounterFunc creates a new CounterFunc instance and publishes it if name is 92 // set. 93 func NewCounterFunc(name string, help string, f func() int64) *CounterFunc { 94 c := &CounterFunc{ 95 F: f, 96 help: help, 97 } 98 99 if name != "" { 100 publish(name, c) 101 } 102 return c 103 } 104 105 // Help returns the help string. 106 func (cf CounterFunc) Help() string { 107 return cf.help 108 } 109 110 // Get returns the value. 111 func (cf CounterFunc) Get() int64 { 112 return cf.F() 113 } 114 115 // String implements expvar.Var. 116 func (cf CounterFunc) String() string { 117 return strconv.FormatInt(cf.F(), 10) 118 } 119 120 // Gauge tracks the current value of an integer metric. 121 // The emphasis here is on *current* i.e. this is not a cumulative counter. 122 // For a one-dimensional or multi-dimensional gauge, please use 123 // GaugeWithSingleLabel or GaugesWithMultiLabels instead. 124 type Gauge struct { 125 Counter 126 } 127 128 // NewGauge creates a new Gauge and publishes it if name is set. 129 func NewGauge(name string, help string) *Gauge { 130 v := &Gauge{Counter: Counter{help: help}} 131 132 if name != "" { 133 publish(name, v) 134 } 135 return v 136 } 137 138 // Set overwrites the current value. 139 func (v *Gauge) Set(value int64) { 140 v.Counter.i.Set(value) 141 } 142 143 // Add adds the provided value to the Gauge. 144 func (v *Gauge) Add(delta int64) { 145 v.Counter.i.Add(delta) 146 } 147 148 // GaugeFunc is the same as CounterFunc but meant for gauges. 149 // It's a wrapper around CounterFunc for values that go up/down for 150 // implementations (like Prometheus) that need to differ between Counters and 151 // Gauges. 152 type GaugeFunc struct { 153 CounterFunc 154 } 155 156 // NewGaugeFunc creates a new GaugeFunc instance and publishes it if name is 157 // set. 158 func NewGaugeFunc(name string, help string, f func() int64) *GaugeFunc { 159 i := &GaugeFunc{ 160 CounterFunc: CounterFunc{ 161 F: f, 162 help: help, 163 }} 164 165 if name != "" { 166 publish(name, i) 167 } 168 return i 169 } 170 171 // GaugeFloat64 tracks a cumulative count of a metric. 172 // For a one-dimensional or multi-dimensional counter, please use 173 // CountersWithSingleLabel or CountersWithMultiLabels instead. 174 type GaugeFloat64 struct { 175 i sync2.AtomicFloat64 176 help string 177 } 178 179 // NewCounter returns a new GaugeFloat64. 180 func NewGaugeFloat64(name string, help string) *GaugeFloat64 { 181 v := &GaugeFloat64{help: help} 182 if name != "" { 183 publish(name, v) 184 } 185 return v 186 } 187 188 // Set overwrites the current value. 189 // This should be used with caution for GaugeFloat64 values 190 // only when we are certain that the underlying value we are setting 191 // is increment only 192 func (v *GaugeFloat64) Set(value float64) { 193 v.i.Set(value) 194 } 195 196 // Reset resets the counter value to 0. 197 func (v *GaugeFloat64) Reset() { 198 v.i.Set(float64(0)) 199 } 200 201 // Get returns the value. 202 func (v *GaugeFloat64) Get() float64 { 203 return v.i.Get() 204 } 205 206 // String implements the expvar.Var interface. 207 func (v *GaugeFloat64) String() string { 208 return strconv.FormatFloat(v.i.Get(), 'f', -1, 64) 209 } 210 211 // Help returns the help string. 212 func (v *GaugeFloat64) Help() string { 213 return v.help 214 }