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}