[v11.3.x] Plugin Metrics: Eliminate data race in plugin metrics middleware (#100076)

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()
  ...

```

(cherry picked from commit e74cf72d99)

Co-authored-by: Christopher Lord <christopher.lord@grafana.com>
This commit is contained in:
grafana-delivery-bot[bot]
2025-02-04 17:48:39 +00:00
committed by GitHub
co-authored by Christopher Lord
parent 16d77128f2
commit f99b152dc1
@@ -76,10 +76,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,
}
})
}