metrics.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. package redis
  2. import (
  3. "sync"
  4. red "github.com/go-redis/redis/v8"
  5. "github.com/prometheus/client_golang/prometheus"
  6. "github.com/wuntsong-org/go-zero-plus/core/metric"
  7. )
  8. const namespace = "redis_client"
  9. var (
  10. metricReqDur = metric.NewHistogramVec(&metric.HistogramVecOpts{
  11. Namespace: namespace,
  12. Subsystem: "requests",
  13. Name: "duration_ms",
  14. Help: "redis client requests duration(ms).",
  15. Labels: []string{"command"},
  16. Buckets: []float64{0.25, 0.5, 1, 1.5, 2, 3, 5, 10, 25, 50, 100, 250, 500, 1000, 2000, 5000, 10000, 15000},
  17. })
  18. metricReqErr = metric.NewCounterVec(&metric.CounterVecOpts{
  19. Namespace: namespace,
  20. Subsystem: "requests",
  21. Name: "error_total",
  22. Help: "redis client requests error count.",
  23. Labels: []string{"command", "error"},
  24. })
  25. metricSlowCount = metric.NewCounterVec(&metric.CounterVecOpts{
  26. Namespace: namespace,
  27. Subsystem: "requests",
  28. Name: "slow_total",
  29. Help: "redis client requests slow count.",
  30. Labels: []string{"command"},
  31. })
  32. connLabels = []string{"key", "client_type"}
  33. connCollector = newCollector()
  34. _ prometheus.Collector = (*collector)(nil)
  35. )
  36. type (
  37. statGetter struct {
  38. clientType string
  39. key string
  40. poolSize int
  41. poolStats func() *red.PoolStats
  42. }
  43. // collector collects statistics from a redis client.
  44. // It implements the prometheus.Collector interface.
  45. collector struct {
  46. hitDesc *prometheus.Desc
  47. missDesc *prometheus.Desc
  48. timeoutDesc *prometheus.Desc
  49. totalDesc *prometheus.Desc
  50. idleDesc *prometheus.Desc
  51. staleDesc *prometheus.Desc
  52. maxDesc *prometheus.Desc
  53. clients []*statGetter
  54. lock sync.Mutex
  55. }
  56. )
  57. func newCollector() *collector {
  58. c := &collector{
  59. hitDesc: prometheus.NewDesc(
  60. prometheus.BuildFQName(namespace, "", "pool_hit_total"),
  61. "Number of times a connection was found in the pool",
  62. connLabels, nil,
  63. ),
  64. missDesc: prometheus.NewDesc(
  65. prometheus.BuildFQName(namespace, "", "pool_miss_total"),
  66. "Number of times a connection was not found in the pool",
  67. connLabels, nil,
  68. ),
  69. timeoutDesc: prometheus.NewDesc(
  70. prometheus.BuildFQName(namespace, "", "pool_timeout_total"),
  71. "Number of times a timeout occurred when looking for a connection in the pool",
  72. connLabels, nil,
  73. ),
  74. totalDesc: prometheus.NewDesc(
  75. prometheus.BuildFQName(namespace, "", "pool_conn_total_current"),
  76. "Current number of connections in the pool",
  77. connLabels, nil,
  78. ),
  79. idleDesc: prometheus.NewDesc(
  80. prometheus.BuildFQName(namespace, "", "pool_conn_idle_current"),
  81. "Current number of idle connections in the pool",
  82. connLabels, nil,
  83. ),
  84. staleDesc: prometheus.NewDesc(
  85. prometheus.BuildFQName(namespace, "", "pool_conn_stale_total"),
  86. "Number of times a connection was removed from the pool because it was stale",
  87. connLabels, nil,
  88. ),
  89. maxDesc: prometheus.NewDesc(
  90. prometheus.BuildFQName(namespace, "", "pool_conn_max"),
  91. "Max number of connections in the pool",
  92. connLabels, nil,
  93. ),
  94. }
  95. prometheus.MustRegister(c)
  96. return c
  97. }
  98. // Describe implements the prometheus.Collector interface.
  99. func (s *collector) Describe(descs chan<- *prometheus.Desc) {
  100. descs <- s.hitDesc
  101. descs <- s.missDesc
  102. descs <- s.timeoutDesc
  103. descs <- s.totalDesc
  104. descs <- s.idleDesc
  105. descs <- s.staleDesc
  106. descs <- s.maxDesc
  107. }
  108. // Collect implements the prometheus.Collector interface.
  109. func (s *collector) Collect(metrics chan<- prometheus.Metric) {
  110. s.lock.Lock()
  111. defer s.lock.Unlock()
  112. for _, client := range s.clients {
  113. key, clientType := client.key, client.clientType
  114. stats := client.poolStats()
  115. metrics <- prometheus.MustNewConstMetric(
  116. s.hitDesc,
  117. prometheus.CounterValue,
  118. float64(stats.Hits),
  119. key,
  120. clientType,
  121. )
  122. metrics <- prometheus.MustNewConstMetric(
  123. s.missDesc,
  124. prometheus.CounterValue,
  125. float64(stats.Misses),
  126. key,
  127. clientType,
  128. )
  129. metrics <- prometheus.MustNewConstMetric(
  130. s.timeoutDesc,
  131. prometheus.CounterValue,
  132. float64(stats.Timeouts),
  133. key,
  134. clientType,
  135. )
  136. metrics <- prometheus.MustNewConstMetric(
  137. s.totalDesc,
  138. prometheus.GaugeValue,
  139. float64(stats.TotalConns),
  140. key,
  141. clientType,
  142. )
  143. metrics <- prometheus.MustNewConstMetric(
  144. s.idleDesc,
  145. prometheus.GaugeValue,
  146. float64(stats.IdleConns),
  147. key,
  148. clientType,
  149. )
  150. metrics <- prometheus.MustNewConstMetric(
  151. s.staleDesc,
  152. prometheus.CounterValue,
  153. float64(stats.StaleConns),
  154. key,
  155. clientType,
  156. )
  157. metrics <- prometheus.MustNewConstMetric(
  158. s.maxDesc,
  159. prometheus.CounterValue,
  160. float64(client.poolSize),
  161. key,
  162. clientType,
  163. )
  164. }
  165. }
  166. func (s *collector) registerClient(client *statGetter) {
  167. s.lock.Lock()
  168. defer s.lock.Unlock()
  169. s.clients = append(s.clients, client)
  170. }