diff --git a/pkg/metrics/group.go b/pkg/metrics/group.go index ff1c090bb9c..9d087ae597a 100644 --- a/pkg/metrics/group.go +++ b/pkg/metrics/group.go @@ -9,37 +9,34 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -// CollectorWithInit extends prometheus.Collector with methods for metrics -// initialization and checking constraints. -type CollectorWithInit interface { - prometheus.Collector +// initializer contains methods for metrics initialization and checking +// constraints. +type initializer interface { IsConstrained() bool Init() InitForDocs() } -// Group extends prometheus.Registerer with methods for metrics -// initialization and checking constraints. It also includes -// prometheus.Collector, because MetricsGroups are intended to be registered in -// a root prometheus.Registry. -type Group interface { +// CollectorWithInit extends prometheus.Collector with initializer. +type CollectorWithInit interface { prometheus.Collector + initializer +} + +// Group extends prometheus.Registerer with CollectorWithInit. +// It represents a sub-registry of the root prometheus.Registry. +type Group interface { prometheus.Registerer - RegisterWithInit(CollectorWithInit) error - MustRegisterWithInit(CollectorWithInit) + CollectorWithInit ExtendInit(func()) ExtendInitForDocs(func()) - IsConstrained() bool - Init() - InitForDocs() } // metricsGroup wraps prometheus.Registry and implements Group type metricsGroup struct { registry *prometheus.Registry - // If constrained is true, group will only accept metrics with constrained - // cardinality - but this is checked only for metrics registered with - // (Must)RegisterWithInit. + // If constrained is true, group will accept collectors implementing + // initializer only if they are constrained. constrained bool initFunc func() initForDocsFunc func() @@ -66,13 +63,41 @@ func (r *metricsGroup) Collect(ch chan<- prometheus.Metric) { } // Register implements Group (prometheus.Registerer). +// +// It wraps the Register method of the underlying registry. Additionally, if +// the collector implements initializer, it: +// - checks constraints - attempt to register an unconstrained collector in +// a constrained group results in an error +// - extends Init and InitForDocs methods with initialization of the +// registered collector func (r *metricsGroup) Register(c prometheus.Collector) error { - return r.registry.Register(c) + cc, hasInit := c.(initializer) + if hasInit { + // check constraints + if r.IsConstrained() && !cc.IsConstrained() { + return errors.New("can't register unconstrained metrics in a constrained group") + } + } + // register + err := r.registry.Register(c) + if err != nil { + return err + } + if hasInit { + // extend init + r.ExtendInit(cc.Init) + r.ExtendInitForDocs(cc.InitForDocs) + } + return nil } // MustRegister implements Group (prometheus.Registerer). func (r *metricsGroup) MustRegister(cs ...prometheus.Collector) { - r.registry.MustRegister(cs...) + for _, c := range cs { + if err := r.Register(c); err != nil { + panic(err) + } + } } // Unregister implements Group (prometheus.Registerer). @@ -80,51 +105,19 @@ func (r *metricsGroup) Unregister(c prometheus.Collector) bool { return r.registry.Unregister(c) } -// IsConstrained implements Group. +// IsConstrained implements Group (initializer). func (r *metricsGroup) IsConstrained() bool { return r.constrained } -// RegisterWithInit implements Group. It wraps Register method and -// additionally: -// - checks constraints - attempt to register an unconstrained collector in -// a constrained group results in an error -// - extends Init and InitForDocs methods with initialization of the -// registered collector -func (r *metricsGroup) RegisterWithInit(c CollectorWithInit) error { - // check constraints - if r.IsConstrained() && !c.IsConstrained() { - return errors.New("can't register unconstrained metrics in a constrained group") - } - - // register - err := r.Register(c) - if err != nil { - return err - } - - // extend init - r.ExtendInit(c.Init) - r.ExtendInitForDocs(c.InitForDocs) - return nil -} - -// MustRegisterWithInit implements Group. -func (r *metricsGroup) MustRegisterWithInit(c CollectorWithInit) { - err := r.RegisterWithInit(c) - if err != nil { - panic(err) - } -} - -// Init implements Group. +// Init implements Group (initializer). func (r *metricsGroup) Init() { if r.initFunc != nil { r.initFunc() } } -// InitForDocs implements Group. +// InitForDocs implements Group (initializer). func (r *metricsGroup) InitForDocs() { if r.initForDocsFunc != nil { r.initForDocsFunc()