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
6 // http://www.apache.org/licenses/LICENSE-2.0
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.
21 dto "github.com/prometheus/client_model/go"
24 // Gauge is a Metric that represents a single numerical value that can
25 // arbitrarily go up and down.
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.
31 // To create Gauge instances, use NewGauge.
32 type Gauge interface {
36 // Set sets the Gauge to an arbitrary value.
38 // Inc increments the Gauge by 1. Use Add to increment it by arbitrary
41 // Dec decrements the Gauge by 1. Use Sub to decrement it by arbitrary
44 // Add adds the given value to the Gauge. (The value can be negative,
45 // resulting in a decrease of the Gauge.)
47 // Sub subtracts the given value from the Gauge. (The value can be
48 // negative, resulting in an increase of the Gauge.)
51 // SetToCurrentTime sets the Gauge to the current Unix time in seconds.
55 // GaugeOpts is an alias for Opts. See there for doc comments.
58 // NewGauge creates a new Gauge based on the provided GaugeOpts.
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 {
68 BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
73 result := &gauge{desc: desc, labelPairs: desc.constLabelPairs}
74 result.init(result) // Init self-collection.
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
87 labelPairs []*dto.LabelPair
90 func (g *gauge) Desc() *Desc {
94 func (g *gauge) Set(val float64) {
95 atomic.StoreUint64(&g.valBits, math.Float64bits(val))
98 func (g *gauge) SetToCurrentTime() {
99 g.Set(float64(time.Now().UnixNano()) / 1e9)
102 func (g *gauge) Inc() {
106 func (g *gauge) Dec() {
110 func (g *gauge) Add(val float64) {
112 oldBits := atomic.LoadUint64(&g.valBits)
113 newBits := math.Float64bits(math.Float64frombits(oldBits) + val)
114 if atomic.CompareAndSwapUint64(&g.valBits, oldBits, newBits) {
120 func (g *gauge) Sub(val float64) {
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)
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 {
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 {
142 BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
148 metricVec: newMetricVec(desc, func(lvs ...string) Metric {
149 if len(lvs) != len(desc.variableLabels) {
150 panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
152 result := &gauge{desc: desc, labelPairs: makeLabelPairs(desc, lvs)}
153 result.init(result) // Init self-collection.
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.
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.
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
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).
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...)
185 return metric.(Gauge), err
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.
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).
199 // This method is used for the same purpose as
200 // GetMetricWithLabelValues(...string). See there for pros and cons of the two
202 func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
203 metric, err := v.metricVec.getMetricWith(labels)
205 return metric.(Gauge), err
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...)
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)
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.
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)
249 return &GaugeVec{vec}, err
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)
264 // GaugeFunc is a Gauge whose value is determined at collect time by calling a
265 // provided function.
267 // To create GaugeFunc instances, use NewGaugeFunc.
268 type GaugeFunc interface {
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),
285 ), GaugeValue, function)