/
op.go
134 lines (110 loc) · 3.46 KB
/
op.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
132
133
134
package inspect
import (
"fmt"
"strings"
"github.com/gyuho/linux-inspect/top"
)
// EntryOp defines entry option(filter).
type EntryOp struct {
ProgramMatchFunc func(string) bool
program string
PID int64
TopLimit int
// for ss
TCP bool
TCP6 bool
LocalPort int64
RemotePort int64
// for ps
TopExecPath string
TopStream *top.Stream
// for Proc
DiskDevice string
NetworkInterface string
ExtraPath string
}
// OpFunc applies each filter.
type OpFunc func(*EntryOp)
// WithProgramMatch matches command name.
func WithProgramMatch(matchFunc func(string) bool) OpFunc {
return func(op *EntryOp) { op.ProgramMatchFunc = matchFunc }
}
// WithProgram to filter entries by program name.
func WithProgram(name string) OpFunc {
return func(op *EntryOp) {
op.ProgramMatchFunc = func(commandName string) bool {
return strings.HasSuffix(commandName, name)
}
op.program = name
}
}
// WithPID to filter entries by PIDs.
func WithPID(pid int64) OpFunc {
return func(op *EntryOp) { op.PID = pid }
}
// WithTopLimit to filter entries with limit.
func WithTopLimit(limit int) OpFunc {
return func(op *EntryOp) { op.TopLimit = limit }
}
// WithLocalPort to filter entries by local port.
func WithLocalPort(port int64) OpFunc {
return func(op *EntryOp) { op.LocalPort = port }
}
// WithRemotePort to filter entries by remote port.
func WithRemotePort(port int64) OpFunc {
return func(op *EntryOp) { op.RemotePort = port }
}
// WithTCP to filter entries by TCP.
// Can be used with 'WithTCP6'.
func WithTCP() OpFunc {
return func(op *EntryOp) { op.TCP = true }
}
// WithTCP6 to filter entries by TCP6.
// Can be used with 'WithTCP'.
func WithTCP6() OpFunc {
return func(op *EntryOp) { op.TCP6 = true }
}
// WithTopExecPath configures 'top' command path.
func WithTopExecPath(path string) OpFunc {
return func(op *EntryOp) { op.TopExecPath = path }
}
// WithTopStream gets the PSEntry from the 'top' stream.
func WithTopStream(str *top.Stream) OpFunc {
return func(op *EntryOp) { op.TopStream = str }
}
// WithDiskDevice to filter entries by disk device.
func WithDiskDevice(name string) OpFunc {
return func(op *EntryOp) { op.DiskDevice = name }
}
// WithNetworkInterface to filter entries by disk device.
func WithNetworkInterface(name string) OpFunc {
return func(op *EntryOp) { op.NetworkInterface = name }
}
// WithExtraPath to filter entries by disk device.
func WithExtraPath(path string) OpFunc {
return func(op *EntryOp) { op.ExtraPath = path }
}
// applyOpts panics when op.Program != "" && op.PID > 0.
func (op *EntryOp) applyOpts(opts []OpFunc) {
for _, of := range opts {
of(op)
}
if op.DiskDevice != "" || op.NetworkInterface != "" || op.ExtraPath != "" {
if (op.program != "" || op.ProgramMatchFunc != nil) || op.TopLimit > 0 || op.LocalPort > 0 || op.RemotePort > 0 || op.TCP || op.TCP6 {
panic(fmt.Errorf("not-valid Proc fileter; disk device %q or network interface %q or extra path %q", op.DiskDevice, op.NetworkInterface, op.ExtraPath))
}
}
if (op.program != "" || op.ProgramMatchFunc != nil) && op.PID > 0 {
panic(fmt.Errorf("can't filter both by program(%q or %p) and PID(%d)", op.program, op.ProgramMatchFunc, op.PID))
}
if !op.TCP && !op.TCP6 {
// choose both
op.TCP, op.TCP6 = true, true
}
if op.LocalPort > 0 && op.RemotePort > 0 {
panic(fmt.Errorf("can't query by both local(%d) and remote(%d) ports", op.LocalPort, op.RemotePort))
}
if op.TopExecPath == "" {
op.TopExecPath = top.DefaultExecPath
}
}