Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 13, 14:15 UTC
reverseproxy: Add upstreams healthy metrics (#4935)
Dávid Szabó committed
Aug 27, 2022 at 20:30 UTC
0c57facc67910a6b0994763ac8e6e55e693f20e4
2 files changed
+84
modules/caddyhttp/reverseproxy/metrics.go
new
+81
@@ -0,0 +1,81 @@
1
+package reverseproxy
2
+
3
+import (
4
+ "runtime/debug"
5
+ "sync"
6
+ "time"
7
+
8
+ "github.com/prometheus/client_golang/prometheus"
9
+ "github.com/prometheus/client_golang/prometheus/promauto"
10
+ "go.uber.org/zap"
11
+)
12
+
13
+var reverseProxyMetrics = struct {
14
+ init sync.Once
15
+ upstreamsHealthy *prometheus.GaugeVec
16
+ logger *zap.Logger
17
+}{}
18
+
19
+func initReverseProxyMetrics(handler *Handler) {
20
+ const ns, sub = "caddy", "reverse_proxy"
21
+
22
+ upstreamsLabels := []string{"upstream"}
23
+ reverseProxyMetrics.upstreamsHealthy = promauto.NewGaugeVec(prometheus.GaugeOpts{
24
+ Namespace: ns,
25
+ Subsystem: sub,
26
+ Name: "upstreams_healthy",
27
+ Help: "Health status of reverse proxy upstreams.",
28
+ }, upstreamsLabels)
29
+
30
+ reverseProxyMetrics.logger = handler.logger.Named("reverse_proxy.metrics")
31
+}
32
+
33
+type metricsUpstreamsHealthyUpdater struct {
34
+ handler *Handler
35
+}
36
+
37
+func newMetricsUpstreamsHealthyUpdater(handler *Handler) *metricsUpstreamsHealthyUpdater {
38
+ reverseProxyMetrics.init.Do(func() {
39
+ initReverseProxyMetrics(handler)
40
+ })
41
+
42
+ return &metricsUpstreamsHealthyUpdater{handler}
43
+}
44
+
45
+func (m *metricsUpstreamsHealthyUpdater) Init() {
46
+ go func() {
47
+ defer func() {
48
+ if err := recover(); err != nil {
49
+ reverseProxyMetrics.logger.Error("upstreams healthy metrics updater panicked",
50
+ zap.Any("error", err),
51
+ zap.ByteString("stack", debug.Stack()))
52
+ }
53
+ }()
54
+
55
+ m.update()
56
+
57
+ ticker := time.NewTicker(10 * time.Second)
58
+ for {
59
+ select {
60
+ case <-ticker.C:
61
+ m.update()
62
+ case <-m.handler.ctx.Done():
63
+ ticker.Stop()
64
+ return
65
+ }
66
+ }
67
+ }()
68
+}
69
+
70
+func (m *metricsUpstreamsHealthyUpdater) update() {
71
+ for _, upstream := range m.handler.Upstreams {
72
+ labels := prometheus.Labels{"upstream": upstream.Dial}
73
+
74
+ gaugeValue := 0.0
75
+ if upstream.Healthy() {
76
+ gaugeValue = 1.0
77
+ }
78
+
79
+ reverseProxyMetrics.upstreamsHealthy.With(labels).Set(gaugeValue)
80
+ }
81
+}
modules/caddyhttp/reverseproxy/reverseproxy.go
+3
@@ -392,6 +392,9 @@ func (h *Handler) Provision(ctx caddy.Context) error {
392
}
393
}
394
395
+ upstreamHealthyUpdater := newMetricsUpstreamsHealthyUpdater(h)
396
+ upstreamHealthyUpdater.Init()
397
+
398
return nil
399
}
400