-
Notifications
You must be signed in to change notification settings - Fork 12
/
config.go
159 lines (143 loc) · 4.4 KB
/
config.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License 2.0;
// you may not use this file except in compliance with the Elastic License 2.0.
// Package loadgencfg contains configuration related code for load generator.
package loadgencfg
import (
"flag"
"fmt"
"net/url"
"os"
"strconv"
"strings"
"time"
)
var Config struct {
ServerURL *url.URL
SecretToken string
APIKey string
Secure bool
EventRate RateFlag
IgnoreErrors bool
RewriteIDs bool
RewriteTimestamps bool
RewriteServiceNames bool
RewriteServiceNodeNames bool
RewriteServiceTargetNames bool
RewriteSpanNames bool
RewriteTransactionNames bool
RewriteTransactionTypes bool
Headers map[string]string
}
type RateFlag struct {
Burst int
Interval time.Duration
}
func (f *RateFlag) String() string {
return fmt.Sprintf("%d/%s", f.Burst, f.Interval)
}
func (f *RateFlag) Set(s string) error {
before, after, ok := strings.Cut(s, "/")
if !ok || before == "" || after == "" {
return fmt.Errorf("invalid rate %q, expected format burst/duration", s)
}
burst, err := strconv.Atoi(before)
if err != nil {
return fmt.Errorf("invalid burst %s in event rate: %w", before, err)
}
if !(after[0] >= '0' && after[0] <= '9') {
after = "1" + after
}
interval, err := time.ParseDuration(after)
if err != nil {
return fmt.Errorf("invalid interval %q in event rate: %w", after, err)
}
if interval <= 0 {
return fmt.Errorf("invalid interval %q, must be positive", after)
}
f.Burst = burst
f.Interval = interval
return nil
}
func init() {
// Server config
flag.Func(
"server",
"server URL (default http://127.0.0.1:8200)",
func(server string) (err error) {
if server != "" {
Config.ServerURL, err = url.Parse(server)
}
return
})
flag.StringVar(&Config.SecretToken, "secret-token", "", "secret token for APM Server")
flag.StringVar(&Config.APIKey, "api-key", "", "API key for APM Server")
flag.BoolVar(&Config.Secure, "secure", false, "validate the remote server TLS certificates")
flag.BoolVar(
&Config.RewriteTimestamps,
"rewrite-timestamps",
true,
"rewrite event timestamps every iteration, maintaining relative offsets",
)
flag.BoolVar(
&Config.RewriteIDs,
"rewrite-ids",
true,
"rewrite event IDs every iteration, maintaining event relationships",
)
flag.Func("header",
"extra headers to use when sending data to the server",
func(s string) error {
k, v, ok := strings.Cut(s, "=")
if !ok {
return fmt.Errorf("invalid header '%s': format must be key=value", s)
}
if len(Config.Headers) == 0 {
Config.Headers = make(map[string]string)
}
Config.Headers[k] = v
return nil
},
)
flag.Var(&Config.EventRate, "event-rate", "Event rate in format of {burst}/{interval}. For example, 200/5s, <= 0 values evaluate to Inf (default 0/s)")
flag.BoolVar(&Config.IgnoreErrors, "ignore-errors", false, "Ignore HTTP errors while sending events")
rewriteNames := map[string]*bool{
"service.name": &Config.RewriteServiceNames,
"service.node.name": &Config.RewriteServiceNodeNames,
"service.target.name": &Config.RewriteServiceTargetNames,
"span.name": &Config.RewriteSpanNames,
"transaction.name": &Config.RewriteTransactionNames,
"transaction.type": &Config.RewriteTransactionTypes,
}
for field, config := range rewriteNames {
flag.BoolVar(
config,
fmt.Sprintf("rewrite-%ss", strings.Replace(field, ".", "-", -1)),
false,
fmt.Sprintf("replace `%s` in events", field),
)
}
// For configs that can be set via environment variables, set the required
// flags from env if they are not explicitly provided via command line
setFlagsFromEnv()
}
func setFlagsFromEnv() {
// value[0] is environment key
// value[1] is default value
flagEnvMap := map[string][]string{
"server": {"ELASTIC_APM_SERVER_URL", "http://127.0.0.1:8200"},
"secret-token": {"ELASTIC_APM_SECRET_TOKEN", ""},
"api-key": {"ELASTIC_APM_API_KEY", ""},
"secure": {"ELASTIC_APM_VERIFY_SERVER_CERT", "false"},
}
for k, v := range flagEnvMap {
flag.Set(k, getEnvOrDefault(v[0], v[1]))
}
}
func getEnvOrDefault(name, defaultValue string) string {
value := os.Getenv(name)
if value != "" {
return value
}
return defaultValue
}