From 242b076c48bf0b63012e88628f6919fb6d5deb95 Mon Sep 17 00:00:00 2001 From: bwplotka Date: Tue, 25 Mar 2025 10:17:22 +0000 Subject: [PATCH 1/2] Add tmp prometheus.AllowReservedLabels global. Signed-off-by: bwplotka --- prometheus/labels.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/prometheus/labels.go b/prometheus/labels.go index c21911f29..e8c8dadae 100644 --- a/prometheus/labels.go +++ b/prometheus/labels.go @@ -183,6 +183,14 @@ func validateLabelValues(vals []string, expectedNumberOfValues int) error { return nil } +// AllowReservedLabels relaxes the check for labels starting with __ +// TODO(bwplotka): Only for demo, if needed long term, it has to be part of desc option, +// not global. +var AllowReservedLabels bool + func checkLabelName(l string) bool { + if AllowReservedLabels { + return model.LabelName(l).IsValid() + } return model.LabelName(l).IsValid() && !strings.HasPrefix(l, reservedLabelPrefix) } From 483cccb37fdbfa9f96dbd18d3e6e2f6e3e0a1ee2 Mon Sep 17 00:00:00 2001 From: bwplotka Date: Wed, 26 Mar 2025 13:26:11 +0000 Subject: [PATCH 2/2] Yolo, add units. Signed-off-by: bwplotka --- prometheus/counter.go | 4 +++- prometheus/desc.go | 10 ++++++++-- prometheus/gauge.go | 4 +++- prometheus/histogram.go | 5 ++++- prometheus/metric.go | 1 + prometheus/registry.go | 4 ++++ prometheus/summary.go | 1 + prometheus/wrap.go | 2 +- 8 files changed, 25 insertions(+), 6 deletions(-) diff --git a/prometheus/counter.go b/prometheus/counter.go index 4ce84e7a8..adcc262d8 100644 --- a/prometheus/counter.go +++ b/prometheus/counter.go @@ -85,9 +85,10 @@ type CounterVecOpts struct { // Both internal tracking values are added up in the Write method. This has to // be taken into account when it comes to precision and overflow behavior. func NewCounter(opts CounterOpts) Counter { - desc := NewDesc( + desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, + opts.Unit, nil, opts.ConstLabels, ) @@ -203,6 +204,7 @@ func (v2) NewCounterVec(opts CounterVecOpts) *CounterVec { desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, + opts.Unit, opts.VariableLabels, opts.ConstLabels, ) diff --git a/prometheus/desc.go b/prometheus/desc.go index ad347113c..b798edc0f 100644 --- a/prometheus/desc.go +++ b/prometheus/desc.go @@ -47,6 +47,8 @@ type Desc struct { fqName string // help provides some helpful information about this metric. help string + // unit is a OpenMetrics unit. + unit string // constLabelPairs contains precalculated DTO label pairs based on // the constant labels. constLabelPairs []*dto.LabelPair @@ -76,7 +78,7 @@ type Desc struct { // For constLabels, the label values are constant. Therefore, they are fully // specified in the Desc. See the Collector example for a usage pattern. func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc { - return V2.NewDesc(fqName, help, UnconstrainedLabels(variableLabels), constLabels) + return V2.NewDesc(fqName, help, "", UnconstrainedLabels(variableLabels), constLabels) } // NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc @@ -89,10 +91,14 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) * // // For constLabels, the label values are constant. Therefore, they are fully // specified in the Desc. See the Collector example for a usage pattern. -func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, constLabels Labels) *Desc { +func (v2) NewDesc(fqName, help, unit string, variableLabels ConstrainableLabels, constLabels Labels) *Desc { + if variableLabels == nil { + variableLabels = UnconstrainedLabels(nil) + } d := &Desc{ fqName: fqName, help: help, + unit: unit, variableLabels: variableLabels.compile(), } if !model.IsValidMetricName(model.LabelValue(fqName)) { diff --git a/prometheus/gauge.go b/prometheus/gauge.go index dd2eac940..13a4b21d3 100644 --- a/prometheus/gauge.go +++ b/prometheus/gauge.go @@ -76,9 +76,10 @@ type GaugeVecOpts struct { // scenarios for Gauges and Counters, where the former tends to be Set-heavy and // the latter Inc-heavy. func NewGauge(opts GaugeOpts) Gauge { - desc := NewDesc( + desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, + opts.Unit, nil, opts.ConstLabels, ) @@ -161,6 +162,7 @@ func (v2) NewGaugeVec(opts GaugeVecOpts) *GaugeVec { desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, + opts.Unit, opts.VariableLabels, opts.ConstLabels, ) diff --git a/prometheus/histogram.go b/prometheus/histogram.go index c453b754a..a80e8c975 100644 --- a/prometheus/histogram.go +++ b/prometheus/histogram.go @@ -371,6 +371,7 @@ type HistogramOpts struct { Namespace string Subsystem string Name string + Unit string // Help provides information about this Histogram. // @@ -522,9 +523,10 @@ type HistogramVecOpts struct { // for each bucket. func NewHistogram(opts HistogramOpts) Histogram { return newHistogram( - NewDesc( + V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, + opts.Unit, nil, opts.ConstLabels, ), @@ -1188,6 +1190,7 @@ func (v2) NewHistogramVec(opts HistogramVecOpts) *HistogramVec { desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, + opts.Unit, opts.VariableLabels, opts.ConstLabels, ) diff --git a/prometheus/metric.go b/prometheus/metric.go index 592eec3e2..286d9f357 100644 --- a/prometheus/metric.go +++ b/prometheus/metric.go @@ -74,6 +74,7 @@ type Opts struct { Namespace string Subsystem string Name string + Unit string // Help provides information about this metric. // diff --git a/prometheus/registry.go b/prometheus/registry.go index c6fd2f58b..8054256fc 100644 --- a/prometheus/registry.go +++ b/prometheus/registry.go @@ -685,6 +685,10 @@ func processMetric( metricFamily = &dto.MetricFamily{} metricFamily.Name = proto.String(desc.fqName) metricFamily.Help = proto.String(desc.help) + if desc.unit != "" { + metricFamily.Unit = proto.String(desc.unit) + } + // TODO(beorn7): Simplify switch once Desc has type. switch { case dtoMetric.Gauge != nil: diff --git a/prometheus/summary.go b/prometheus/summary.go index ac5203c6f..6d61ac3e8 100644 --- a/prometheus/summary.go +++ b/prometheus/summary.go @@ -576,6 +576,7 @@ func (v2) NewSummaryVec(opts SummaryVecOpts) *SummaryVec { desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, + "", // TODO opts.VariableLabels, opts.ConstLabels, ) diff --git a/prometheus/wrap.go b/prometheus/wrap.go index 25da157f1..258f1cd1a 100644 --- a/prometheus/wrap.go +++ b/prometheus/wrap.go @@ -204,7 +204,7 @@ func wrapDesc(desc *Desc, prefix string, labels Labels) *Desc { constLabels[ln] = lv } // NewDesc will do remaining validations. - newDesc := V2.NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels) + newDesc := V2.NewDesc(prefix+desc.fqName, desc.help, desc.unit, desc.variableLabels, constLabels) // Propagate errors if there was any. This will override any errer // created by NewDesc above, i.e. earlier errors get precedence. if desc.err != nil {