Skip to content

Commit 6560bcd

Browse files
Michael Jennyprinzdezibel
authored andcommitted
This change enables setting min and max values for gauges. It prevents the gauge's value to become smaller/greater than the specified limits. The values are optional and don't change the gauge's behaviour if not given.
Example use case: A log stream increases or decreases a user session gauge if a corresponding login/logoff log entry is seen. Specifying a minimum value of 0 for the gauge helps to prevent the user session gauge to get negative if the very first message that triggers the gauge is a logoff message. This might happen if the user is already logged in and the prometheus service is restarted, which resets the gauge values to 0. Signed-off-by: Michael Jenny <[email protected]>
1 parent 54b80c0 commit 6560bcd

File tree

1 file changed

+43
-4
lines changed

1 file changed

+43
-4
lines changed

prometheus/gauge.go

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,37 @@ type Gauge interface {
5252
SetToCurrentTime()
5353
}
5454

55-
// GaugeOpts is an alias for Opts. See there for doc comments.
56-
type GaugeOpts Opts
55+
type GaugeOpts struct {
56+
// Namespace, Subsystem, and Name are components of the fully-qualified
57+
// name of the Metric (created by joining these components with
58+
// "_"). Only Name is mandatory, the others merely help structuring the
59+
// name. Note that the fully-qualified name of the metric must be a
60+
// valid Prometheus metric name.
61+
Namespace string
62+
Subsystem string
63+
Name string
64+
65+
// Help provides information about this metric.
66+
//
67+
// Metrics with the same fully-qualified name must have the same Help
68+
// string.
69+
Help string
70+
71+
// ConstLabels are used to attach fixed labels to this metric. Metrics
72+
// with the same fully-qualified name must have the same label names in
73+
// their ConstLabels.
74+
//
75+
// ConstLabels are only used rarely. In particular, do not use them to
76+
// attach the same labels to all your metrics. Those use cases are
77+
// better covered by target labels set by the scraping Prometheus
78+
// server, or by one specific metric (e.g. a build_info or a
79+
// machine_role metric). See also
80+
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels
81+
ConstLabels Labels
82+
83+
MinValue *float64
84+
MaxValue *float64
85+
}
5786

5887
// GaugeVecOpts bundles the options to create a GaugeVec metric.
5988
// It is mandatory to set GaugeOpts, see there for mandatory fields. VariableLabels
@@ -82,7 +111,7 @@ func NewGauge(opts GaugeOpts) Gauge {
82111
nil,
83112
opts.ConstLabels,
84113
)
85-
result := &gauge{desc: desc, labelPairs: desc.constLabelPairs}
114+
result := &gauge{desc: desc, labelPairs: desc.constLabelPairs, minValue: opts.MinValue, maxValue: opts.MaxValue}
86115
result.init(result) // Init self-collection.
87116
return result
88117
}
@@ -97,6 +126,8 @@ type gauge struct {
97126

98127
desc *Desc
99128
labelPairs []*dto.LabelPair
129+
minValue *float64
130+
maxValue *float64
100131
}
101132

102133
func (g *gauge) Desc() *Desc {
@@ -122,7 +153,15 @@ func (g *gauge) Dec() {
122153
func (g *gauge) Add(val float64) {
123154
for {
124155
oldBits := atomic.LoadUint64(&g.valBits)
125-
newBits := math.Float64bits(math.Float64frombits(oldBits) + val)
156+
oldVal := math.Float64frombits(oldBits)
157+
newVal := oldVal + val
158+
if g.minValue != nil && newVal < *g.minValue {
159+
newVal = *g.minValue
160+
} else if g.maxValue != nil && newVal > *g.maxValue {
161+
newVal = *g.maxValue
162+
}
163+
164+
newBits := math.Float64bits(newVal)
126165
if atomic.CompareAndSwapUint64(&g.valBits, oldBits, newBits) {
127166
return
128167
}

0 commit comments

Comments
 (0)