metrics.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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. MasterVolumeLayoutWritable = prometheus.NewGaugeVec(
  63. prometheus.GaugeOpts{
  64. Namespace: Namespace,
  65. Subsystem: "master",
  66. Name: "volume_layout_writable",
  67. Help: "Number of writable volumes in volume layouts",
  68. }, []string{"collection", "disk", "rp", "ttl"})
  69. MasterVolumeLayoutCrowded = prometheus.NewGaugeVec(
  70. prometheus.GaugeOpts{
  71. Namespace: Namespace,
  72. Subsystem: "master",
  73. Name: "volume_layout_crowded",
  74. Help: "Number of crowded volumes in volume layouts",
  75. }, []string{"collection", "disk", "rp", "ttl"})
  76. MasterPickForWriteErrorCounter = prometheus.NewCounter(
  77. prometheus.CounterOpts{
  78. Namespace: Namespace,
  79. Subsystem: "master",
  80. Name: "pick_for_write_error",
  81. Help: "Counter of master pick for write error",
  82. })
  83. MasterLeaderChangeCounter = prometheus.NewCounterVec(
  84. prometheus.CounterOpts{
  85. Namespace: Namespace,
  86. Subsystem: "master",
  87. Name: "leader_changes",
  88. Help: "Counter of master leader changes.",
  89. }, []string{"type"})
  90. FilerRequestCounter = prometheus.NewCounterVec(
  91. prometheus.CounterOpts{
  92. Namespace: Namespace,
  93. Subsystem: "filer",
  94. Name: "request_total",
  95. Help: "Counter of filer requests.",
  96. }, []string{"type", "code"})
  97. FilerHandlerCounter = prometheus.NewCounterVec(
  98. prometheus.CounterOpts{
  99. Namespace: Namespace,
  100. Subsystem: "filer",
  101. Name: "handler_total",
  102. Help: "Counter of filer handlers.",
  103. }, []string{"type"})
  104. FilerRequestHistogram = prometheus.NewHistogramVec(
  105. prometheus.HistogramOpts{
  106. Namespace: Namespace,
  107. Subsystem: "filer",
  108. Name: "request_seconds",
  109. Help: "Bucketed histogram of filer request processing time.",
  110. Buckets: prometheus.ExponentialBuckets(0.0001, 2, 24),
  111. }, []string{"type"})
  112. FilerServerLastSendTsOfSubscribeGauge = prometheus.NewGaugeVec(
  113. prometheus.GaugeOpts{
  114. Namespace: Namespace,
  115. Subsystem: "filer",
  116. Name: "last_send_timestamp_of_subscribe",
  117. Help: "The last send timestamp of the filer subscription.",
  118. }, []string{"sourceFiler", "clientName", "path"})
  119. FilerStoreCounter = prometheus.NewCounterVec(
  120. prometheus.CounterOpts{
  121. Namespace: Namespace,
  122. Subsystem: "filerStore",
  123. Name: "request_total",
  124. Help: "Counter of filer store requests.",
  125. }, []string{"store", "type"})
  126. FilerStoreHistogram = prometheus.NewHistogramVec(
  127. prometheus.HistogramOpts{
  128. Namespace: Namespace,
  129. Subsystem: "filerStore",
  130. Name: "request_seconds",
  131. Help: "Bucketed histogram of filer store request processing time.",
  132. Buckets: prometheus.ExponentialBuckets(0.0001, 2, 24),
  133. }, []string{"store", "type"})
  134. FilerSyncOffsetGauge = prometheus.NewGaugeVec(
  135. prometheus.GaugeOpts{
  136. Namespace: Namespace,
  137. Subsystem: "filerSync",
  138. Name: "sync_offset",
  139. Help: "The offset of the filer synchronization service.",
  140. }, []string{"sourceFiler", "targetFiler", "clientName", "path"})
  141. VolumeServerRequestCounter = prometheus.NewCounterVec(
  142. prometheus.CounterOpts{
  143. Namespace: Namespace,
  144. Subsystem: "volumeServer",
  145. Name: "request_total",
  146. Help: "Counter of volume server requests.",
  147. }, []string{"type", "code"})
  148. VolumeServerHandlerCounter = prometheus.NewCounterVec(
  149. prometheus.CounterOpts{
  150. Namespace: Namespace,
  151. Subsystem: "volumeServer",
  152. Name: "handler_total",
  153. Help: "Counter of volume server handlers.",
  154. }, []string{"type"})
  155. VolumeServerVacuumingCompactCounter = prometheus.NewCounterVec(
  156. prometheus.CounterOpts{
  157. Namespace: Namespace,
  158. Subsystem: "volumeServer",
  159. Name: "vacuuming_compact_count",
  160. Help: "Counter of volume vacuuming Compact counter",
  161. }, []string{"success"})
  162. VolumeServerVacuumingCommitCounter = prometheus.NewCounterVec(
  163. prometheus.CounterOpts{
  164. Namespace: Namespace,
  165. Subsystem: "volumeServer",
  166. Name: "vacuuming_commit_count",
  167. Help: "Counter of volume vacuuming commit counter",
  168. }, []string{"success"})
  169. VolumeServerVacuumingHistogram = prometheus.NewHistogramVec(
  170. prometheus.HistogramOpts{
  171. Namespace: Namespace,
  172. Subsystem: "volumeServer",
  173. Name: "vacuuming_seconds",
  174. Help: "Bucketed histogram of volume server vacuuming processing time.",
  175. Buckets: prometheus.ExponentialBuckets(0.0001, 2, 24),
  176. }, []string{"type"})
  177. VolumeServerRequestHistogram = prometheus.NewHistogramVec(
  178. prometheus.HistogramOpts{
  179. Namespace: Namespace,
  180. Subsystem: "volumeServer",
  181. Name: "request_seconds",
  182. Help: "Bucketed histogram of volume server request processing time.",
  183. Buckets: prometheus.ExponentialBuckets(0.0001, 2, 24),
  184. }, []string{"type"})
  185. VolumeServerVolumeGauge = prometheus.NewGaugeVec(
  186. prometheus.GaugeOpts{
  187. Namespace: Namespace,
  188. Subsystem: "volumeServer",
  189. Name: "volumes",
  190. Help: "Number of volumes or shards.",
  191. }, []string{"collection", "type"})
  192. VolumeServerReadOnlyVolumeGauge = prometheus.NewGaugeVec(
  193. prometheus.GaugeOpts{
  194. Namespace: Namespace,
  195. Subsystem: "volumeServer",
  196. Name: "read_only_volumes",
  197. Help: "Number of read only volumes.",
  198. }, []string{"collection", "type"})
  199. VolumeServerMaxVolumeCounter = prometheus.NewGauge(
  200. prometheus.GaugeOpts{
  201. Namespace: Namespace,
  202. Subsystem: "volumeServer",
  203. Name: "max_volumes",
  204. Help: "Maximum number of volumes.",
  205. })
  206. VolumeServerDiskSizeGauge = prometheus.NewGaugeVec(
  207. prometheus.GaugeOpts{
  208. Namespace: Namespace,
  209. Subsystem: "volumeServer",
  210. Name: "total_disk_size",
  211. Help: "Actual disk size used by volumes.",
  212. }, []string{"collection", "type"})
  213. VolumeServerResourceGauge = prometheus.NewGaugeVec(
  214. prometheus.GaugeOpts{
  215. Namespace: Namespace,
  216. Subsystem: "volumeServer",
  217. Name: "resource",
  218. Help: "Resource usage",
  219. }, []string{"name", "type"})
  220. S3RequestCounter = prometheus.NewCounterVec(
  221. prometheus.CounterOpts{
  222. Namespace: Namespace,
  223. Subsystem: "s3",
  224. Name: "request_total",
  225. Help: "Counter of s3 requests.",
  226. }, []string{"type", "code", "bucket"})
  227. S3HandlerCounter = prometheus.NewCounterVec(
  228. prometheus.CounterOpts{
  229. Namespace: Namespace,
  230. Subsystem: "s3",
  231. Name: "handler_total",
  232. Help: "Counter of s3 server handlers.",
  233. }, []string{"type"})
  234. S3RequestHistogram = prometheus.NewHistogramVec(
  235. prometheus.HistogramOpts{
  236. Namespace: Namespace,
  237. Subsystem: "s3",
  238. Name: "request_seconds",
  239. Help: "Bucketed histogram of s3 request processing time.",
  240. Buckets: prometheus.ExponentialBuckets(0.0001, 2, 24),
  241. }, []string{"type", "bucket"})
  242. S3TimeToFirstByteHistogram = prometheus.NewHistogramVec(
  243. prometheus.HistogramOpts{
  244. Namespace: Namespace,
  245. Subsystem: "s3",
  246. Name: "time_to_first_byte_millisecond",
  247. Help: "Bucketed histogram of s3 time to first byte request processing time.",
  248. Buckets: prometheus.ExponentialBuckets(0.001, 2, 27),
  249. }, []string{"type", "bucket"})
  250. )
  251. func init() {
  252. Gather.MustRegister(MasterClientConnectCounter)
  253. Gather.MustRegister(MasterRaftIsleader)
  254. Gather.MustRegister(MasterAdminLock)
  255. Gather.MustRegister(MasterReceivedHeartbeatCounter)
  256. Gather.MustRegister(MasterLeaderChangeCounter)
  257. Gather.MustRegister(MasterReplicaPlacementMismatch)
  258. Gather.MustRegister(MasterVolumeLayoutWritable)
  259. Gather.MustRegister(MasterVolumeLayoutCrowded)
  260. Gather.MustRegister(FilerRequestCounter)
  261. Gather.MustRegister(FilerHandlerCounter)
  262. Gather.MustRegister(FilerRequestHistogram)
  263. Gather.MustRegister(FilerStoreCounter)
  264. Gather.MustRegister(FilerStoreHistogram)
  265. Gather.MustRegister(FilerSyncOffsetGauge)
  266. Gather.MustRegister(FilerServerLastSendTsOfSubscribeGauge)
  267. Gather.MustRegister(collectors.NewGoCollector())
  268. Gather.MustRegister(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}))
  269. Gather.MustRegister(VolumeServerRequestCounter)
  270. Gather.MustRegister(VolumeServerHandlerCounter)
  271. Gather.MustRegister(VolumeServerRequestHistogram)
  272. Gather.MustRegister(VolumeServerVacuumingCompactCounter)
  273. Gather.MustRegister(VolumeServerVacuumingCommitCounter)
  274. Gather.MustRegister(VolumeServerVacuumingHistogram)
  275. Gather.MustRegister(VolumeServerVolumeGauge)
  276. Gather.MustRegister(VolumeServerMaxVolumeCounter)
  277. Gather.MustRegister(VolumeServerReadOnlyVolumeGauge)
  278. Gather.MustRegister(VolumeServerDiskSizeGauge)
  279. Gather.MustRegister(VolumeServerResourceGauge)
  280. Gather.MustRegister(S3RequestCounter)
  281. Gather.MustRegister(S3HandlerCounter)
  282. Gather.MustRegister(S3RequestHistogram)
  283. Gather.MustRegister(S3TimeToFirstByteHistogram)
  284. }
  285. func LoopPushingMetric(name, instance, addr string, intervalSeconds int) {
  286. if addr == "" || intervalSeconds == 0 {
  287. return
  288. }
  289. glog.V(0).Infof("%s server sends metrics to %s every %d seconds", name, addr, intervalSeconds)
  290. pusher := push.New(addr, name).Gatherer(Gather).Grouping("instance", instance)
  291. for {
  292. err := pusher.Push()
  293. if err != nil && !strings.HasPrefix(err.Error(), "unexpected status code 200") {
  294. glog.V(0).Infof("could not push metrics to prometheus push gateway %s: %v", addr, err)
  295. }
  296. if intervalSeconds <= 0 {
  297. intervalSeconds = 15
  298. }
  299. time.Sleep(time.Duration(intervalSeconds) * time.Second)
  300. }
  301. }
  302. func JoinHostPort(host string, port int) string {
  303. portStr := strconv.Itoa(port)
  304. if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
  305. return host + ":" + portStr
  306. }
  307. return net.JoinHostPort(host, portStr)
  308. }
  309. func StartMetricsServer(ip string, port int) {
  310. if port == 0 {
  311. return
  312. }
  313. http.Handle("/metrics", promhttp.HandlerFor(Gather, promhttp.HandlerOpts{}))
  314. log.Fatal(http.ListenAndServe(JoinHostPort(ip, port), nil))
  315. }
  316. func SourceName(port uint32) string {
  317. hostname, err := os.Hostname()
  318. if err != nil {
  319. return "unknown"
  320. }
  321. return net.JoinHostPort(hostname, strconv.Itoa(int(port)))
  322. }
  323. // todo - can be changed to DeletePartialMatch when https://github.com/prometheus/client_golang/pull/1013 gets released
  324. func DeleteCollectionMetrics(collection string) {
  325. VolumeServerDiskSizeGauge.DeleteLabelValues(collection, "normal")
  326. for _, volume_type := range readOnlyVolumeTypes {
  327. VolumeServerReadOnlyVolumeGauge.DeleteLabelValues(collection, volume_type)
  328. }
  329. VolumeServerVolumeGauge.DeleteLabelValues(collection, "volume")
  330. }