Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / prometheus / client_golang / prometheus / counter.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         "errors"
18         "math"
19         "sync/atomic"
20
21         dto "github.com/prometheus/client_model/go"
22 )
23
24 // Counter is a Metric that represents a single numerical value that only ever
25 // goes up. That implies that it cannot be used to count items whose number can
26 // also go down, e.g. the number of currently running goroutines. Those
27 // "counters" are represented by Gauges.
28 //
29 // A Counter is typically used to count requests served, tasks completed, errors
30 // occurred, etc.
31 //
32 // To create Counter instances, use NewCounter.
33 type Counter interface {
34         Metric
35         Collector
36
37         // Inc increments the counter by 1. Use Add to increment it by arbitrary
38         // non-negative values.
39         Inc()
40         // Add adds the given value to the counter. It panics if the value is <
41         // 0.
42         Add(float64)
43 }
44
45 // CounterOpts is an alias for Opts. See there for doc comments.
46 type CounterOpts Opts
47
48 // NewCounter creates a new Counter based on the provided CounterOpts.
49 //
50 // The returned implementation tracks the counter value in two separate
51 // variables, a float64 and a uint64. The latter is used to track calls of the
52 // Inc method and calls of the Add method with a value that can be represented
53 // as a uint64. This allows atomic increments of the counter with optimal
54 // performance. (It is common to have an Inc call in very hot execution paths.)
55 // Both internal tracking values are added up in the Write method. This has to
56 // be taken into account when it comes to precision and overflow behavior.
57 func NewCounter(opts CounterOpts) Counter {
58         desc := NewDesc(
59                 BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
60                 opts.Help,
61                 nil,
62                 opts.ConstLabels,
63         )
64         result := &counter{desc: desc, labelPairs: desc.constLabelPairs}
65         result.init(result) // Init self-collection.
66         return result
67 }
68
69 type counter struct {
70         // valBits contains the bits of the represented float64 value, while
71         // valInt stores values that are exact integers. Both have to go first
72         // in the struct to guarantee alignment for atomic operations.
73         // http://golang.org/pkg/sync/atomic/#pkg-note-BUG
74         valBits uint64
75         valInt  uint64
76
77         selfCollector
78         desc *Desc
79
80         labelPairs []*dto.LabelPair
81 }
82
83 func (c *counter) Desc() *Desc {
84         return c.desc
85 }
86
87 func (c *counter) Add(v float64) {
88         if v < 0 {
89                 panic(errors.New("counter cannot decrease in value"))
90         }
91         ival := uint64(v)
92         if float64(ival) == v {
93                 atomic.AddUint64(&c.valInt, ival)
94                 return
95         }
96
97         for {
98                 oldBits := atomic.LoadUint64(&c.valBits)
99                 newBits := math.Float64bits(math.Float64frombits(oldBits) + v)
100                 if atomic.CompareAndSwapUint64(&c.valBits, oldBits, newBits) {
101                         return
102                 }
103         }
104 }
105
106 func (c *counter) Inc() {
107         atomic.AddUint64(&c.valInt, 1)
108 }
109
110 func (c *counter) Write(out *dto.Metric) error {
111         fval := math.Float64frombits(atomic.LoadUint64(&c.valBits))
112         ival := atomic.LoadUint64(&c.valInt)
113         val := fval + float64(ival)
114
115         return populateMetric(CounterValue, val, c.labelPairs, out)
116 }
117
118 // CounterVec is a Collector that bundles a set of Counters that all share the
119 // same Desc, but have different values for their variable labels. This is used
120 // if you want to count the same thing partitioned by various dimensions
121 // (e.g. number of HTTP requests, partitioned by response code and
122 // method). Create instances with NewCounterVec.
123 type CounterVec struct {
124         *metricVec
125 }
126
127 // NewCounterVec creates a new CounterVec based on the provided CounterOpts and
128 // partitioned by the given label names.
129 func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
130         desc := NewDesc(
131                 BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
132                 opts.Help,
133                 labelNames,
134                 opts.ConstLabels,
135         )
136         return &CounterVec{
137                 metricVec: newMetricVec(desc, func(lvs ...string) Metric {
138                         if len(lvs) != len(desc.variableLabels) {
139                                 panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
140                         }
141                         result := &counter{desc: desc, labelPairs: makeLabelPairs(desc, lvs)}
142                         result.init(result) // Init self-collection.
143                         return result
144                 }),
145         }
146 }
147
148 // GetMetricWithLabelValues returns the Counter for the given slice of label
149 // values (same order as the VariableLabels in Desc). If that combination of
150 // label values is accessed for the first time, a new Counter is created.
151 //
152 // It is possible to call this method without using the returned Counter to only
153 // create the new Counter but leave it at its starting value 0. See also the
154 // SummaryVec example.
155 //
156 // Keeping the Counter for later use is possible (and should be considered if
157 // performance is critical), but keep in mind that Reset, DeleteLabelValues and
158 // Delete can be used to delete the Counter from the CounterVec. In that case,
159 // the Counter will still exist, but it will not be exported anymore, even if a
160 // Counter with the same label values is created later.
161 //
162 // An error is returned if the number of label values is not the same as the
163 // number of VariableLabels in Desc (minus any curried labels).
164 //
165 // Note that for more than one label value, this method is prone to mistakes
166 // caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
167 // an alternative to avoid that type of mistake. For higher label numbers, the
168 // latter has a much more readable (albeit more verbose) syntax, but it comes
169 // with a performance overhead (for creating and processing the Labels map).
170 // See also the GaugeVec example.
171 func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
172         metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
173         if metric != nil {
174                 return metric.(Counter), err
175         }
176         return nil, err
177 }
178
179 // GetMetricWith returns the Counter for the given Labels map (the label names
180 // must match those of the VariableLabels in Desc). If that label map is
181 // accessed for the first time, a new Counter is created. Implications of
182 // creating a Counter without using it and keeping the Counter for later use are
183 // the same as for GetMetricWithLabelValues.
184 //
185 // An error is returned if the number and names of the Labels are inconsistent
186 // with those of the VariableLabels in Desc (minus any curried labels).
187 //
188 // This method is used for the same purpose as
189 // GetMetricWithLabelValues(...string). See there for pros and cons of the two
190 // methods.
191 func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) {
192         metric, err := v.metricVec.getMetricWith(labels)
193         if metric != nil {
194                 return metric.(Counter), err
195         }
196         return nil, err
197 }
198
199 // WithLabelValues works as GetMetricWithLabelValues, but panics where
200 // GetMetricWithLabelValues would have returned an error. Not returning an
201 // error allows shortcuts like
202 //     myVec.WithLabelValues("404", "GET").Add(42)
203 func (v *CounterVec) WithLabelValues(lvs ...string) Counter {
204         c, err := v.GetMetricWithLabelValues(lvs...)
205         if err != nil {
206                 panic(err)
207         }
208         return c
209 }
210
211 // With works as GetMetricWith, but panics where GetMetricWithLabels would have
212 // returned an error. Not returning an error allows shortcuts like
213 //     myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42)
214 func (v *CounterVec) With(labels Labels) Counter {
215         c, err := v.GetMetricWith(labels)
216         if err != nil {
217                 panic(err)
218         }
219         return c
220 }
221
222 // CurryWith returns a vector curried with the provided labels, i.e. the
223 // returned vector has those labels pre-set for all labeled operations performed
224 // on it. The cardinality of the curried vector is reduced accordingly. The
225 // order of the remaining labels stays the same (just with the curried labels
226 // taken out of the sequence – which is relevant for the
227 // (GetMetric)WithLabelValues methods). It is possible to curry a curried
228 // vector, but only with labels not yet used for currying before.
229 //
230 // The metrics contained in the CounterVec are shared between the curried and
231 // uncurried vectors. They are just accessed differently. Curried and uncurried
232 // vectors behave identically in terms of collection. Only one must be
233 // registered with a given registry (usually the uncurried version). The Reset
234 // method deletes all metrics, even if called on a curried vector.
235 func (v *CounterVec) CurryWith(labels Labels) (*CounterVec, error) {
236         vec, err := v.curryWith(labels)
237         if vec != nil {
238                 return &CounterVec{vec}, err
239         }
240         return nil, err
241 }
242
243 // MustCurryWith works as CurryWith but panics where CurryWith would have
244 // returned an error.
245 func (v *CounterVec) MustCurryWith(labels Labels) *CounterVec {
246         vec, err := v.CurryWith(labels)
247         if err != nil {
248                 panic(err)
249         }
250         return vec
251 }
252
253 // CounterFunc is a Counter whose value is determined at collect time by calling a
254 // provided function.
255 //
256 // To create CounterFunc instances, use NewCounterFunc.
257 type CounterFunc interface {
258         Metric
259         Collector
260 }
261
262 // NewCounterFunc creates a new CounterFunc based on the provided
263 // CounterOpts. The value reported is determined by calling the given function
264 // from within the Write method. Take into account that metric collection may
265 // happen concurrently. If that results in concurrent calls to Write, like in
266 // the case where a CounterFunc is directly registered with Prometheus, the
267 // provided function must be concurrency-safe. The function should also honor
268 // the contract for a Counter (values only go up, not down), but compliance will
269 // not be checked.
270 func NewCounterFunc(opts CounterOpts, function func() float64) CounterFunc {
271         return newValueFunc(NewDesc(
272                 BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
273                 opts.Help,
274                 nil,
275                 opts.ConstLabels,
276         ), CounterValue, function)
277 }