Skip to content

Commit fe7c206

Browse files
committed
prometheus: implement Collector interface for Registry
This change allows Registries to be used as Collectors. This enables new instances of Registry to be passed to ephemeral subroutines for collecting metrics from subroutines which are still running: ```go package main import ( "fmt" "github.com/prometheus/client_golang/prometheus" ) func main() { globalReg := prometheus.NewRegistry() for i := 0; i < 100; i++ { workerReg := prometheus.WrapRegistererWith(prometheus.Labels{ // Add an ID label so registered metrics from workers don't // collide. "worker_id": fmt.Sprintf("%d", i), }, prometheus.NewRegistry() globalReg.MustRegister(workerReg) go func(i int) { runWorker(workerReg) // Unregister any metrics the worker may have created. globalReg.Unregister(workerReg) }(i) } } // runWorker runs a worker, registering worker-specific metrics. func runWorker(reg *prometheus.Registry) { // ... register metrics ... // ... do work ... } ``` This change makes it easier to avoid leaking metrics from subroutines which do not consistently properly unregister metrics.
1 parent 618194d commit fe7c206

File tree

1 file changed

+28
-3
lines changed

1 file changed

+28
-3
lines changed

prometheus/registry.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,9 @@ func (errs MultiError) MaybeUnwrap() error {
252252
}
253253

254254
// Registry registers Prometheus collectors, collects their metrics, and gathers
255-
// them into MetricFamilies for exposition. It implements both Registerer and
256-
// Gatherer. The zero value is not usable. Create instances with NewRegistry or
257-
// NewPedanticRegistry.
255+
// them into MetricFamilies for exposition. It implements both Registerer,
256+
// Gatherer, and Collector. The zero value is not usable. Create instances with
257+
// NewRegistry or NewPedanticRegistry.
258258
type Registry struct {
259259
mtx sync.RWMutex
260260
collectorsByID map[uint64]Collector // ID is a hash of the descIDs.
@@ -556,6 +556,31 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) {
556556
return internal.NormalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap()
557557
}
558558

559+
// Describe implements Collector.
560+
func (r *Registry) Describe(ch chan<- *Desc) {
561+
r.mtx.RLock()
562+
defer r.mtx.RUnlock()
563+
564+
// Only report the checked Collectors; unchecked collectors don't report any
565+
// Desc.
566+
for _, c := range r.collectorsByID {
567+
c.Describe(ch)
568+
}
569+
}
570+
571+
// Collect implements Collector.
572+
func (r *Registry) Collect(ch chan<- Metric) {
573+
r.mtx.RLock()
574+
defer r.mtx.RUnlock()
575+
576+
for _, c := range r.collectorsByID {
577+
c.Collect(ch)
578+
}
579+
for _, c := range r.uncheckedCollectors {
580+
c.Collect(ch)
581+
}
582+
}
583+
559584
// WriteToTextfile calls Gather on the provided Gatherer, encodes the result in the
560585
// Prometheus text format, and writes it to a temporary file. Upon success, the
561586
// temporary file is renamed to the provided filename.

0 commit comments

Comments
 (0)