// Copyright 2020 The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package discovery import ( "fmt" "github.com/prometheus/client_golang/prometheus" ) // MetricRegisterer is used by implementations of discovery.Discoverer that need // to manage the lifetime of their metrics. type MetricRegisterer interface { RegisterMetrics() error UnregisterMetrics() } // metricRegistererImpl is an implementation of MetricRegisterer. type metricRegistererImpl struct { reg prometheus.Registerer metrics []prometheus.Collector } var _ MetricRegisterer = &metricRegistererImpl{} // NewMetricRegisterer creates an instance of a MetricRegisterer. // Typically called inside the implementation of the NewDiscoverer() method. func NewMetricRegisterer(reg prometheus.Registerer, metrics []prometheus.Collector) MetricRegisterer { return &metricRegistererImpl{ reg: reg, metrics: metrics, } } // RegisterMetrics registers the metrics with a Prometheus registerer. // If any metric fails to register, it will unregister all metrics that // were registered so far, and return an error. // Typically called at the start of the SD's Run() method. func (rh *metricRegistererImpl) RegisterMetrics() error { for _, collector := range rh.metrics { err := rh.reg.Register(collector) if err != nil { // Unregister all metrics that were registered so far. // This is so that if RegisterMetrics() gets called again, // there will not be an error due to a duplicate registration. rh.UnregisterMetrics() return fmt.Errorf("failed to register metric: %w", err) } } return nil } // UnregisterMetrics unregisters the metrics from the same Prometheus // registerer which was used to register them. // Typically called at the end of the SD's Run() method by a defer statement. func (rh *metricRegistererImpl) UnregisterMetrics() { for _, collector := range rh.metrics { rh.reg.Unregister(collector) } }