runtime.go 8.8 KB

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