/
sample_session.go
111 lines (97 loc) · 2.53 KB
/
sample_session.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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package zhuge
import (
"bytes"
"runtime"
"runtime/pprof"
"time"
"github.com/pyroscope-io/client/upstream"
)
type SampleSession Session
func NewSampleSession(c SessionConfig) (*SampleSession, error) {
appName, err := mergeTagsWithAppName(c.AppName, c.Tags)
if err != nil {
return nil, err
}
ps := &SampleSession{
upstream: c.Upstream,
appName: appName,
profileTypes: c.ProfilingTypes,
disableGCRuns: c.DisableGCRuns,
sampleRate: c.SampleRate,
uploadRate: c.UploadRate,
stopCh: make(chan struct{}),
logger: c.Logger,
cpuBuf: &bytes.Buffer{},
memBuf: &bytes.Buffer{},
}
return ps, nil
}
func (ps *SampleSession) isCPUEnabled() bool {
for _, t := range ps.profileTypes {
if t == ProfileCPU {
return true
}
}
return false
}
func (ps *SampleSession) isMemEnabled() bool {
for _, t := range ps.profileTypes {
if t == ProfileInuseObjects || t == ProfileAllocObjects || t == ProfileInuseSpace || t == ProfileAllocSpace {
return true
}
}
return false
}
func (ps *SampleSession) SampleNow() {
now := time.Now()
startTime := now.Truncate(ps.uploadRate)
endTime := startTime.Add(ps.uploadRate)
if ps.isCPUEnabled() {
pprof.StartCPUProfile(ps.cpuBuf)
}
time.Sleep(ps.uploadRate)
if ps.isCPUEnabled() {
pprof.StopCPUProfile()
ps.upstream.Upload(&upstream.UploadJob{
Name: ps.appName,
StartTime: startTime,
EndTime: endTime,
SpyName: "gospy",
SampleRate: 100,
Units: "samples",
AggregationType: "sum",
Format: upstream.FormatPprof,
Profile: copyBuf(ps.cpuBuf.Bytes()),
})
ps.cpuBuf.Reset()
}
if ps.isMemEnabled() {
currentGCGeneration := numGC()
// sometimes GC doesn't run within 10 seconds
// in such cases we force a GC run
// users can disable it with disableGCRuns option
if currentGCGeneration == ps.lastGCGeneration && !ps.disableGCRuns {
runtime.GC()
currentGCGeneration = numGC()
}
if currentGCGeneration != ps.lastGCGeneration {
pprof.WriteHeapProfile(ps.memBuf)
curMemBytes := copyBuf(ps.memBuf.Bytes())
ps.memBuf.Reset()
if ps.memPrevBytes != nil {
ps.upstream.Upload(&upstream.UploadJob{
Name: ps.appName,
StartTime: startTime,
EndTime: endTime,
SpyName: "gospy",
SampleRate: 100,
Format: upstream.FormatPprof,
Profile: curMemBytes,
PrevProfile: ps.memPrevBytes,
})
}
ps.memPrevBytes = curMemBytes
ps.lastGCGeneration = currentGCGeneration
}
}
}