blob: bd0733d6a7d6bc604ff74723e5d22c25419ddef8 [file] [log] [blame]
khenaidooab1f7bd2019-11-14 14:00:27 -05001// 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
14package prometheus
15
16import (
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.
32type 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.
56type 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.
66func 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
78type 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
90func (g *gauge) Desc() *Desc {
91 return g.desc
92}
93
94func (g *gauge) Set(val float64) {
95 atomic.StoreUint64(&g.valBits, math.Float64bits(val))
96}
97
98func (g *gauge) SetToCurrentTime() {
99 g.Set(float64(time.Now().UnixNano()) / 1e9)
100}
101
102func (g *gauge) Inc() {
103 g.Add(1)
104}
105
106func (g *gauge) Dec() {
107 g.Add(-1)
108}
109
110func (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
120func (g *gauge) Sub(val float64) {
121 g.Add(val * -1)
122}
123
124func (g *gauge) Write(out *dto.Metric) error {
125 val := math.Float64frombits(atomic.LoadUint64(&g.valBits))
khenaidood948f772021-08-11 17:49:24 -0400126 return populateMetric(GaugeValue, val, g.labelPairs, nil, out)
khenaidooab1f7bd2019-11-14 14:00:27 -0500127}
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.
134type GaugeVec struct {
khenaidood948f772021-08-11 17:49:24 -0400135 *MetricVec
khenaidooab1f7bd2019-11-14 14:00:27 -0500136}
137
138// NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and
139// partitioned by the given label names.
140func 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{
khenaidood948f772021-08-11 17:49:24 -0400148 MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
khenaidooab1f7bd2019-11-14 14:00:27 -0500149 if len(lvs) != len(desc.variableLabels) {
150 panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
151 }
khenaidood948f772021-08-11 17:49:24 -0400152 result := &gauge{desc: desc, labelPairs: MakeLabelPairs(desc, lvs)}
khenaidooab1f7bd2019-11-14 14:00:27 -0500153 result.init(result) // Init self-collection.
154 return result
155 }),
156 }
157}
158
159// GetMetricWithLabelValues returns the Gauge for the given slice of label
khenaidood948f772021-08-11 17:49:24 -0400160// values (same order as the variable labels in Desc). If that combination of
khenaidooab1f7bd2019-11-14 14:00:27 -0500161// 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
khenaidood948f772021-08-11 17:49:24 -0400175// number of variable labels in Desc (minus any curried labels).
khenaidooab1f7bd2019-11-14 14:00:27 -0500176//
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).
182func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
khenaidood948f772021-08-11 17:49:24 -0400183 metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
khenaidooab1f7bd2019-11-14 14:00:27 -0500184 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
khenaidood948f772021-08-11 17:49:24 -0400191// must match those of the variable labels in Desc). If that label map is
khenaidooab1f7bd2019-11-14 14:00:27 -0500192// 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
khenaidood948f772021-08-11 17:49:24 -0400197// with those of the variable labels in Desc (minus any curried labels).
khenaidooab1f7bd2019-11-14 14:00:27 -0500198//
199// This method is used for the same purpose as
200// GetMetricWithLabelValues(...string). See there for pros and cons of the two
201// methods.
202func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
khenaidood948f772021-08-11 17:49:24 -0400203 metric, err := v.MetricVec.GetMetricWith(labels)
khenaidooab1f7bd2019-11-14 14:00:27 -0500204 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)
214func (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)
225func (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.
246func (v *GaugeVec) CurryWith(labels Labels) (*GaugeVec, error) {
khenaidood948f772021-08-11 17:49:24 -0400247 vec, err := v.MetricVec.CurryWith(labels)
khenaidooab1f7bd2019-11-14 14:00:27 -0500248 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.
256func (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.
268type 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
khenaidood948f772021-08-11 17:49:24 -0400276// concurrently. Therefore, it must be safe to call the provided function
277// concurrently.
278//
279// NewGaugeFunc is a good way to create an “info” style metric with a constant
280// value of 1. Example:
281// https://github.com/prometheus/common/blob/8558a5b7db3c84fa38b4766966059a7bd5bfa2ee/version/info.go#L36-L56
khenaidooab1f7bd2019-11-14 14:00:27 -0500282func NewGaugeFunc(opts GaugeOpts, function func() float64) GaugeFunc {
283 return newValueFunc(NewDesc(
284 BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
285 opts.Help,
286 nil,
287 opts.ConstLabels,
288 ), GaugeValue, function)
289}