...
1 package redis
2
3 import (
4 "errors"
5 "slices"
6 "strings"
7
8 "github.com/prometheus/client_golang/prometheus"
9 "github.com/redis/go-redis/v9"
10 )
11
12
13 type poolStatGetter interface {
14 PoolStats() *redis.PoolStats
15 }
16
17 var _ poolStatGetter = (*redis.ClusterClient)(nil)
18
19 type metricsCollector struct {
20 statGetter poolStatGetter
21
22
23
24 lookups *prometheus.Desc
25 totalConns *prometheus.Desc
26 idleConns *prometheus.Desc
27 staleConns *prometheus.Desc
28 }
29
30
31
32 func (dbc metricsCollector) Describe(ch chan<- *prometheus.Desc) {
33 prometheus.DescribeByCollect(dbc, ch)
34 }
35
36
37
38
39
40
41
42 func (dbc metricsCollector) Collect(ch chan<- prometheus.Metric) {
43 writeGauge := func(stat *prometheus.Desc, val uint32, labelValues ...string) {
44 ch <- prometheus.MustNewConstMetric(stat, prometheus.GaugeValue, float64(val), labelValues...)
45 }
46
47 stats := dbc.statGetter.PoolStats()
48 writeGauge(dbc.lookups, stats.Hits, "hit")
49 writeGauge(dbc.lookups, stats.Misses, "miss")
50 writeGauge(dbc.lookups, stats.Timeouts, "timeout")
51 writeGauge(dbc.totalConns, stats.TotalConns)
52 writeGauge(dbc.idleConns, stats.IdleConns)
53 writeGauge(dbc.staleConns, stats.StaleConns)
54 }
55
56
57 func newClientMetricsCollector(statGetter poolStatGetter, labels prometheus.Labels) metricsCollector {
58 return metricsCollector{
59 statGetter: statGetter,
60 lookups: prometheus.NewDesc(
61 "redis_connection_pool_lookups",
62 "Number of lookups for a connection in the pool, labeled by hit/miss",
63 []string{"result"}, labels),
64 totalConns: prometheus.NewDesc(
65 "redis_connection_pool_total_conns",
66 "Number of total connections in the pool.",
67 nil, labels),
68 idleConns: prometheus.NewDesc(
69 "redis_connection_pool_idle_conns",
70 "Number of idle connections in the pool.",
71 nil, labels),
72 staleConns: prometheus.NewDesc(
73 "redis_connection_pool_stale_conns",
74 "Number of stale connections removed from the pool.",
75 nil, labels),
76 }
77 }
78
79
80
81
82
83 func MustRegisterClientMetricsCollector(client poolStatGetter, stats prometheus.Registerer, addrs map[string]string, user string) {
84 var labelAddrs []string
85 for addr := range addrs {
86 labelAddrs = append(labelAddrs, addr)
87 }
88
89 slices.Sort(labelAddrs)
90 labels := prometheus.Labels{
91 "addresses": strings.Join(labelAddrs, ", "),
92 "user": user,
93 }
94 err := stats.Register(newClientMetricsCollector(client, labels))
95 if err != nil {
96 are := prometheus.AlreadyRegisteredError{}
97 if errors.As(err, &are) {
98
99 return
100 }
101 panic(err)
102 }
103 }
104
View as plain text