-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtracer_linux_test.go
131 lines (112 loc) · 3.59 KB
/
tracer_linux_test.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package exectrace
import (
"os"
"os/exec"
"testing"
"github.com/DataDog/ebpfbench"
"github.com/stretchr/testify/require"
"github.com/coder/exectrace"
)
func BenchmarkExectraceBase(b *testing.B) {
// This test must be run as root so we can start exectrace.
if os.Geteuid() != 0 {
b.Fatal("must be run as root")
}
// Start tracer.
tracer, err := exectrace.New(&exectrace.TracerOpts{
LogFn: func(uid, gid, pid uint32, logLine string) {
b.Errorf("tracer error log (uid=%v, gid=%v, pid=%v): %s", uid, gid, pid, logLine)
},
})
require.NoError(b, err)
defer tracer.Close()
eb := ebpfbench.NewEBPFBenchmark(b)
defer eb.Close()
eb.ProfileProgram(tracer.FD(), "enter_execve")
eb.Run(func(b *testing.B) {
// NOTE: the actual iteration count in the final logs might be higher
// than b.N because the program runs on every execve syscall (even ones
// that don't originate from the benchmarked code).
//
// ebpfbench will still report the correct number of iterations and the
// average time per iteration.
for i := 0; i < b.N; i++ {
cmd := exec.Command("true")
err := cmd.Run()
require.NoError(b, err)
_, err = tracer.Read()
require.NoError(b, err)
// Can't verify the process here because we are not filtering and
// other processes on the system will cause any checks to fail.
}
})
}
// NOTE: you should probably run this benchmark with ./bench.sh or `make bench`.
func BenchmarkExectracePIDNSFilter(b *testing.B) {
// This test must be run as root so we can start exectrace.
if os.Geteuid() != 0 {
b.Fatal("must be run as root")
}
pidNS, err := exectrace.GetPidNS()
require.NoError(b, err)
// Start tracer.
tracer, err := exectrace.New(&exectrace.TracerOpts{
PidNS: pidNS,
LogFn: func(uid, gid, pid uint32, logLine string) {
b.Errorf("tracer error log (uid=%v, gid=%v, pid=%v): %s", uid, gid, pid, logLine)
},
})
require.NoError(b, err)
defer tracer.Close()
eb := ebpfbench.NewEBPFBenchmark(b)
defer eb.Close()
eb.ProfileProgram(tracer.FD(), "enter_execve")
eb.Run(func(b *testing.B) {
// NOTE: iteration count can end up higher than b.N, see above.
//
// Because filtered events take less time to process in the kernel, this
// does impact the benchmark results. The average time per iteration
// reported will be lower than it should be. If you run with a high
// iteration count the effect should be mostly invisible, however.
for i := 0; i < b.N; i++ {
cmd := exec.Command("true")
err := cmd.Run()
require.NoError(b, err)
event, err := tracer.Read()
require.NoError(b, err)
require.Equal(b, "true", event.Argv[0])
}
})
}
func BenchmarkExectracePIDNSFilterNoHit(b *testing.B) {
// This test must be run as root so we can start exectrace.
if os.Geteuid() != 0 {
b.Fatal("must be run as root")
}
pidNS, err := exectrace.GetPidNS()
require.NoError(b, err)
// Start tracer.
tracer, err := exectrace.New(&exectrace.TracerOpts{
// Use a nonsense PID NS so we don't match any processes.
PidNS: pidNS + 1,
LogFn: func(uid, gid, pid uint32, logLine string) {
b.Errorf("tracer error log (uid=%v, gid=%v, pid=%v): %s", uid, gid, pid, logLine)
},
})
require.NoError(b, err)
defer tracer.Close()
eb := ebpfbench.NewEBPFBenchmark(b)
defer eb.Close()
eb.ProfileProgram(tracer.FD(), "enter_execve")
eb.Run(func(b *testing.B) {
// NOTE: iteration count can end up higher than b.N, see above.
//
// Since every event is a no hit because the filter doesn't match
// anything, results should not be impacted.
for i := 0; i < b.N; i++ {
cmd := exec.Command("true")
err := cmd.Run()
require.NoError(b, err)
}
})
}