/
gc.go
72 lines (59 loc) · 1.81 KB
/
gc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package gonr
import (
"runtime/debug"
"time"
"github.com/neocortical/newrelic"
"github.com/neocortical/nrmetrics"
metrics "github.com/rcrowley/go-metrics"
)
var gcStats debug.GCStats
func addGCMetrics(p *newrelic.Plugin) {
numGC := metrics.NewMeter()
pauseDur := metrics.NewMeter()
pauseTime := metrics.NewHistogram(metrics.NewExpDecaySample(10000, 0.015))
gcr := &gcReader{
sampleRate: time.Second * 10,
numGC: numGC,
pauseDur: pauseDur,
pauseTime: pauseTime,
}
gcr.Run()
nrmetrics.AddMeterMetric(p, numGC, nrmetrics.MetricConfig{Name: "GC/GC Pauses Per Second", Unit: "pauses", Rate1: true, Rate5: true, Rate15: true})
nrmetrics.AddMeterMetric(p, pauseDur, nrmetrics.MetricConfig{Name: "GC/GC Pause Time Per Second", Unit: "nanoseconds", Rate1: true, Rate5: true, Rate15: true})
nrmetrics.AddHistogramMetric(p, pauseTime, nrmetrics.MetricConfig{
Name: "GC/GC Time Per Pause",
Unit: "pauses",
Duration: time.Microsecond,
Mean: true,
Percentiles: []float64{0.5, 0.75, 0.9, 0.99, 0.999},
})
}
type gcReader struct {
sampleRate time.Duration
lastGC time.Time
lastNumGC int64
numGC metrics.Meter
lastPauseTotal time.Duration
pauseDur metrics.Meter
pauseTime metrics.Histogram
}
func (gcr *gcReader) Run() {
go gcr.run()
}
func (gcr *gcReader) run() {
ticks := time.Tick(gcr.sampleRate)
for _ = range ticks {
gcr.updateMetrics()
}
}
func (gcr *gcReader) updateMetrics() {
debug.ReadGCStats(&gcStats)
gcr.numGC.Mark(gcStats.NumGC - gcr.lastNumGC)
gcr.lastNumGC = gcStats.NumGC
gcr.pauseDur.Mark(int64(gcStats.PauseTotal - gcr.lastPauseTotal))
gcr.lastPauseTotal = gcStats.PauseTotal
if gcr.lastGC != gcStats.LastGC && 0 < len(gcStats.Pause) {
gcr.pauseTime.Update(int64(gcStats.Pause[0]))
}
gcr.lastGC = gcStats.LastGC
}