Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / prometheus / client_golang / prometheus / gauge.go
1 // Copyright 2014 The Prometheus Authors
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package prometheus
15
16 import (
17         "math"
18         "sync/atomic"
19         "time"
20
21         dto "github.com/prometheus/client_model/go"
22 )
23
24 // Gauge is a Metric that represents a single numerical value that can
25 // arbitrarily go up and down.
26 //
27 // A Gauge is typically used for measured values like temperatures or current
28 // memory usage, but also "counts" that can go up and down, like the number of
29 // running goroutines.
30 //
31 // To create Gauge instances, use NewGauge.
32 type Gauge interface {
33         Metric
34         Collector
35
36         // Set sets the Gauge to an arbitrary value.
37         Set(float64)
38         // Inc increments the Gauge by 1. Use Add to increment it by arbitrary
39         // values.
40         Inc()
41         // Dec decrements the Gauge by 1. Use Sub to decrement it by arbitrary
42         // values.
43         Dec()
44         // Add adds the given value to the Gauge. (The value can be negative,
45         // resulting in a decrease of the Gauge.)
46         Add(float64)
47         // Sub subtracts the given value from the Gauge. (The value can be
48         // negative, resulting in an increase of the Gauge.)
49         Sub(float64)
50
51         // SetToCurrentTime sets the Gauge to the current Unix time in seconds.
52         SetToCurrentTime()
53 }
54
55 // GaugeOpts is an alias for Opts. See there for doc comments.
56 type GaugeOpts Opts
57
58 // NewGauge creates a new Gauge based on the provided GaugeOpts.
59 //
60 // The returned implementation is optimized for a fast Set method. If you have a
61 // choice for managing the value of a Gauge via Set vs. Inc/Dec/Add/Sub, pick
62 // the former. For example, the Inc method of the returned Gauge is slower than
63 // the Inc method of a Counter returned by NewCounter. This matches the typical
64 // scenarios for Gauges and Counters, where the former tends to be Set-heavy and
65 // the latter Inc-heavy.
66 func NewGauge(opts GaugeOpts) Gauge {
67         desc := NewDesc(
68                 BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
69                 opts.Help,
70                 nil,
71                 opts.ConstLabels,
72         )
73         result := &gauge{desc: desc, labelPairs: desc.constLabelPairs}
74         result.init(result) // Init self-collection.
75         return result
76 }
77
78 type gauge struct {
79         // valBits contains the bits of the represented float64 value. It has
80         // to go first in the struct to guarantee alignment for atomic
81         // operations.  http://golang.org/pkg/sync/atomic/#pkg-note-BUG
82         valBits uint64
83
84         selfCollector
85
86         desc       *Desc
87         labelPairs []*dto.LabelPair
88 }
89
90 func (g *gauge) Desc() *Desc {
91         return g.desc
92 }
93
94 func (g *gauge) Set(val float64) {
95         atomic.StoreUint64(&g.valBits, math.Float64bits(val))
96 }
97
98 func (g *gauge) SetToCurrentTime() {
99         g.Set(float64(time.Now().UnixNano()) / 1e9)
100 }
101
102 func (g *gauge) Inc() {
103         g.Add(1)
104 }
105
106 func (g *gauge) Dec() {
107         g.Add(-1)
108 }
109
110 func (g *gauge) Add(val float64) {
111         for {
112                 oldBits := atomic.LoadUint64(&g.valBits)
113                 newBits := math.Float64bits(math.Float64frombits(oldBits) + val)
114                 if atomic.CompareAndSwapUint64(&g.valBits, oldBits, newBits) {
115                         return
116                 }
117         }
118 }
119
120 func (g *gauge) Sub(val float64) {
121         g.Add(val * -1)
122 }
123
124 func (g *gauge) Write(out *dto.Metric) error {
125         val := math.Float64frombits(atomic.LoadUint64(&g.valBits))
126         return populateMetric(GaugeValue, val, g.labelPairs, out)
127 }
128
129 // GaugeVec is a Collector that bundles a set of Gauges that all share the same
130 // Desc, but have different values for their variable labels. This is used if
131 // you want to count the same thing partitioned by various dimensions
132 // (e.g. number of operations queued, partitioned by user and operation
133 // type). Create instances with NewGaugeVec.
134 type GaugeVec struct {
135         *metricVec
136 }
137
138 // NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and
139 // partitioned by the given label names.
140 func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
141         desc := NewDesc(
142                 BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
143                 opts.Help,
144                 labelNames,
145                 opts.ConstLabels,
146         )
147         return &GaugeVec{
148                 metricVec: newMetricVec(desc, func(lvs ...string) Metric {
149                         if len(lvs) != len(desc.variableLabels) {
150                                 panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
151                         }
152                         result := &gauge{desc: desc, labelPairs: makeLabelPairs(desc, lvs)}
153                         result.init(result) // Init self-collection.
154                         return result
155                 }),
156         }
157 }
158
159 // GetMetricWithLabelValues returns the Gauge for the given slice of label
160 // values (same order as the VariableLabels in Desc). If that combination of
161 // label values is accessed for the first time, a new Gauge is created.
162 //
163 // It is possible to call this method without using the returned Gauge to only
164 // create the new Gauge but leave it at its starting value 0. See also the
165 // SummaryVec example.
166 //
167 // Keeping the Gauge for later use is possible (and should be considered if
168 // performance is critical), but keep in mind that Reset, DeleteLabelValues and
169 // Delete can be used to delete the Gauge from the GaugeVec. In that case, the
170 // Gauge will still exist, but it will not be exported anymore, even if a
171 // Gauge with the same label values is created later. See also the CounterVec
172 // example.
173 //
174 // An error is returned if the number of label values is not the same as the
175 // number of VariableLabels in Desc (minus any curried labels).
176 //
177 // Note that for more than one label value, this method is prone to mistakes
178 // caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
179 // an alternative to avoid that type of mistake. For higher label numbers, the
180 // latter has a much more readable (albeit more verbose) syntax, but it comes
181 // with a performance overhead (for creating and processing the Labels map).
182 func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
183         metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
184         if metric != nil {
185                 return metric.(Gauge), err
186         }
187         return nil, err
188 }
189
190 // GetMetricWith returns the Gauge for the given Labels map (the label names
191 // must match those of the VariableLabels in Desc). If that label map is
192 // accessed for the first time, a new Gauge is created. Implications of
193 // creating a Gauge without using it and keeping the Gauge for later use are
194 // the same as for GetMetricWithLabelValues.
195 //
196 // An error is returned if the number and names of the Labels are inconsistent
197 // with those of the VariableLabels in Desc (minus any curried labels).
198 //
199 // This method is used for the same purpose as
200 // GetMetricWithLabelValues(...string). See there for pros and cons of the two
201 // methods.
202 func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
203         metric, err := v.metricVec.getMetricWith(labels)
204         if metric != nil {
205                 return metric.(Gauge), err
206         }
207         return nil, err
208 }
209
210 // WithLabelValues works as GetMetricWithLabelValues, but panics where
211 // GetMetricWithLabelValues would have returned an error. Not returning an
212 // error allows shortcuts like
213 //     myVec.WithLabelValues("404", "GET").Add(42)
214 func (v *GaugeVec) WithLabelValues(lvs ...string) Gauge {
215         g, err := v.GetMetricWithLabelValues(lvs...)
216         if err != nil {
217                 panic(err)
218         }
219         return g
220 }
221
222 // With works as GetMetricWith, but panics where GetMetricWithLabels would have
223 // returned an error. Not returning an error allows shortcuts like
224 //     myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42)
225 func (v *GaugeVec) With(labels Labels) Gauge {
226         g, err := v.GetMetricWith(labels)
227         if err != nil {
228                 panic(err)
229         }
230         return g
231 }
232
233 // CurryWith returns a vector curried with the provided labels, i.e. the
234 // returned vector has those labels pre-set for all labeled operations performed
235 // on it. The cardinality of the curried vector is reduced accordingly. The
236 // order of the remaining labels stays the same (just with the curried labels
237 // taken out of the sequence – which is relevant for the
238 // (GetMetric)WithLabelValues methods). It is possible to curry a curried
239 // vector, but only with labels not yet used for currying before.
240 //
241 // The metrics contained in the GaugeVec are shared between the curried and
242 // uncurried vectors. They are just accessed differently. Curried and uncurried
243 // vectors behave identically in terms of collection. Only one must be
244 // registered with a given registry (usually the uncurried version). The Reset
245 // method deletes all metrics, even if called on a curried vector.
246 func (v *GaugeVec) CurryWith(labels Labels) (*GaugeVec, error) {
247         vec, err := v.curryWith(labels)
248         if vec != nil {
249                 return &GaugeVec{vec}, err
250         }
251         return nil, err
252 }
253
254 // MustCurryWith works as CurryWith but panics where CurryWith would have
255 // returned an error.
256 func (v *GaugeVec) MustCurryWith(labels Labels) *GaugeVec {
257         vec, err := v.CurryWith(labels)
258         if err != nil {
259                 panic(err)
260         }
261         return vec
262 }
263
264 // GaugeFunc is a Gauge whose value is determined at collect time by calling a
265 // provided function.
266 //
267 // To create GaugeFunc instances, use NewGaugeFunc.
268 type GaugeFunc interface {
269         Metric
270         Collector
271 }
272
273 // NewGaugeFunc creates a new GaugeFunc based on the provided GaugeOpts. The
274 // value reported is determined by calling the given function from within the
275 // Write method. Take into account that metric collection may happen
276 // concurrently. If that results in concurrent calls to Write, like in the case
277 // where a GaugeFunc is directly registered with Prometheus, the provided
278 // function must be concurrency-safe.
279 func NewGaugeFunc(opts GaugeOpts, function func() float64) GaugeFunc {
280         return newValueFunc(NewDesc(
281                 BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
282                 opts.Help,
283                 nil,
284                 opts.ConstLabels,
285         ), GaugeValue, function)
286 }