Plugin Metrics: Eliminate data race in plugin metrics middleware (#99396)

fix: eliminate data race in plugin metrics middleware

A data race was detected when multiple goroutines accessed the `MetricsMiddleware`
simultaneously. The race occurred because a single `MetricsMiddleware` instance
was being shared across goroutines while its `BaseHandler` field was being
modified during middleware chain setup.

Fix by creating a new `MetricsMiddleware` instance for each middleware chain,
while safely sharing the thread-safe Prometheus metrics and plugin registry.
This maintains proper metrics collection while eliminating the mutable shared
state that caused the race condition.

Original error was detected here:

```
WARNING: DATA RACE
Read at 0x00c0039c0790 by goroutine 4486:
  github.com/grafana/grafana-plugin-sdk-go/backend.(*ErrorSourceMiddleware).CallResource()
      /Users/clord/src/grafana/irm-devstack/.devenv/state/go/pkg/mod/github.com/grafana/grafana-plugin-sdk-go@v0.261.0/backend/error_source_middleware.go:93 +0x40
  github.com/grafana/grafana-plugin-sdk-go/backend.BaseHandler.CallResource()
  ...

```
This commit is contained in:
Christopher Lord
2025-02-04 16:54:27 +00:00
committed by GitHub
parent b16e290444
commit e74cf72d99
@@ -75,10 +75,13 @@ func newMetricsMiddleware(promRegisterer prometheus.Registerer, pluginRegistry r
// NewMetricsMiddleware returns a new MetricsMiddleware.
func NewMetricsMiddleware(promRegisterer prometheus.Registerer, pluginRegistry registry.Service) backend.HandlerMiddleware {
imw := newMetricsMiddleware(promRegisterer, pluginRegistry)
metrics := newMetricsMiddleware(promRegisterer, pluginRegistry)
return backend.HandlerMiddlewareFunc(func(next backend.Handler) backend.Handler {
imw.BaseHandler = backend.NewBaseHandler(next)
return imw
return &MetricsMiddleware{
BaseHandler: backend.NewBaseHandler(next),
pluginMetrics: metrics.pluginMetrics,
pluginRegistry: metrics.pluginRegistry,
}
})
}