go_collector.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. package prometheus
  2. import (
  3. "fmt"
  4. "runtime"
  5. "runtime/debug"
  6. "time"
  7. )
  8. type goCollector struct {
  9. goroutinesDesc *Desc
  10. threadsDesc *Desc
  11. gcDesc *Desc
  12. goInfoDesc *Desc
  13. // metrics to describe and collect
  14. metrics memStatsMetrics
  15. }
  16. // NewGoCollector returns a collector which exports metrics about the current
  17. // go process.
  18. func NewGoCollector() Collector {
  19. return &goCollector{
  20. goroutinesDesc: NewDesc(
  21. "go_goroutines",
  22. "Number of goroutines that currently exist.",
  23. nil, nil),
  24. threadsDesc: NewDesc(
  25. "go_threads",
  26. "Number of OS threads created.",
  27. nil, nil),
  28. gcDesc: NewDesc(
  29. "go_gc_duration_seconds",
  30. "A summary of the GC invocation durations.",
  31. nil, nil),
  32. goInfoDesc: NewDesc(
  33. "go_info",
  34. "Information about the Go environment.",
  35. nil, Labels{"version": runtime.Version()}),
  36. metrics: memStatsMetrics{
  37. {
  38. desc: NewDesc(
  39. memstatNamespace("alloc_bytes"),
  40. "Number of bytes allocated and still in use.",
  41. nil, nil,
  42. ),
  43. eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) },
  44. valType: GaugeValue,
  45. }, {
  46. desc: NewDesc(
  47. memstatNamespace("alloc_bytes_total"),
  48. "Total number of bytes allocated, even if freed.",
  49. nil, nil,
  50. ),
  51. eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) },
  52. valType: CounterValue,
  53. }, {
  54. desc: NewDesc(
  55. memstatNamespace("sys_bytes"),
  56. "Number of bytes obtained from system.",
  57. nil, nil,
  58. ),
  59. eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) },
  60. valType: GaugeValue,
  61. }, {
  62. desc: NewDesc(
  63. memstatNamespace("lookups_total"),
  64. "Total number of pointer lookups.",
  65. nil, nil,
  66. ),
  67. eval: func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) },
  68. valType: CounterValue,
  69. }, {
  70. desc: NewDesc(
  71. memstatNamespace("mallocs_total"),
  72. "Total number of mallocs.",
  73. nil, nil,
  74. ),
  75. eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) },
  76. valType: CounterValue,
  77. }, {
  78. desc: NewDesc(
  79. memstatNamespace("frees_total"),
  80. "Total number of frees.",
  81. nil, nil,
  82. ),
  83. eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) },
  84. valType: CounterValue,
  85. }, {
  86. desc: NewDesc(
  87. memstatNamespace("heap_alloc_bytes"),
  88. "Number of heap bytes allocated and still in use.",
  89. nil, nil,
  90. ),
  91. eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) },
  92. valType: GaugeValue,
  93. }, {
  94. desc: NewDesc(
  95. memstatNamespace("heap_sys_bytes"),
  96. "Number of heap bytes obtained from system.",
  97. nil, nil,
  98. ),
  99. eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) },
  100. valType: GaugeValue,
  101. }, {
  102. desc: NewDesc(
  103. memstatNamespace("heap_idle_bytes"),
  104. "Number of heap bytes waiting to be used.",
  105. nil, nil,
  106. ),
  107. eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) },
  108. valType: GaugeValue,
  109. }, {
  110. desc: NewDesc(
  111. memstatNamespace("heap_inuse_bytes"),
  112. "Number of heap bytes that are in use.",
  113. nil, nil,
  114. ),
  115. eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) },
  116. valType: GaugeValue,
  117. }, {
  118. desc: NewDesc(
  119. memstatNamespace("heap_released_bytes"),
  120. "Number of heap bytes released to OS.",
  121. nil, nil,
  122. ),
  123. eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) },
  124. valType: GaugeValue,
  125. }, {
  126. desc: NewDesc(
  127. memstatNamespace("heap_objects"),
  128. "Number of allocated objects.",
  129. nil, nil,
  130. ),
  131. eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) },
  132. valType: GaugeValue,
  133. }, {
  134. desc: NewDesc(
  135. memstatNamespace("stack_inuse_bytes"),
  136. "Number of bytes in use by the stack allocator.",
  137. nil, nil,
  138. ),
  139. eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) },
  140. valType: GaugeValue,
  141. }, {
  142. desc: NewDesc(
  143. memstatNamespace("stack_sys_bytes"),
  144. "Number of bytes obtained from system for stack allocator.",
  145. nil, nil,
  146. ),
  147. eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) },
  148. valType: GaugeValue,
  149. }, {
  150. desc: NewDesc(
  151. memstatNamespace("mspan_inuse_bytes"),
  152. "Number of bytes in use by mspan structures.",
  153. nil, nil,
  154. ),
  155. eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) },
  156. valType: GaugeValue,
  157. }, {
  158. desc: NewDesc(
  159. memstatNamespace("mspan_sys_bytes"),
  160. "Number of bytes used for mspan structures obtained from system.",
  161. nil, nil,
  162. ),
  163. eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) },
  164. valType: GaugeValue,
  165. }, {
  166. desc: NewDesc(
  167. memstatNamespace("mcache_inuse_bytes"),
  168. "Number of bytes in use by mcache structures.",
  169. nil, nil,
  170. ),
  171. eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) },
  172. valType: GaugeValue,
  173. }, {
  174. desc: NewDesc(
  175. memstatNamespace("mcache_sys_bytes"),
  176. "Number of bytes used for mcache structures obtained from system.",
  177. nil, nil,
  178. ),
  179. eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) },
  180. valType: GaugeValue,
  181. }, {
  182. desc: NewDesc(
  183. memstatNamespace("buck_hash_sys_bytes"),
  184. "Number of bytes used by the profiling bucket hash table.",
  185. nil, nil,
  186. ),
  187. eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) },
  188. valType: GaugeValue,
  189. }, {
  190. desc: NewDesc(
  191. memstatNamespace("gc_sys_bytes"),
  192. "Number of bytes used for garbage collection system metadata.",
  193. nil, nil,
  194. ),
  195. eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) },
  196. valType: GaugeValue,
  197. }, {
  198. desc: NewDesc(
  199. memstatNamespace("other_sys_bytes"),
  200. "Number of bytes used for other system allocations.",
  201. nil, nil,
  202. ),
  203. eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) },
  204. valType: GaugeValue,
  205. }, {
  206. desc: NewDesc(
  207. memstatNamespace("next_gc_bytes"),
  208. "Number of heap bytes when next garbage collection will take place.",
  209. nil, nil,
  210. ),
  211. eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) },
  212. valType: GaugeValue,
  213. }, {
  214. desc: NewDesc(
  215. memstatNamespace("last_gc_time_seconds"),
  216. "Number of seconds since 1970 of last garbage collection.",
  217. nil, nil,
  218. ),
  219. eval: func(ms *runtime.MemStats) float64 { return float64(ms.LastGC) / 1e9 },
  220. valType: GaugeValue,
  221. }, {
  222. desc: NewDesc(
  223. memstatNamespace("gc_cpu_fraction"),
  224. "The fraction of this program's available CPU time used by the GC since the program started.",
  225. nil, nil,
  226. ),
  227. eval: func(ms *runtime.MemStats) float64 { return ms.GCCPUFraction },
  228. valType: GaugeValue,
  229. },
  230. },
  231. }
  232. }
  233. func memstatNamespace(s string) string {
  234. return fmt.Sprintf("go_memstats_%s", s)
  235. }
  236. // Describe returns all descriptions of the collector.
  237. func (c *goCollector) Describe(ch chan<- *Desc) {
  238. ch <- c.goroutinesDesc
  239. ch <- c.threadsDesc
  240. ch <- c.gcDesc
  241. ch <- c.goInfoDesc
  242. for _, i := range c.metrics {
  243. ch <- i.desc
  244. }
  245. }
  246. // Collect returns the current state of all metrics of the collector.
  247. func (c *goCollector) Collect(ch chan<- Metric) {
  248. ch <- MustNewConstMetric(c.goroutinesDesc, GaugeValue, float64(runtime.NumGoroutine()))
  249. n, _ := runtime.ThreadCreateProfile(nil)
  250. ch <- MustNewConstMetric(c.threadsDesc, GaugeValue, float64(n))
  251. var stats debug.GCStats
  252. stats.PauseQuantiles = make([]time.Duration, 5)
  253. debug.ReadGCStats(&stats)
  254. quantiles := make(map[float64]float64)
  255. for idx, pq := range stats.PauseQuantiles[1:] {
  256. quantiles[float64(idx+1)/float64(len(stats.PauseQuantiles)-1)] = pq.Seconds()
  257. }
  258. quantiles[0.0] = stats.PauseQuantiles[0].Seconds()
  259. ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles)
  260. ch <- MustNewConstMetric(c.goInfoDesc, GaugeValue, 1)
  261. ms := &runtime.MemStats{}
  262. runtime.ReadMemStats(ms)
  263. for _, i := range c.metrics {
  264. ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms))
  265. }
  266. }
  267. // memStatsMetrics provide description, value, and value type for memstat metrics.
  268. type memStatsMetrics []struct {
  269. desc *Desc
  270. eval func(*runtime.MemStats) float64
  271. valType ValueType
  272. }