@marcel91200 / caddy Mirror · read-only / commits / 9283770f
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 12, 03:15 UTC

reverseproxy: ignore duplicate collector registration error (#6820)

Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com>

Mohammed Al Sahaf committed Feb 4, 2025 at 10:55 UTC 9283770f68f570f47ca20aa9c6f9de8cc50063ba
1 file changed +23 -13
modules/caddyhttp/reverseproxy/metrics.go
+23 -13
@@ -1,11 +1,12 @@
1 package reverseproxy
2
3 import (
4 + "errors"
5 "runtime/debug"
6 + "sync"
7 "time"
8
9 "github.com/prometheus/client_golang/prometheus"
8 - "github.com/prometheus/client_golang/prometheus/promauto"
10 "go.uber.org/zap"
11 "go.uber.org/zap/zapcore"
12
@@ -13,6 +14,7 @@ import (
14 )
15
16 var reverseProxyMetrics = struct {
17 + once sync.Once
18 upstreamsHealthy *prometheus.GaugeVec
19 logger *zap.Logger
20 }{}
@@ -21,12 +23,25 @@ func initReverseProxyMetrics(handler *Handler, registry *prometheus.Registry) {
23 const ns, sub = "caddy", "reverse_proxy"
24
25 upstreamsLabels := []string{"upstream"}
24 - reverseProxyMetrics.upstreamsHealthy = promauto.With(registry).NewGaugeVec(prometheus.GaugeOpts{
25 - Namespace: ns,
26 - Subsystem: sub,
27 - Name: "upstreams_healthy",
28 - Help: "Health status of reverse proxy upstreams.",
29 - }, upstreamsLabels)
26 + reverseProxyMetrics.once.Do(func() {
27 + reverseProxyMetrics.upstreamsHealthy = prometheus.NewGaugeVec(prometheus.GaugeOpts{
28 + Namespace: ns,
29 + Subsystem: sub,
30 + Name: "upstreams_healthy",
31 + Help: "Health status of reverse proxy upstreams.",
32 + }, upstreamsLabels)
33 + })
34 +
35 + // duplicate registration could happen if multiple sites with reverse proxy are configured; so ignore the error because
36 + // there's no good way to capture having multiple sites with reverse proxy. If this happens, the metrics will be
37 + // registered twice, but the second registration will be ignored.
38 + if err := registry.Register(reverseProxyMetrics.upstreamsHealthy); err != nil &&
39 + !errors.Is(err, prometheus.AlreadyRegisteredError{
40 + ExistingCollector: reverseProxyMetrics.upstreamsHealthy,
41 + NewCollector: reverseProxyMetrics.upstreamsHealthy,
42 + }) {
43 + panic(err)
44 + }
45
46 reverseProxyMetrics.logger = handler.logger.Named("reverse_proxy.metrics")
47 }
@@ -35,13 +50,8 @@ type metricsUpstreamsHealthyUpdater struct {
50 handler *Handler
51 }
52
38 -const upstreamsHealthyMetrics caddy.CtxKey = "reverse_proxy_upstreams_healthy"
39 -
53 func newMetricsUpstreamsHealthyUpdater(handler *Handler, ctx caddy.Context) *metricsUpstreamsHealthyUpdater {
41 - if set := ctx.Value(upstreamsHealthyMetrics); set == nil {
42 - initReverseProxyMetrics(handler, ctx.GetMetricsRegistry())
43 - ctx = ctx.WithValue(upstreamsHealthyMetrics, true)
44 - }
54 + initReverseProxyMetrics(handler, ctx.GetMetricsRegistry())
55 reverseProxyMetrics.upstreamsHealthy.Reset()
56
57 return &metricsUpstreamsHealthyUpdater{handler}