diff --git a/pkg/metrics/counter.go b/pkg/metrics/counter.go index 2e7095765d5..12ad40186e4 100644 --- a/pkg/metrics/counter.go +++ b/pkg/metrics/counter.go @@ -7,6 +7,8 @@ import ( "github.com/prometheus/client_golang/prometheus" ) +type initCounterFunc func(*prometheus.CounterVec) + // NewCounterVecWithPod is a wrapper around prometheus.NewCounterVec that also // registers the metric to be cleaned up when a pod is deleted. // @@ -37,7 +39,7 @@ func NewCounterVecWithPodV2(opts prometheus.CounterVecOpts) *prometheus.CounterV type GranularCounter[L FilteredLabels] struct { metric *prometheus.CounterVec constrained bool - initFunc func() + initFunc initCounterFunc initForDocs func() } @@ -56,8 +58,9 @@ type GranularCounter[L FilteredLabels] struct { // same thing in different formats, or two labels are mutually exclusive). // - metric is unconstrained, but some of the unconstrained label values are // known beforehand, so can be initialized. -// - you want to disable default initialization - pass func() {} in such case -func NewGranularCounter[L FilteredLabels](opts Opts, init func()) (*GranularCounter[L], error) { +// - you want to disable default initialization - pass +// func(*prometheus.CounterVec) {} in such case +func NewGranularCounter[L FilteredLabels](opts Opts, init initCounterFunc) (*GranularCounter[L], error) { labels, constrained, err := getVariableLabels[L](&opts) if err != nil { return nil, err @@ -85,9 +88,12 @@ func NewGranularCounter[L FilteredLabels](opts Opts, init func()) (*GranularCoun metric.WithLabelValues(lvs...).Add(0) } - // if metric is constrained, default to initializing all combinations of labels + // If metric is constrained, default to initializing all combinations of + // labels. Note that in such case the initialization function doesn't + // reference the wrapped metric passed as an argument because this metric + // is captured already in initMetric closure. if constrained && init == nil { - init = func() { + init = func(_ *prometheus.CounterVec) { initAllCombinations(initMetric, opts.ConstrainedLabels) } } @@ -125,7 +131,7 @@ func MustNewGranularCounter[L FilteredLabels](promOpts prometheus.CounterOpts, e // MustNewGranularCounterWithInit is a convenience function that wraps // NewGranularCounter and panics on error. -func MustNewGranularCounterWithInit[L FilteredLabels](opts Opts, init func()) *GranularCounter[L] { +func MustNewGranularCounterWithInit[L FilteredLabels](opts Opts, init initCounterFunc) *GranularCounter[L] { metric, err := NewGranularCounter[L](opts, init) if err != nil { panic(err) @@ -151,7 +157,7 @@ func (m *GranularCounter[L]) IsConstrained() bool { // Init implements CollectorWithInit. func (m *GranularCounter[L]) Init() { if m.initFunc != nil { - m.initFunc() + m.initFunc(m.metric) } } @@ -188,7 +194,7 @@ type Counter struct { // NewCounter creates a new Counter. // // See NewGranularCounter for usage notes. -func NewCounter(opts Opts, init func()) (*Counter, error) { +func NewCounter(opts Opts, init initCounterFunc) (*Counter, error) { metric, err := NewGranularCounter[NilLabels](opts, init) if err != nil { return nil, err @@ -198,7 +204,7 @@ func NewCounter(opts Opts, init func()) (*Counter, error) { // MustNewCounter is a convenience function that wraps NewCounter and panics on // error. -func MustNewCounter(opts Opts, init func()) *Counter { +func MustNewCounter(opts Opts, init initCounterFunc) *Counter { metric, err := NewCounter(opts, init) if err != nil { panic(err) diff --git a/pkg/metrics/gauge.go b/pkg/metrics/gauge.go index ce048063112..69dff54e9f2 100644 --- a/pkg/metrics/gauge.go +++ b/pkg/metrics/gauge.go @@ -7,6 +7,8 @@ import ( "github.com/prometheus/client_golang/prometheus" ) +type initGaugeFunc func(*prometheus.GaugeVec) + // NewGaugeVecWithPod is a wrapper around prometheus.NewGaugeVec that also // registers the metric to be cleaned up when a pod is deleted. // @@ -35,14 +37,14 @@ func NewGaugeVecWithPodV2(opts prometheus.GaugeVecOpts) *prometheus.GaugeVec { type GranularGauge[L FilteredLabels] struct { metric *prometheus.GaugeVec constrained bool - initFunc func() + initFunc initGaugeFunc initForDocs func() } // NewGranularGauge creates a new GranularGauge. // // See NewGranularCounter for usage notes. -func NewGranularGauge[L FilteredLabels](opts Opts, init func()) (*GranularGauge[L], error) { +func NewGranularGauge[L FilteredLabels](opts Opts, init initGaugeFunc) (*GranularGauge[L], error) { labels, constrained, err := getVariableLabels[L](&opts) if err != nil { return nil, err @@ -70,9 +72,12 @@ func NewGranularGauge[L FilteredLabels](opts Opts, init func()) (*GranularGauge[ metric.WithLabelValues(lvs...).Set(0) } - // if metric is constrained, default to initializing all combinations of labels + // If metric is constrained, default to initializing all combinations of + // labels. Note that in such case the initialization function doesn't + // reference the wrapped metric passed as an argument because this metric + // is captured already in initMetric closure. if constrained && init == nil { - init = func() { + init = func(_ *prometheus.GaugeVec) { initAllCombinations(initMetric, opts.ConstrainedLabels) } } @@ -108,7 +113,7 @@ func MustNewGranularGauge[L FilteredLabels](promOpts prometheus.GaugeOpts, extra // MustNewGranularGaugeWithInit is a convenience function that wraps // NewGranularGauge and panics on error. -func MustNewGranularGaugeWithInit[L FilteredLabels](opts Opts, init func()) *GranularGauge[L] { +func MustNewGranularGaugeWithInit[L FilteredLabels](opts Opts, init initGaugeFunc) *GranularGauge[L] { metric, err := NewGranularGauge[L](opts, init) if err != nil { panic(err) @@ -134,7 +139,7 @@ func (m *GranularGauge[L]) IsConstrained() bool { // Init implements CollectorWithInit. func (m *GranularGauge[L]) Init() { if m.initFunc != nil { - m.initFunc() + m.initFunc(m.metric) } } @@ -171,7 +176,7 @@ type Gauge struct { // NewGauge creates a new Gauge. // // See NewGranularCounter for usage notes. -func NewGauge(opts Opts, init func()) (*Gauge, error) { +func NewGauge(opts Opts, init initGaugeFunc) (*Gauge, error) { metric, err := NewGranularGauge[NilLabels](opts, init) if err != nil { return nil, err @@ -181,7 +186,7 @@ func NewGauge(opts Opts, init func()) (*Gauge, error) { // MustNewGauge is a convenience function that wraps NewGauge and panics on // error. -func MustNewGauge(opts Opts, init func()) *Gauge { +func MustNewGauge(opts Opts, init initGaugeFunc) *Gauge { metric, err := NewGauge(opts, init) if err != nil { panic(err) diff --git a/pkg/metrics/granularmetric.go b/pkg/metrics/granularmetric.go index e0798270ea5..2d6eb9b39b5 100644 --- a/pkg/metrics/granularmetric.go +++ b/pkg/metrics/granularmetric.go @@ -3,11 +3,11 @@ package metrics -type initMetricFunc func(...string) +type initLabelValuesFunc func(...string) // initAllCombinations initializes a metric with all possible combinations of // label values. -func initAllCombinations(initMetric initMetricFunc, labels []ConstrainedLabel) { +func initAllCombinations(initMetric initLabelValuesFunc, labels []ConstrainedLabel) { initCombinations(initMetric, labels, make([]string, len(labels)), 0) } @@ -20,7 +20,7 @@ func initAllCombinations(initMetric initMetricFunc, labels []ConstrainedLabel) { // - cursor is in the range [0, len(labels)] // // If any of these is not met, the function will do nothing. -func initCombinations(initMetric initMetricFunc, labels []ConstrainedLabel, lvs []string, cursor int) { +func initCombinations(initMetric initLabelValuesFunc, labels []ConstrainedLabel, lvs []string, cursor int) { if initMetric == nil || len(labels) != len(lvs) || cursor < 0 || cursor > len(labels) { // The function was called with invalid arguments. Silently return. return @@ -43,7 +43,7 @@ func initCombinations(initMetric initMetricFunc, labels []ConstrainedLabel, lvs // metrics server - but here we care only about extracting labels for // documentation, so we don't try to make the metrics realistic. func initForDocs[L FilteredLabels]( - initMetric initMetricFunc, constrained []ConstrainedLabel, unconstrained []UnconstrainedLabel, + initMetric initLabelValuesFunc, constrained []ConstrainedLabel, unconstrained []UnconstrainedLabel, ) { var dummy L commonLabels := dummy.Keys() diff --git a/pkg/metrics/histogram.go b/pkg/metrics/histogram.go index c1ae38c2afd..00c0623eaed 100644 --- a/pkg/metrics/histogram.go +++ b/pkg/metrics/histogram.go @@ -7,6 +7,8 @@ import ( "github.com/prometheus/client_golang/prometheus" ) +type initHistogramFunc func(*prometheus.HistogramVec) + // NewHistogramVecWithPod is a wrapper around prometheus.NewHistogramVec that also // registers the metric to be cleaned up when a pod is deleted. // @@ -35,14 +37,14 @@ func NewHistogramVecWithPodV2(opts prometheus.HistogramVecOpts) *prometheus.Hist type GranularHistogram[L FilteredLabels] struct { metric *prometheus.HistogramVec constrained bool - initFunc func() + initFunc initHistogramFunc initForDocs func() } // NewGranularHistogram creates a new GranularHistogram. // // See NewGranularCounter for usage notes. -func NewGranularHistogram[L FilteredLabels](opts HistogramOpts, init func()) (*GranularHistogram[L], error) { +func NewGranularHistogram[L FilteredLabels](opts HistogramOpts, init initHistogramFunc) (*GranularHistogram[L], error) { labels, constrained, err := getVariableLabels[L](&opts.Opts) if err != nil { return nil, err @@ -71,9 +73,12 @@ func NewGranularHistogram[L FilteredLabels](opts HistogramOpts, init func()) (*G metric.WithLabelValues(lvs...) } - // if metric is constrained, default to initializing all combinations of labels + // If metric is constrained, default to initializing all combinations of + // labels. Note that in such case the initialization function doesn't + // reference the wrapped metric passed as an argument because this metric + // is captured already in initMetric closure. if constrained && init == nil { - init = func() { + init = func(_ *prometheus.HistogramVec) { initAllCombinations(initMetric, opts.ConstrainedLabels) } } @@ -118,7 +123,7 @@ func MustNewGranularHistogram[L FilteredLabels](promOpts prometheus.HistogramOpt // MustNewGranularHistogramWithInit is a convenience function that wraps // NewGranularHistogram and panics on error. -func MustNewGranularHistogramWithInit[L FilteredLabels](opts HistogramOpts, init func()) *GranularHistogram[L] { +func MustNewGranularHistogramWithInit[L FilteredLabels](opts HistogramOpts, init initHistogramFunc) *GranularHistogram[L] { metric, err := NewGranularHistogram[L](opts, init) if err != nil { panic(err) @@ -144,7 +149,7 @@ func (m *GranularHistogram[L]) IsConstrained() bool { // Init implements CollectorWithInit. func (m *GranularHistogram[L]) Init() { if m.initFunc != nil { - m.initFunc() + m.initFunc(m.metric) } } @@ -181,7 +186,7 @@ type Histogram struct { // NewHistogram creates a new Histogram. // // See NewGranularCounter for usage notes. -func NewHistogram(opts HistogramOpts, init func()) (*Histogram, error) { +func NewHistogram(opts HistogramOpts, init initHistogramFunc) (*Histogram, error) { metric, err := NewGranularHistogram[NilLabels](opts, init) if err != nil { return nil, err @@ -191,7 +196,7 @@ func NewHistogram(opts HistogramOpts, init func()) (*Histogram, error) { // MustNewHistogram is a convenience function that wraps NewHistogram and panics on // error. -func MustNewHistogram(opts HistogramOpts, init func()) *Histogram { +func MustNewHistogram(opts HistogramOpts, init initHistogramFunc) *Histogram { metric, err := NewHistogram(opts, init) if err != nil { panic(err)