runtime.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. package metrics
  2. import (
  3. "runtime"
  4. "time"
  5. )
  6. var (
  7. memStats runtime.MemStats
  8. runtimeMetrics struct {
  9. MemStats struct {
  10. Alloc Gauge
  11. BuckHashSys Gauge
  12. DebugGC Gauge
  13. EnableGC Gauge
  14. Frees Gauge
  15. HeapAlloc Gauge
  16. HeapIdle Gauge
  17. HeapInuse Gauge
  18. HeapObjects Gauge
  19. HeapReleased Gauge
  20. HeapSys Gauge
  21. LastGC Gauge
  22. Lookups Gauge
  23. Mallocs Gauge
  24. MCacheInuse Gauge
  25. MCacheSys Gauge
  26. MSpanInuse Gauge
  27. MSpanSys Gauge
  28. NextGC Gauge
  29. NumGC Gauge
  30. GCCPUFraction GaugeFloat64
  31. PauseNs Histogram
  32. PauseTotalNs Gauge
  33. StackInuse Gauge
  34. StackSys Gauge
  35. Sys Gauge
  36. TotalAlloc Gauge
  37. }
  38. NumCgoCall Gauge
  39. NumGoroutine Gauge
  40. ReadMemStats Timer
  41. }
  42. frees uint64
  43. lookups uint64
  44. mallocs uint64
  45. numGC uint32
  46. numCgoCalls int64
  47. )
  48. // Capture new values for the Go runtime statistics exported in
  49. // runtime.MemStats. This is designed to be called as a goroutine.
  50. func CaptureRuntimeMemStats(r Registry, d time.Duration) {
  51. for _ = range time.Tick(d) {
  52. CaptureRuntimeMemStatsOnce(r)
  53. }
  54. }
  55. // Capture new values for the Go runtime statistics exported in
  56. // runtime.MemStats. This is designed to be called in a background
  57. // goroutine. Giving a registry which has not been given to
  58. // RegisterRuntimeMemStats will panic.
  59. //
  60. // Be very careful with this because runtime.ReadMemStats calls the C
  61. // functions runtime·semacquire(&runtime·worldsema) and runtime·stoptheworld()
  62. // and that last one does what it says on the tin.
  63. func CaptureRuntimeMemStatsOnce(r Registry) {
  64. t := time.Now()
  65. runtime.ReadMemStats(&memStats) // This takes 50-200us.
  66. runtimeMetrics.ReadMemStats.UpdateSince(t)
  67. runtimeMetrics.MemStats.Alloc.Update(int64(memStats.Alloc))
  68. runtimeMetrics.MemStats.BuckHashSys.Update(int64(memStats.BuckHashSys))
  69. if memStats.DebugGC {
  70. runtimeMetrics.MemStats.DebugGC.Update(1)
  71. } else {
  72. runtimeMetrics.MemStats.DebugGC.Update(0)
  73. }
  74. if memStats.EnableGC {
  75. runtimeMetrics.MemStats.EnableGC.Update(1)
  76. } else {
  77. runtimeMetrics.MemStats.EnableGC.Update(0)
  78. }
  79. runtimeMetrics.MemStats.Frees.Update(int64(memStats.Frees - frees))
  80. runtimeMetrics.MemStats.HeapAlloc.Update(int64(memStats.HeapAlloc))
  81. runtimeMetrics.MemStats.HeapIdle.Update(int64(memStats.HeapIdle))
  82. runtimeMetrics.MemStats.HeapInuse.Update(int64(memStats.HeapInuse))
  83. runtimeMetrics.MemStats.HeapObjects.Update(int64(memStats.HeapObjects))
  84. runtimeMetrics.MemStats.HeapReleased.Update(int64(memStats.HeapReleased))
  85. runtimeMetrics.MemStats.HeapSys.Update(int64(memStats.HeapSys))
  86. runtimeMetrics.MemStats.LastGC.Update(int64(memStats.LastGC))
  87. runtimeMetrics.MemStats.Lookups.Update(int64(memStats.Lookups - lookups))
  88. runtimeMetrics.MemStats.Mallocs.Update(int64(memStats.Mallocs - mallocs))
  89. runtimeMetrics.MemStats.MCacheInuse.Update(int64(memStats.MCacheInuse))
  90. runtimeMetrics.MemStats.MCacheSys.Update(int64(memStats.MCacheSys))
  91. runtimeMetrics.MemStats.MSpanInuse.Update(int64(memStats.MSpanInuse))
  92. runtimeMetrics.MemStats.MSpanSys.Update(int64(memStats.MSpanSys))
  93. runtimeMetrics.MemStats.NextGC.Update(int64(memStats.NextGC))
  94. runtimeMetrics.MemStats.NumGC.Update(int64(memStats.NumGC - numGC))
  95. runtimeMetrics.MemStats.GCCPUFraction.Update(gcCPUFraction(&memStats))
  96. // <https://code.google.com/p/go/source/browse/src/pkg/runtime/mgc0.c>
  97. i := numGC % uint32(len(memStats.PauseNs))
  98. ii := memStats.NumGC % uint32(len(memStats.PauseNs))
  99. if memStats.NumGC-numGC >= uint32(len(memStats.PauseNs)) {
  100. for i = 0; i < uint32(len(memStats.PauseNs)); i++ {
  101. runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i]))
  102. }
  103. } else {
  104. if i > ii {
  105. for ; i < uint32(len(memStats.PauseNs)); i++ {
  106. runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i]))
  107. }
  108. i = 0
  109. }
  110. for ; i < ii; i++ {
  111. runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i]))
  112. }
  113. }
  114. frees = memStats.Frees
  115. lookups = memStats.Lookups
  116. mallocs = memStats.Mallocs
  117. numGC = memStats.NumGC
  118. runtimeMetrics.MemStats.PauseTotalNs.Update(int64(memStats.PauseTotalNs))
  119. runtimeMetrics.MemStats.StackInuse.Update(int64(memStats.StackInuse))
  120. runtimeMetrics.MemStats.StackSys.Update(int64(memStats.StackSys))
  121. runtimeMetrics.MemStats.Sys.Update(int64(memStats.Sys))
  122. runtimeMetrics.MemStats.TotalAlloc.Update(int64(memStats.TotalAlloc))
  123. currentNumCgoCalls := numCgoCall()
  124. runtimeMetrics.NumCgoCall.Update(currentNumCgoCalls - numCgoCalls)
  125. numCgoCalls = currentNumCgoCalls
  126. runtimeMetrics.NumGoroutine.Update(int64(runtime.NumGoroutine()))
  127. }
  128. // Register runtimeMetrics for the Go runtime statistics exported in runtime and
  129. // specifically runtime.MemStats. The runtimeMetrics are named by their
  130. // fully-qualified Go symbols, i.e. runtime.MemStats.Alloc.
  131. func RegisterRuntimeMemStats(r Registry) {
  132. runtimeMetrics.MemStats.Alloc = NewGauge()
  133. runtimeMetrics.MemStats.BuckHashSys = NewGauge()
  134. runtimeMetrics.MemStats.DebugGC = NewGauge()
  135. runtimeMetrics.MemStats.EnableGC = NewGauge()
  136. runtimeMetrics.MemStats.Frees = NewGauge()
  137. runtimeMetrics.MemStats.HeapAlloc = NewGauge()
  138. runtimeMetrics.MemStats.HeapIdle = NewGauge()
  139. runtimeMetrics.MemStats.HeapInuse = NewGauge()
  140. runtimeMetrics.MemStats.HeapObjects = NewGauge()
  141. runtimeMetrics.MemStats.HeapReleased = NewGauge()
  142. runtimeMetrics.MemStats.HeapSys = NewGauge()
  143. runtimeMetrics.MemStats.LastGC = NewGauge()
  144. runtimeMetrics.MemStats.Lookups = NewGauge()
  145. runtimeMetrics.MemStats.Mallocs = NewGauge()
  146. runtimeMetrics.MemStats.MCacheInuse = NewGauge()
  147. runtimeMetrics.MemStats.MCacheSys = NewGauge()
  148. runtimeMetrics.MemStats.MSpanInuse = NewGauge()
  149. runtimeMetrics.MemStats.MSpanSys = NewGauge()
  150. runtimeMetrics.MemStats.NextGC = NewGauge()
  151. runtimeMetrics.MemStats.NumGC = NewGauge()
  152. runtimeMetrics.MemStats.GCCPUFraction = NewGaugeFloat64()
  153. runtimeMetrics.MemStats.PauseNs = NewHistogram(NewExpDecaySample(1028, 0.015))
  154. runtimeMetrics.MemStats.PauseTotalNs = NewGauge()
  155. runtimeMetrics.MemStats.StackInuse = NewGauge()
  156. runtimeMetrics.MemStats.StackSys = NewGauge()
  157. runtimeMetrics.MemStats.Sys = NewGauge()
  158. runtimeMetrics.MemStats.TotalAlloc = NewGauge()
  159. runtimeMetrics.NumCgoCall = NewGauge()
  160. runtimeMetrics.NumGoroutine = NewGauge()
  161. runtimeMetrics.ReadMemStats = NewTimer()
  162. r.Register("runtime.MemStats.Alloc", runtimeMetrics.MemStats.Alloc)
  163. r.Register("runtime.MemStats.BuckHashSys", runtimeMetrics.MemStats.BuckHashSys)
  164. r.Register("runtime.MemStats.DebugGC", runtimeMetrics.MemStats.DebugGC)
  165. r.Register("runtime.MemStats.EnableGC", runtimeMetrics.MemStats.EnableGC)
  166. r.Register("runtime.MemStats.Frees", runtimeMetrics.MemStats.Frees)
  167. r.Register("runtime.MemStats.HeapAlloc", runtimeMetrics.MemStats.HeapAlloc)
  168. r.Register("runtime.MemStats.HeapIdle", runtimeMetrics.MemStats.HeapIdle)
  169. r.Register("runtime.MemStats.HeapInuse", runtimeMetrics.MemStats.HeapInuse)
  170. r.Register("runtime.MemStats.HeapObjects", runtimeMetrics.MemStats.HeapObjects)
  171. r.Register("runtime.MemStats.HeapReleased", runtimeMetrics.MemStats.HeapReleased)
  172. r.Register("runtime.MemStats.HeapSys", runtimeMetrics.MemStats.HeapSys)
  173. r.Register("runtime.MemStats.LastGC", runtimeMetrics.MemStats.LastGC)
  174. r.Register("runtime.MemStats.Lookups", runtimeMetrics.MemStats.Lookups)
  175. r.Register("runtime.MemStats.Mallocs", runtimeMetrics.MemStats.Mallocs)
  176. r.Register("runtime.MemStats.MCacheInuse", runtimeMetrics.MemStats.MCacheInuse)
  177. r.Register("runtime.MemStats.MCacheSys", runtimeMetrics.MemStats.MCacheSys)
  178. r.Register("runtime.MemStats.MSpanInuse", runtimeMetrics.MemStats.MSpanInuse)
  179. r.Register("runtime.MemStats.MSpanSys", runtimeMetrics.MemStats.MSpanSys)
  180. r.Register("runtime.MemStats.NextGC", runtimeMetrics.MemStats.NextGC)
  181. r.Register("runtime.MemStats.NumGC", runtimeMetrics.MemStats.NumGC)
  182. r.Register("runtime.MemStats.GCCPUFraction", runtimeMetrics.MemStats.GCCPUFraction)
  183. r.Register("runtime.MemStats.PauseNs", runtimeMetrics.MemStats.PauseNs)
  184. r.Register("runtime.MemStats.PauseTotalNs", runtimeMetrics.MemStats.PauseTotalNs)
  185. r.Register("runtime.MemStats.StackInuse", runtimeMetrics.MemStats.StackInuse)
  186. r.Register("runtime.MemStats.StackSys", runtimeMetrics.MemStats.StackSys)
  187. r.Register("runtime.MemStats.Sys", runtimeMetrics.MemStats.Sys)
  188. r.Register("runtime.MemStats.TotalAlloc", runtimeMetrics.MemStats.TotalAlloc)
  189. r.Register("runtime.NumCgoCall", runtimeMetrics.NumCgoCall)
  190. r.Register("runtime.NumGoroutine", runtimeMetrics.NumGoroutine)
  191. r.Register("runtime.ReadMemStats", runtimeMetrics.ReadMemStats)
  192. }