diff --git a/CHANGELOG.md b/CHANGELOG.md index b1c22e2b4..00d85cc85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Stop percent encoding header environment variables in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc` and `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#6392) - Ensure the `noopSpan.tracerProvider` method is not inlined in `go.opentelemetry.io/otel/trace` so the `go.opentelemetry.io/auto` instrumentation can instrument non-recording spans. (#6456) +- Use a `sync.Pool` instead of allocating `metricdata.ResourceMetrics` in `go.opentelemetry.io/otel/exporters/prometheus`. (#6472) diff --git a/exporters/prometheus/exporter.go b/exporters/prometheus/exporter.go index a8677e93a..c33611c1a 100644 --- a/exporters/prometheus/exporter.go +++ b/exporters/prometheus/exporter.go @@ -40,7 +40,15 @@ const ( spanIDExemplarKey = "span_id" ) -var errScopeInvalid = errors.New("invalid scope") +var ( + errScopeInvalid = errors.New("invalid scope") + + metricsPool = sync.Pool{ + New: func() interface{} { + return &metricdata.ResourceMetrics{} + }, + } +) // Exporter is a Prometheus Exporter that embeds the OTel metric.Reader // interface for easy instantiation with a MeterProvider. @@ -144,9 +152,9 @@ func (c *collector) Describe(ch chan<- *prometheus.Desc) { // // This method is safe to call concurrently. func (c *collector) Collect(ch chan<- prometheus.Metric) { - // TODO (#3047): Use a sync.Pool instead of allocating metrics every Collect. - metrics := metricdata.ResourceMetrics{} - err := c.reader.Collect(context.TODO(), &metrics) + metrics := metricsPool.Get().(*metricdata.ResourceMetrics) + defer metricsPool.Put(metrics) + err := c.reader.Collect(context.TODO(), metrics) if err != nil { if errors.Is(err, metric.ErrReaderShutdown) { return