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