diff --git a/prometheus/gauge.go b/prometheus/gauge.go index dd2eac940..fc4b9dba0 100644 --- a/prometheus/gauge.go +++ b/prometheus/gauge.go @@ -52,8 +52,37 @@ type Gauge interface { SetToCurrentTime() } -// GaugeOpts is an alias for Opts. See there for doc comments. -type GaugeOpts Opts +type GaugeOpts struct { + // Namespace, Subsystem, and Name are components of the fully-qualified + // name of the Metric (created by joining these components with + // "_"). Only Name is mandatory, the others merely help structuring the + // name. Note that the fully-qualified name of the metric must be a + // valid Prometheus metric name. + Namespace string + Subsystem string + Name string + + // Help provides information about this metric. + // + // Metrics with the same fully-qualified name must have the same Help + // string. + Help string + + // ConstLabels are used to attach fixed labels to this metric. Metrics + // with the same fully-qualified name must have the same label names in + // their ConstLabels. + // + // ConstLabels are only used rarely. In particular, do not use them to + // attach the same labels to all your metrics. Those use cases are + // better covered by target labels set by the scraping Prometheus + // server, or by one specific metric (e.g. a build_info or a + // machine_role metric). See also + // https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels + ConstLabels Labels + + MinValue *float64 + MaxValue *float64 +} // GaugeVecOpts bundles the options to create a GaugeVec metric. // It is mandatory to set GaugeOpts, see there for mandatory fields. VariableLabels @@ -82,7 +111,7 @@ func NewGauge(opts GaugeOpts) Gauge { nil, opts.ConstLabels, ) - result := &gauge{desc: desc, labelPairs: desc.constLabelPairs} + result := &gauge{desc: desc, labelPairs: desc.constLabelPairs, minValue: opts.MinValue, maxValue: opts.MaxValue} result.init(result) // Init self-collection. return result } @@ -97,6 +126,8 @@ type gauge struct { desc *Desc labelPairs []*dto.LabelPair + minValue *float64 + maxValue *float64 } func (g *gauge) Desc() *Desc { @@ -122,7 +153,15 @@ func (g *gauge) Dec() { func (g *gauge) Add(val float64) { for { oldBits := atomic.LoadUint64(&g.valBits) - newBits := math.Float64bits(math.Float64frombits(oldBits) + val) + oldVal := math.Float64frombits(oldBits) + newVal := oldVal + val + if g.minValue != nil && newVal < *g.minValue { + newVal = *g.minValue + } else if g.maxValue != nil && newVal > *g.maxValue { + newVal = *g.maxValue + } + + newBits := math.Float64bits(newVal) if atomic.CompareAndSwapUint64(&g.valBits, oldBits, newBits) { return }