metrics.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. package stats
  2. import (
  3. "log"
  4. "net"
  5. "net/http"
  6. "os"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "github.com/prometheus/client_golang/prometheus"
  11. "github.com/prometheus/client_golang/prometheus/collectors"
  12. "github.com/prometheus/client_golang/prometheus/promhttp"
  13. "github.com/prometheus/client_golang/prometheus/push"
  14. "github.com/seaweedfs/seaweedfs/weed/glog"
  15. )
  16. // Readonly volume types
  17. const (
  18. Namespace = "SeaweedFS"
  19. IsReadOnly = "IsReadOnly"
  20. NoWriteOrDelete = "noWriteOrDelete"
  21. NoWriteCanDelete = "noWriteCanDelete"
  22. IsDiskSpaceLow = "isDiskSpaceLow"
  23. )
  24. var readOnlyVolumeTypes = [4]string{IsReadOnly, NoWriteOrDelete, NoWriteCanDelete, IsDiskSpaceLow}
  25. var (
  26. Gather = prometheus.NewRegistry()
  27. MasterClientConnectCounter = prometheus.NewCounterVec(
  28. prometheus.CounterOpts{
  29. Namespace: Namespace,
  30. Subsystem: "wdclient",
  31. Name: "connect_updates",
  32. Help: "Counter of master client leader updates.",
  33. }, []string{"type"})
  34. MasterRaftIsleader = prometheus.NewGauge(
  35. prometheus.GaugeOpts{
  36. Namespace: Namespace,
  37. Subsystem: "master",
  38. Name: "is_leader",
  39. Help: "is leader",
  40. })
  41. MasterAdminLock = prometheus.NewGaugeVec(
  42. prometheus.GaugeOpts{
  43. Namespace: Namespace,
  44. Subsystem: "master",
  45. Name: "admin_lock",
  46. Help: "admin lock",
  47. }, []string{"client"})
  48. MasterReceivedHeartbeatCounter = prometheus.NewCounterVec(
  49. prometheus.CounterOpts{
  50. Namespace: Namespace,
  51. Subsystem: "master",
  52. Name: "received_heartbeats",
  53. Help: "Counter of master received heartbeat.",
  54. }, []string{"type"})
  55. MasterReplicaPlacementMismatch = prometheus.NewGaugeVec(
  56. prometheus.GaugeOpts{
  57. Namespace: Namespace,
  58. Subsystem: "master",
  59. Name: "replica_placement_mismatch",
  60. Help: "replica placement mismatch",
  61. }, []string{"collection", "id"})
  62. MasterVolumeLayout = prometheus.NewGaugeVec(
  63. prometheus.GaugeOpts{
  64. Namespace: Namespace,
  65. Subsystem: "master",
  66. Name: "volume_layout_total",
  67. Help: "Number of volumes in volume layouts",
  68. }, []string{"collection", "replica", "type"})
  69. MasterLeaderChangeCounter = prometheus.NewCounterVec(
  70. prometheus.CounterOpts{
  71. Namespace: Namespace,
  72. Subsystem: "master",
  73. Name: "leader_changes",
  74. Help: "Counter of master leader changes.",
  75. }, []string{"type"})
  76. FilerRequestCounter = prometheus.NewCounterVec(
  77. prometheus.CounterOpts{
  78. Namespace: Namespace,
  79. Subsystem: "filer",
  80. Name: "request_total",
  81. Help: "Counter of filer requests.",
  82. }, []string{"type", "code"})
  83. FilerHandlerCounter = prometheus.NewCounterVec(
  84. prometheus.CounterOpts{
  85. Namespace: Namespace,
  86. Subsystem: "filer",
  87. Name: "handler_total",
  88. Help: "Counter of filer handlers.",
  89. }, []string{"type"})
  90. FilerRequestHistogram = prometheus.NewHistogramVec(
  91. prometheus.HistogramOpts{
  92. Namespace: Namespace,
  93. Subsystem: "filer",
  94. Name: "request_seconds",
  95. Help: "Bucketed histogram of filer request processing time.",
  96. Buckets: prometheus.ExponentialBuckets(0.0001, 2, 24),
  97. }, []string{"type"})
  98. FilerServerLastSendTsOfSubscribeGauge = prometheus.NewGaugeVec(
  99. prometheus.GaugeOpts{
  100. Namespace: Namespace,
  101. Subsystem: "filer",
  102. Name: "last_send_timestamp_of_subscribe",
  103. Help: "The last send timestamp of the filer subscription.",
  104. }, []string{"sourceFiler", "clientName", "path"})
  105. FilerStoreCounter = prometheus.NewCounterVec(
  106. prometheus.CounterOpts{
  107. Namespace: Namespace,
  108. Subsystem: "filerStore",
  109. Name: "request_total",
  110. Help: "Counter of filer store requests.",
  111. }, []string{"store", "type"})
  112. FilerStoreHistogram = prometheus.NewHistogramVec(
  113. prometheus.HistogramOpts{
  114. Namespace: Namespace,
  115. Subsystem: "filerStore",
  116. Name: "request_seconds",
  117. Help: "Bucketed histogram of filer store request processing time.",
  118. Buckets: prometheus.ExponentialBuckets(0.0001, 2, 24),
  119. }, []string{"store", "type"})
  120. FilerSyncOffsetGauge = prometheus.NewGaugeVec(
  121. prometheus.GaugeOpts{
  122. Namespace: Namespace,
  123. Subsystem: "filerSync",
  124. Name: "sync_offset",
  125. Help: "The offset of the filer synchronization service.",
  126. }, []string{"sourceFiler", "targetFiler", "clientName", "path"})
  127. VolumeServerRequestCounter = prometheus.NewCounterVec(
  128. prometheus.CounterOpts{
  129. Namespace: Namespace,
  130. Subsystem: "volumeServer",
  131. Name: "request_total",
  132. Help: "Counter of volume server requests.",
  133. }, []string{"type", "code"})
  134. VolumeServerHandlerCounter = prometheus.NewCounterVec(
  135. prometheus.CounterOpts{
  136. Namespace: Namespace,
  137. Subsystem: "volumeServer",
  138. Name: "handler_total",
  139. Help: "Counter of volume server handlers.",
  140. }, []string{"type"})
  141. VolumeServerVacuumingCompactCounter = prometheus.NewCounterVec(
  142. prometheus.CounterOpts{
  143. Namespace: Namespace,
  144. Subsystem: "volumeServer",
  145. Name: "vacuuming_compact_count",
  146. Help: "Counter of volume vacuuming Compact counter",
  147. }, []string{"success"})
  148. VolumeServerVacuumingCommitCounter = prometheus.NewCounterVec(
  149. prometheus.CounterOpts{
  150. Namespace: Namespace,
  151. Subsystem: "volumeServer",
  152. Name: "vacuuming_commit_count",
  153. Help: "Counter of volume vacuuming commit counter",
  154. }, []string{"success"})
  155. VolumeServerVacuumingHistogram = prometheus.NewHistogramVec(
  156. prometheus.HistogramOpts{
  157. Namespace: Namespace,
  158. Subsystem: "volumeServer",
  159. Name: "vacuuming_seconds",
  160. Help: "Bucketed histogram of volume server vacuuming processing time.",
  161. Buckets: prometheus.ExponentialBuckets(0.0001, 2, 24),
  162. }, []string{"type"})
  163. VolumeServerRequestHistogram = prometheus.NewHistogramVec(
  164. prometheus.HistogramOpts{
  165. Namespace: Namespace,
  166. Subsystem: "volumeServer",
  167. Name: "request_seconds",
  168. Help: "Bucketed histogram of volume server request processing time.",
  169. Buckets: prometheus.ExponentialBuckets(0.0001, 2, 24),
  170. }, []string{"type"})
  171. VolumeServerVolumeGauge = prometheus.NewGaugeVec(
  172. prometheus.GaugeOpts{
  173. Namespace: Namespace,
  174. Subsystem: "volumeServer",
  175. Name: "volumes",
  176. Help: "Number of volumes or shards.",
  177. }, []string{"collection", "type"})
  178. VolumeServerReadOnlyVolumeGauge = prometheus.NewGaugeVec(
  179. prometheus.GaugeOpts{
  180. Namespace: Namespace,
  181. Subsystem: "volumeServer",
  182. Name: "read_only_volumes",
  183. Help: "Number of read only volumes.",
  184. }, []string{"collection", "type"})
  185. VolumeServerMaxVolumeCounter = prometheus.NewGauge(
  186. prometheus.GaugeOpts{
  187. Namespace: Namespace,
  188. Subsystem: "volumeServer",
  189. Name: "max_volumes",
  190. Help: "Maximum number of volumes.",
  191. })
  192. VolumeServerDiskSizeGauge = prometheus.NewGaugeVec(
  193. prometheus.GaugeOpts{
  194. Namespace: Namespace,
  195. Subsystem: "volumeServer",
  196. Name: "total_disk_size",
  197. Help: "Actual disk size used by volumes.",
  198. }, []string{"collection", "type"})
  199. VolumeServerResourceGauge = prometheus.NewGaugeVec(
  200. prometheus.GaugeOpts{
  201. Namespace: Namespace,
  202. Subsystem: "volumeServer",
  203. Name: "resource",
  204. Help: "Resource usage",
  205. }, []string{"name", "type"})
  206. S3RequestCounter = prometheus.NewCounterVec(
  207. prometheus.CounterOpts{
  208. Namespace: Namespace,
  209. Subsystem: "s3",
  210. Name: "request_total",
  211. Help: "Counter of s3 requests.",
  212. }, []string{"type", "code", "bucket"})
  213. S3HandlerCounter = prometheus.NewCounterVec(
  214. prometheus.CounterOpts{
  215. Namespace: Namespace,
  216. Subsystem: "s3",
  217. Name: "handler_total",
  218. Help: "Counter of s3 server handlers.",
  219. }, []string{"type"})
  220. S3RequestHistogram = prometheus.NewHistogramVec(
  221. prometheus.HistogramOpts{
  222. Namespace: Namespace,
  223. Subsystem: "s3",
  224. Name: "request_seconds",
  225. Help: "Bucketed histogram of s3 request processing time.",
  226. Buckets: prometheus.ExponentialBuckets(0.0001, 2, 24),
  227. }, []string{"type", "bucket"})
  228. S3TimeToFirstByteHistogram = prometheus.NewHistogramVec(
  229. prometheus.HistogramOpts{
  230. Namespace: Namespace,
  231. Subsystem: "s3",
  232. Name: "time_to_first_byte_millisecond",
  233. Help: "Bucketed histogram of s3 time to first byte request processing time.",
  234. Buckets: prometheus.ExponentialBuckets(0.001, 2, 27),
  235. }, []string{"type", "bucket"})
  236. )
  237. func init() {
  238. Gather.MustRegister(MasterClientConnectCounter)
  239. Gather.MustRegister(MasterRaftIsleader)
  240. Gather.MustRegister(MasterAdminLock)
  241. Gather.MustRegister(MasterReceivedHeartbeatCounter)
  242. Gather.MustRegister(MasterLeaderChangeCounter)
  243. Gather.MustRegister(MasterReplicaPlacementMismatch)
  244. Gather.MustRegister(MasterVolumeLayout)
  245. Gather.MustRegister(FilerRequestCounter)
  246. Gather.MustRegister(FilerHandlerCounter)
  247. Gather.MustRegister(FilerRequestHistogram)
  248. Gather.MustRegister(FilerStoreCounter)
  249. Gather.MustRegister(FilerStoreHistogram)
  250. Gather.MustRegister(FilerSyncOffsetGauge)
  251. Gather.MustRegister(FilerServerLastSendTsOfSubscribeGauge)
  252. Gather.MustRegister(collectors.NewGoCollector())
  253. Gather.MustRegister(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}))
  254. Gather.MustRegister(VolumeServerRequestCounter)
  255. Gather.MustRegister(VolumeServerHandlerCounter)
  256. Gather.MustRegister(VolumeServerRequestHistogram)
  257. Gather.MustRegister(VolumeServerVacuumingCompactCounter)
  258. Gather.MustRegister(VolumeServerVacuumingCommitCounter)
  259. Gather.MustRegister(VolumeServerVacuumingHistogram)
  260. Gather.MustRegister(VolumeServerVolumeGauge)
  261. Gather.MustRegister(VolumeServerMaxVolumeCounter)
  262. Gather.MustRegister(VolumeServerReadOnlyVolumeGauge)
  263. Gather.MustRegister(VolumeServerDiskSizeGauge)
  264. Gather.MustRegister(VolumeServerResourceGauge)
  265. Gather.MustRegister(S3RequestCounter)
  266. Gather.MustRegister(S3HandlerCounter)
  267. Gather.MustRegister(S3RequestHistogram)
  268. Gather.MustRegister(S3TimeToFirstByteHistogram)
  269. }
  270. func LoopPushingMetric(name, instance, addr string, intervalSeconds int) {
  271. if addr == "" || intervalSeconds == 0 {
  272. return
  273. }
  274. glog.V(0).Infof("%s server sends metrics to %s every %d seconds", name, addr, intervalSeconds)
  275. pusher := push.New(addr, name).Gatherer(Gather).Grouping("instance", instance)
  276. for {
  277. err := pusher.Push()
  278. if err != nil && !strings.HasPrefix(err.Error(), "unexpected status code 200") {
  279. glog.V(0).Infof("could not push metrics to prometheus push gateway %s: %v", addr, err)
  280. }
  281. if intervalSeconds <= 0 {
  282. intervalSeconds = 15
  283. }
  284. time.Sleep(time.Duration(intervalSeconds) * time.Second)
  285. }
  286. }
  287. func JoinHostPort(host string, port int) string {
  288. portStr := strconv.Itoa(port)
  289. if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
  290. return host + ":" + portStr
  291. }
  292. return net.JoinHostPort(host, portStr)
  293. }
  294. func StartMetricsServer(ip string, port int) {
  295. if port == 0 {
  296. return
  297. }
  298. http.Handle("/metrics", promhttp.HandlerFor(Gather, promhttp.HandlerOpts{}))
  299. log.Fatal(http.ListenAndServe(JoinHostPort(ip, port), nil))
  300. }
  301. func SourceName(port uint32) string {
  302. hostname, err := os.Hostname()
  303. if err != nil {
  304. return "unknown"
  305. }
  306. return net.JoinHostPort(hostname, strconv.Itoa(int(port)))
  307. }
  308. // todo - can be changed to DeletePartialMatch when https://github.com/prometheus/client_golang/pull/1013 gets released
  309. func DeleteCollectionMetrics(collection string) {
  310. VolumeServerDiskSizeGauge.DeleteLabelValues(collection, "normal")
  311. for _, volume_type := range readOnlyVolumeTypes {
  312. VolumeServerReadOnlyVolumeGauge.DeleteLabelValues(collection, volume_type)
  313. }
  314. VolumeServerVolumeGauge.DeleteLabelValues(collection, "volume")
  315. }