-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathpprof.go
92 lines (82 loc) · 2.74 KB
/
pprof.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
package pprof
import (
"bytes"
"log"
"os"
"path/filepath"
"runtime"
"runtime/pprof"
"strconv"
"strings"
"time"
"github.com/projectdiscovery/utils/env"
)
const (
PPROFSwitchENV = "PPROF"
MemProfileENV = "MEM_PROFILE_DIR"
CPUProfileENV = "CPU_PROFILE_DIR"
PPROFTimeENV = "PPROF_TIME"
MemProfileRate = "MEM_PROFILE_RATE"
)
func init() {
if env.GetEnvOrDefault(PPROFSwitchENV, 0) == 1 {
startDefaultProfiler()
}
}
func startDefaultProfiler() {
log.Printf("[+] GOOS: %v\n", runtime.GOOS)
log.Printf("[+] GOARCH: %v\n", runtime.GOARCH)
log.Printf("[+] Command: %v\n", strings.Join(os.Args, " "))
log.Println("Available PPROF Config Options:")
log.Printf("%-16v - directory to write memory profiles to\n", MemProfileENV)
log.Printf("%-16v - directory to write cpu profiles to\n", CPUProfileENV)
log.Printf("%-16v - polling time for cpu and memory profiles (with unit ex: 10s)\n", PPROFTimeENV)
log.Printf("%-16v - memory profiling rate (default 4096)\n", MemProfileRate)
memProfilesDir := env.GetEnvOrDefault(MemProfileENV, "memdump")
cpuProfilesDir := env.GetEnvOrDefault(CPUProfileENV, "cpuprofile")
pprofTimeDuration := env.GetEnvOrDefault(PPROFTimeENV, time.Duration(3)*time.Second)
pprofRate := env.GetEnvOrDefault(MemProfileRate, 4096)
_ = os.MkdirAll(memProfilesDir, 0755)
_ = os.MkdirAll(cpuProfilesDir, 0755)
runtime.MemProfileRate = pprofRate
log.Printf("profile: memory profiling enabled (rate %d), %s\n", runtime.MemProfileRate, memProfilesDir)
log.Printf("profile: ticker enabled (rate %s)\n", pprofTimeDuration)
// cpu ticker and profiler
go func() {
ticker := time.NewTicker(pprofTimeDuration)
count := 0
buff := bytes.Buffer{}
log.Printf("profile: cpu profiling enabled (ticker %s)\n", pprofTimeDuration)
for {
err := pprof.StartCPUProfile(&buff)
if err != nil {
log.Fatalf("profile: could not start cpu profile: %s\n", err)
}
<-ticker.C
pprof.StopCPUProfile()
if err := os.WriteFile(filepath.Join(cpuProfilesDir, "cpuprofile-t"+strconv.Itoa(count)+".out"), buff.Bytes(), 0755); err != nil {
log.Fatalf("profile: could not write cpu profile: %s\n", err)
}
buff.Reset()
count++
}
}()
// memory ticker and profiler
go func() {
ticker := time.NewTicker(pprofTimeDuration)
count := 0
log.Printf("profile: memory profiling enabled (ticker %s)\n", pprofTimeDuration)
for {
<-ticker.C
var buff bytes.Buffer
if err := pprof.WriteHeapProfile(&buff); err != nil {
log.Printf("profile: could not write memory profile: %s\n", err)
}
err := os.WriteFile(filepath.ToSlash(filepath.Join(memProfilesDir, "memprofile-t"+strconv.Itoa(count)+".out")), buff.Bytes(), 0755)
if err != nil {
log.Printf("profile: could not write memory profile: %s\n", err)
}
count++
}
}()
}