Repository: caddyserver/caddy (language: go)

Issue:
caddy_reverse_proxy_upstreams_healthy missing in metrics page
Since update to 2.9.0, all the `caddy_reverse_proxy_upstreams_healthy` metrics are missing in the Prometheus metrics page.
All the others metrics are present, but those ones are missing.
I have checked the release note, and I don't see anything related to this. I have already moved `metric` out of `servers`
Here a part of my config :

```
{
  servers {
    trusted_proxies static 10.0.0.0/8
  }
  metrics {
    per_host
  }
  admin :2019
}


xxxxx.xxxxx.xxxx {
  tls /etc/ssl/acme/-.xxxxxx/fullchain.pem /etc/ssl/acme/-.xxxxxxx/key.pem
  reverse_proxy xxxxxx.xxxx:8096 {
    health_uri /health
    health_follow_redirects
    health_fails 3
    health_timeout 20s
  }
  log {
    output file /var/log/caddy/xxxxx.xxxxx.xxxx.log {
      roll_size 50mb
      roll_local_time
    }
  }
  handle_errors {
    root /srv
    rewrite * /{err.status_code}.html
    file_server
  }
}

```


Discussion / hints:
Sorry. I missed wiring that up when I worked on metrics.
+1

Fix patch:
diff --git a/modules/caddyhttp/reverseproxy/metrics.go b/modules/caddyhttp/reverseproxy/metrics.go
index f744756d3f9..8a7105c1193 100644
--- a/modules/caddyhttp/reverseproxy/metrics.go
+++ b/modules/caddyhttp/reverseproxy/metrics.go
@@ -2,26 +2,26 @@ package reverseproxy
 
 import (
 	"runtime/debug"
-	"sync"
 	"time"
 
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promauto"
 	"go.uber.org/zap"
 	"go.uber.org/zap/zapcore"
+
+	"github.com/caddyserver/caddy/v2"
 )
 
 var reverseProxyMetrics = struct {
-	init             sync.Once
 	upstreamsHealthy *prometheus.GaugeVec
 	logger           *zap.Logger
 }{}
 
-func initReverseProxyMetrics(handler *Handler) {
+func initReverseProxyMetrics(handler *Handler, registry *prometheus.Registry) {
 	const ns, sub = "caddy", "reverse_proxy"
 
 	upstreamsLabels := []string{"upstream"}
-	reverseProxyMetrics.upstreamsHealthy = promauto.NewGaugeVec(prometheus.GaugeOpts{
+	reverseProxyMetrics.upstreamsHealthy = promauto.With(registry).NewGaugeVec(prometheus.GaugeOpts{
 		Namespace: ns,
 		Subsystem: sub,
 		Name:      "upstreams_healthy",
@@ -35,17 +35,19 @@ type metricsUpstreamsHealthyUpdater struct {
 	handler *Handler
 }
 
-func newMetricsUpstreamsHealthyUpdater(handler *Handler) *metricsUpstreamsHealthyUpdater {
-	reverseProxyMetrics.init.Do(func() {
-		initReverseProxyMetrics(handler)
-	})
+const upstreamsHealthyMetrics caddy.CtxKey = "reverse_proxy_upstreams_healthy"
 
+func newMetricsUpstreamsHealthyUpdater(handler *Handler, ctx caddy.Context) *metricsUpstreamsHealthyUpdater {
+	if set := ctx.Value(upstreamsHealthyMetrics); set == nil {
+		initReverseProxyMetrics(handler, ctx.GetMetricsRegistry())
+		ctx = ctx.WithValue(upstreamsHealthyMetrics, true)
+	}
 	reverseProxyMetrics.upstreamsHealthy.Reset()
 
 	return &metricsUpstreamsHealthyUpdater{handler}
 }
 
-func (m *metricsUpstreamsHealthyUpdater) Init() {
+func (m *metricsUpstreamsHealthyUpdater) init() {
 	go func() {
 		defer func() {
 			if err := recover(); err != nil {
diff --git a/modules/caddyhttp/reverseproxy/reverseproxy.go b/modules/caddyhttp/reverseproxy/reverseproxy.go
index a15dbe42484..d799c5a6e7e 100644
--- a/modules/caddyhttp/reverseproxy/reverseproxy.go
+++ b/modules/caddyhttp/reverseproxy/reverseproxy.go
@@ -382,8 +382,8 @@ func (h *Handler) Provision(ctx caddy.Context) error {
 		}
 	}
 
-	upstreamHealthyUpdater := newMetricsUpstreamsHealthyUpdater(h)
-	upstreamHealthyUpdater.Init()
+	upstreamHealthyUpdater := newMetricsUpstreamsHealthyUpdater(h, ctx)
+	upstreamHealthyUpdater.init()
 
 	return nil
 }


Test patch: