summaryrefslogtreecommitdiff
path: root/modules/caddyhttp/reverseproxy/metrics.go
diff options
context:
space:
mode:
authorDávid Szabó <david.szabo97@gmail.com>2022-08-27 20:30:23 +0200
committerGitHub <noreply@github.com>2022-08-27 12:30:23 -0600
commit0c57facc67910a6b0994763ac8e6e55e693f20e4 (patch)
tree56f819b1a15004140735d6826b64a0c116937b29 /modules/caddyhttp/reverseproxy/metrics.go
parent4c282e86dae16359370f410e29dc96dc5aeeb449 (diff)
reverseproxy: Add upstreams healthy metrics (#4935)
Diffstat (limited to 'modules/caddyhttp/reverseproxy/metrics.go')
-rw-r--r--modules/caddyhttp/reverseproxy/metrics.go81
1 files changed, 81 insertions, 0 deletions
diff --git a/modules/caddyhttp/reverseproxy/metrics.go b/modules/caddyhttp/reverseproxy/metrics.go
new file mode 100644
index 0000000..4272bc4
--- /dev/null
+++ b/modules/caddyhttp/reverseproxy/metrics.go
@@ -0,0 +1,81 @@
+package reverseproxy
+
+import (
+ "runtime/debug"
+ "sync"
+ "time"
+
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promauto"
+ "go.uber.org/zap"
+)
+
+var reverseProxyMetrics = struct {
+ init sync.Once
+ upstreamsHealthy *prometheus.GaugeVec
+ logger *zap.Logger
+}{}
+
+func initReverseProxyMetrics(handler *Handler) {
+ const ns, sub = "caddy", "reverse_proxy"
+
+ upstreamsLabels := []string{"upstream"}
+ reverseProxyMetrics.upstreamsHealthy = promauto.NewGaugeVec(prometheus.GaugeOpts{
+ Namespace: ns,
+ Subsystem: sub,
+ Name: "upstreams_healthy",
+ Help: "Health status of reverse proxy upstreams.",
+ }, upstreamsLabels)
+
+ reverseProxyMetrics.logger = handler.logger.Named("reverse_proxy.metrics")
+}
+
+type metricsUpstreamsHealthyUpdater struct {
+ handler *Handler
+}
+
+func newMetricsUpstreamsHealthyUpdater(handler *Handler) *metricsUpstreamsHealthyUpdater {
+ reverseProxyMetrics.init.Do(func() {
+ initReverseProxyMetrics(handler)
+ })
+
+ return &metricsUpstreamsHealthyUpdater{handler}
+}
+
+func (m *metricsUpstreamsHealthyUpdater) Init() {
+ go func() {
+ defer func() {
+ if err := recover(); err != nil {
+ reverseProxyMetrics.logger.Error("upstreams healthy metrics updater panicked",
+ zap.Any("error", err),
+ zap.ByteString("stack", debug.Stack()))
+ }
+ }()
+
+ m.update()
+
+ ticker := time.NewTicker(10 * time.Second)
+ for {
+ select {
+ case <-ticker.C:
+ m.update()
+ case <-m.handler.ctx.Done():
+ ticker.Stop()
+ return
+ }
+ }
+ }()
+}
+
+func (m *metricsUpstreamsHealthyUpdater) update() {
+ for _, upstream := range m.handler.Upstreams {
+ labels := prometheus.Labels{"upstream": upstream.Dial}
+
+ gaugeValue := 0.0
+ if upstream.Healthy() {
+ gaugeValue = 1.0
+ }
+
+ reverseProxyMetrics.upstreamsHealthy.With(labels).Set(gaugeValue)
+ }
+}