/
cli.go
141 lines (123 loc) · 3.44 KB
/
cli.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
135
136
137
138
139
140
141
package oppprof
import (
"errors"
"fmt"
"math"
"strings"
opservice "github.com/ethereum-optimism/optimism/op-service"
openum "github.com/ethereum-optimism/optimism/op-service/enum"
"github.com/ethereum-optimism/optimism/op-service/flags"
"github.com/urfave/cli/v2"
)
const (
EnabledFlagName = "pprof.enabled"
ListenAddrFlagName = "pprof.addr"
PortFlagName = "pprof.port"
ProfileTypeFlagName = "pprof.type"
ProfilePathFlagName = "pprof.path"
defaultListenAddr = "0.0.0.0"
defaultListenPort = 6060
)
var allowedProfileTypes = []profileType{"cpu", "heap", "goroutine", "threadcreate", "block", "mutex", "allocs"}
type profileType string
func (t profileType) String() string {
return string(t)
}
func (t *profileType) Set(value string) error {
if !validProfileType(profileType(value)) {
return fmt.Errorf("unknown profile type: %q", value)
}
*t = profileType(value)
return nil
}
func (t *profileType) Clone() any {
cpy := *t
return &cpy
}
func validProfileType(value profileType) bool {
for _, k := range allowedProfileTypes {
if k == value {
return true
}
}
return false
}
func DefaultCLIConfig() CLIConfig {
return CLIConfig{
ListenEnabled: false,
ListenAddr: defaultListenAddr,
ListenPort: defaultListenPort,
}
}
func CLIFlags(envPrefix string) []cli.Flag {
return CLIFlagsWithCategory(envPrefix, "")
}
func CLIFlagsWithCategory(envPrefix string, category string) []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Name: EnabledFlagName,
Usage: "Enable the pprof server",
EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_ENABLED"),
Category: category,
},
&cli.StringFlag{
Name: ListenAddrFlagName,
Usage: "pprof listening address",
Value: defaultListenAddr, // TODO(CLI-4159): Switch to 127.0.0.1
EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_ADDR"),
Category: category,
},
&cli.IntFlag{
Name: PortFlagName,
Usage: "pprof listening port",
Value: defaultListenPort,
EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_PORT"),
Category: category,
},
&cli.GenericFlag{
Name: ProfilePathFlagName,
Usage: "pprof file path. If it is a directory, the path is {dir}/{profileType}.prof",
Value: new(flags.PathFlag),
EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_PATH"),
Category: category,
},
&cli.GenericFlag{
Name: ProfileTypeFlagName,
Usage: "pprof profile type. One of " + openum.EnumString(allowedProfileTypes),
Value: func() *profileType {
defaultProfType := profileType("")
return &defaultProfType
}(),
EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_TYPE"),
Category: category,
},
}
}
type CLIConfig struct {
ListenEnabled bool
ListenAddr string
ListenPort int
ProfileType profileType
ProfileDir string
ProfileFilename string
}
func (m CLIConfig) Check() error {
if !m.ListenEnabled {
return nil
}
if m.ListenPort < 0 || m.ListenPort > math.MaxUint16 {
return errors.New("invalid pprof port")
}
return nil
}
func ReadCLIConfig(ctx *cli.Context) CLIConfig {
profilePathFlag := ctx.Generic(ProfilePathFlagName).(*flags.PathFlag)
return CLIConfig{
ListenEnabled: ctx.Bool(EnabledFlagName),
ListenAddr: ctx.String(ListenAddrFlagName),
ListenPort: ctx.Int(PortFlagName),
ProfileType: profileType(strings.ToLower(ctx.String(ProfileTypeFlagName))),
ProfileDir: profilePathFlag.Dir(),
ProfileFilename: profilePathFlag.Filename(),
}
}