1package metrics 2 3import ( 4 "runtime/debug" 5 "time" 6) 7 8var ( 9 debugMetrics struct { 10 GCStats struct { 11 LastGC Gauge 12 NumGC Gauge 13 Pause Histogram 14 //PauseQuantiles Histogram 15 PauseTotal Gauge 16 } 17 ReadGCStats Timer 18 } 19 gcStats debug.GCStats 20) 21 22// Capture new values for the Go garbage collector statistics exported in 23// debug.GCStats. This is designed to be called as a goroutine. 24func CaptureDebugGCStats(r Registry, d time.Duration) { 25 for _ = range time.Tick(d) { 26 CaptureDebugGCStatsOnce(r) 27 } 28} 29 30// Capture new values for the Go garbage collector statistics exported in 31// debug.GCStats. This is designed to be called in a background goroutine. 32// Giving a registry which has not been given to RegisterDebugGCStats will 33// panic. 34// 35// Be careful (but much less so) with this because debug.ReadGCStats calls 36// the C function runtime·lock(runtime·mheap) which, while not a stop-the-world 37// operation, isn't something you want to be doing all the time. 38func CaptureDebugGCStatsOnce(r Registry) { 39 lastGC := gcStats.LastGC 40 t := time.Now() 41 debug.ReadGCStats(&gcStats) 42 debugMetrics.ReadGCStats.UpdateSince(t) 43 44 debugMetrics.GCStats.LastGC.Update(int64(gcStats.LastGC.UnixNano())) 45 debugMetrics.GCStats.NumGC.Update(int64(gcStats.NumGC)) 46 if lastGC != gcStats.LastGC && 0 < len(gcStats.Pause) { 47 debugMetrics.GCStats.Pause.Update(int64(gcStats.Pause[0])) 48 } 49 //debugMetrics.GCStats.PauseQuantiles.Update(gcStats.PauseQuantiles) 50 debugMetrics.GCStats.PauseTotal.Update(int64(gcStats.PauseTotal)) 51} 52 53// Register metrics for the Go garbage collector statistics exported in 54// debug.GCStats. The metrics are named by their fully-qualified Go symbols, 55// i.e. debug.GCStats.PauseTotal. 56func RegisterDebugGCStats(r Registry) { 57 debugMetrics.GCStats.LastGC = NewGauge() 58 debugMetrics.GCStats.NumGC = NewGauge() 59 debugMetrics.GCStats.Pause = NewHistogram(NewExpDecaySample(1028, 0.015)) 60 //debugMetrics.GCStats.PauseQuantiles = NewHistogram(NewExpDecaySample(1028, 0.015)) 61 debugMetrics.GCStats.PauseTotal = NewGauge() 62 debugMetrics.ReadGCStats = NewTimer() 63 64 r.Register("debug.GCStats.LastGC", debugMetrics.GCStats.LastGC) 65 r.Register("debug.GCStats.NumGC", debugMetrics.GCStats.NumGC) 66 r.Register("debug.GCStats.Pause", debugMetrics.GCStats.Pause) 67 //r.Register("debug.GCStats.PauseQuantiles", debugMetrics.GCStats.PauseQuantiles) 68 r.Register("debug.GCStats.PauseTotal", debugMetrics.GCStats.PauseTotal) 69 r.Register("debug.ReadGCStats", debugMetrics.ReadGCStats) 70} 71 72// Allocate an initial slice for gcStats.Pause to avoid allocations during 73// normal operation. 74func init() { 75 gcStats.Pause = make([]time.Duration, 11) 76} 77