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