blob: 043ccefab612df20a24bfa80968cd886dfa7c4ca [file] [log] [blame]
Scott Bakered4efab2020-01-13 19:12:25 -08001package 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}