-
Notifications
You must be signed in to change notification settings - Fork 53
/
options.go
382 lines (313 loc) · 12.9 KB
/
options.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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
package lightstep
import (
"fmt"
"math"
"math/rand"
"os"
"path"
"strings"
"time" // N.B.(jmacd): Do not use google.golang.org/glog in this package.
"github.com/lightstep/lightstep-tracer-go/constants"
"github.com/opentracing/opentracing-go"
"google.golang.org/grpc"
)
// Default Option values.
const (
DefaultCollectorPath = "/_rpc/v1/reports/binary"
DefaultPlainPort = 80
DefaultSecurePort = 443
DefaultGRPCCollectorHost = "collector-grpc.lightstep.com"
DefaultSystemMetricsHost = "ingest.lightstep.com"
DefaultSystemMetricsMeasurementFrequency = 30 * time.Second
DefaultSystemMetricsTimeout = 5 * time.Second
DefaultMaxReportingPeriod = 2500 * time.Millisecond
DefaultMinReportingPeriod = 500 * time.Millisecond
DefaultMaxSpans = 1000
DefaultReportTimeout = 30 * time.Second
DefaultReconnectPeriod = 5 * time.Minute
DefaultMaxLogKeyLen = 256
DefaultMaxLogValueLen = 1024
DefaultMaxLogsPerSpan = 500
DefaultGRPCMaxCallSendMsgSizeBytes = math.MaxInt32
)
// Tag and Tracer Attribute keys.
const (
ParentSpanGUIDKey = "parent_span_guid" // ParentSpanGUIDKey is the tag key used to record the relationship between child and parent spans.
ComponentNameKey = constants.ComponentNameKey // NOTE: these will be deprecated in favour of the constants package
GUIDKey = "lightstep.guid" // <- runtime guid, not span guid
HostnameKey = constants.HostnameKey // NOTE: these will be deprecated in favour of the constants package
CommandLineKey = "lightstep.command_line"
ServiceVersionKey = constants.ServiceVersionKey // NOTE: these will be deprecated in favour of the constants package
TracerPlatformKey = "lightstep.tracer_platform"
TracerPlatformValue = "go"
TracerPlatformVersionKey = "lightstep.tracer_platform_version"
TracerVersionKey = "lightstep.tracer_version" // Note: TracerVersionValue is generated from ./VERSION
)
const (
secureScheme = "https"
plaintextScheme = "http"
)
// Validation Errors
var (
errInvalidGUIDKey = fmt.Errorf("Options invalid: setting the %v tag is no longer supported", GUIDKey)
)
// A SpanRecorder handles all of the `RawSpan` data generated via an
// associated `Tracer` instance.
type SpanRecorder interface {
RecordSpan(RawSpan)
}
// Endpoint describes a collector or web API host/port and whether or
// not to use plaintext communication.
type Endpoint struct {
Scheme string `yaml:"scheme" json:"scheme" usage:"scheme to use for the endpoint, defaults to appropriate one if no custom one is required"`
Host string `yaml:"host" json:"host" usage:"host on which the endpoint is running"`
Port int `yaml:"port" json:"port" usage:"port on which the endpoint is listening"`
Plaintext bool `yaml:"plaintext" json:"plaintext" usage:"whether or not to encrypt data send to the endpoint"`
CustomCACertFile string `yaml:"custom_ca_cert_file" json:"custom_ca_cert_file" usage:"path to a custom CA cert file, defaults to system defined certs if omitted"`
}
// HostPort use SocketAddress instead.
// DEPRECATED
func (e Endpoint) HostPort() string {
return e.SocketAddress()
}
// SocketAddress returns an address suitable for dialing grpc connections
func (e Endpoint) SocketAddress() string {
return fmt.Sprintf("%s:%d", e.Host, e.Port)
}
// URL returns an address suitable for dialing http connections
func (e Endpoint) URL() string {
return fmt.Sprintf("%s%s", e.urlWithoutPath(), DefaultCollectorPath)
}
// urlWithoutPath returns an address suitable for grpc connections if a custom scheme is provided
func (e Endpoint) urlWithoutPath() string {
return fmt.Sprintf("%s://%s", e.scheme(), e.SocketAddress())
}
func (e Endpoint) scheme() string {
if len(e.Scheme) > 0 {
return e.Scheme
}
if e.Plaintext {
return plaintextScheme
}
return secureScheme
}
type SystemMetricsOptions struct {
Disabled bool `yaml:"disabled"`
Endpoint Endpoint `yaml:"endpoint"`
MeasurementFrequency time.Duration `yaml:"measurement_frequency"`
Timeout time.Duration `yaml:"timeout"`
}
// Options control how the LightStep Tracer behaves.
type Options struct {
// AccessToken is the unique API key for your LightStep project. It is
// available on your account page at https://app.lightstep.com/account
AccessToken string `yaml:"access_token" usage:"access token for reporting to LightStep"`
// Collector is the host, port, and plaintext option to use
// for the collector.
Collector Endpoint `yaml:"collector"`
// Tags are arbitrary key-value pairs that apply to all spans generated by
// this Tracer.
Tags opentracing.Tags
// LightStep is the host, port, and plaintext option to use
// for the LightStep web API.
LightStepAPI Endpoint `yaml:"lightstep_api"`
// MaxBufferedSpans is the maximum number of spans that will be buffered
// before sending them to a collector.
MaxBufferedSpans int `yaml:"max_buffered_spans"`
// MaxLogKeyLen is the maximum allowable size (in characters) of an
// OpenTracing logging key. Longer keys are truncated.
MaxLogKeyLen int `yaml:"max_log_key_len"`
// MaxLogValueLen is the maximum allowable size (in characters) of an
// OpenTracing logging value. Longer values are truncated. Only applies to
// variable-length value types (strings, interface{}, etc).
MaxLogValueLen int `yaml:"max_log_value_len"`
// MaxLogsPerSpan limits the number of logs in a single span.
MaxLogsPerSpan int `yaml:"max_logs_per_span"`
// GRPCMaxCallSendMsgSizeBytes limits the size in bytes of grpc messages
// sent by a client.
GRPCMaxCallSendMsgSizeBytes int `yaml:"grpc_max_call_send_msg_size_bytes"`
// ReportingPeriod is the maximum duration of time between sending spans
// to a collector. If zero, the default will be used.
ReportingPeriod time.Duration `yaml:"reporting_period"`
// MinReportingPeriod is the minimum duration of time between sending spans
// to a collector. If zero, the default will be used. It is strongly
// recommended to use the default.
MinReportingPeriod time.Duration `yaml:"min_reporting_period"`
ReportTimeout time.Duration `yaml:"report_timeout"`
// DropSpanLogs turns log events on all Spans into no-ops.
DropSpanLogs bool `yaml:"drop_span_logs"`
// DEPRECATED: The LightStep library prints the first error to stdout by default.
// See the documentation on the SetGlobalEventHandler function for guidance on
// how to integrate tracer diagnostics with your application's logging and
// metrics systems.
Verbose bool `yaml:"verbose"`
// Force the use of a specific transport protocol. If multiple are set to true,
// the following order is used to select for the first option: http, grpc.
// If none are set to true, HTTP is defaulted to.
UseHttp bool `yaml:"use_http"`
UseGRPC bool `yaml:"usegrpc"`
// Propagators allow inject/extract to use custom propagators for different formats. This
// package includes a `B3Propagator` that supports B3 headers on text maps and http headers.
// Defaults:
// opentracing.HTTPHeaders: LightStepPropagator
// opentracing.TextMap: LightStepPropagator,
// opentracing.Binary: LightStepPropagator
Propagators map[opentracing.BuiltinFormat]Propagator `yaml:"-"`
// CustomCollector allows customizing the Protobuf transport.
// This is an advanced feature that avoids reconnect logic.
CustomCollector Collector `yaml:"-" json:"-"`
ReconnectPeriod time.Duration `yaml:"reconnect_period"`
// DialOptions allows customizing the grpc dial options passed to the grpc.Dial(...) call.
// This is an advanced feature added to allow for a custom balancer or middleware.
// It can be safely ignored if you have no custom dialing requirements.
// If UseGRPC is not set, these dial options are ignored.
DialOptions []grpc.DialOption `yaml:"-" json:"-"`
// A hook for receiving finished span events
Recorder SpanRecorder `yaml:"-" json:"-"`
// For testing purposes only
ConnFactory ConnectorFactory `yaml:"-" json:"-"`
// Enable LightStep Meta Event Logging
MetaEventReportingEnabled bool `yaml:"meta_event_reporting_enabled" json:"meta_event_reporting_enabled"`
SystemMetrics SystemMetricsOptions `yaml:"system_metrics"`
}
// Initialize validates options, and sets default values for unset options.
// This is called automatically when creating a new Tracer.
func (opts *Options) Initialize() error {
err := opts.Validate()
if err != nil {
return err
}
// Note: opts is a copy of the user's data, ok to modify.
if opts.MaxBufferedSpans == 0 {
opts.MaxBufferedSpans = DefaultMaxSpans
}
if opts.MaxLogKeyLen == 0 {
opts.MaxLogKeyLen = DefaultMaxLogKeyLen
}
if opts.MaxLogValueLen == 0 {
opts.MaxLogValueLen = DefaultMaxLogValueLen
}
if opts.MaxLogsPerSpan == 0 {
opts.MaxLogsPerSpan = DefaultMaxLogsPerSpan
}
if opts.GRPCMaxCallSendMsgSizeBytes == 0 {
opts.GRPCMaxCallSendMsgSizeBytes = DefaultGRPCMaxCallSendMsgSizeBytes
}
if opts.ReportingPeriod == 0 {
opts.ReportingPeriod = DefaultMaxReportingPeriod
}
if opts.MinReportingPeriod == 0 {
opts.MinReportingPeriod = DefaultMinReportingPeriod
}
if opts.ReportTimeout == 0 {
opts.ReportTimeout = DefaultReportTimeout
}
if opts.ReconnectPeriod == 0 {
opts.ReconnectPeriod = DefaultReconnectPeriod
}
if opts.Tags == nil {
opts.Tags = map[string]interface{}{}
}
// Set some default attributes if not found in options
if _, found := opts.Tags[constants.ComponentNameKey]; !found {
// If not found, use the first command line argument as the default service name
defaultService := path.Base(os.Args[0])
emitEvent(newEventMissingService(defaultService))
opts.Tags[constants.ComponentNameKey] = defaultService
}
if _, found := opts.Tags[constants.HostnameKey]; !found {
hostname, _ := os.Hostname()
opts.Tags[constants.HostnameKey] = hostname
}
if _, found := opts.Tags[CommandLineKey]; !found {
opts.Tags[CommandLineKey] = strings.Join(os.Args, " ")
}
opts.ReconnectPeriod = time.Duration(float64(opts.ReconnectPeriod) * (1 + 0.2*rand.Float64()))
if opts.Collector.Host == "" {
opts.Collector.Host = DefaultGRPCCollectorHost
}
if opts.Collector.Port <= 0 {
if opts.Collector.Plaintext {
opts.Collector.Port = DefaultPlainPort
} else {
opts.Collector.Port = DefaultSecurePort
}
}
return nil
}
// Validate checks that all required fields are set, and no options are incorrectly
// configured.
func (opts *Options) Validate() error {
if _, found := opts.Tags[GUIDKey]; found {
return errInvalidGUIDKey
}
if len(opts.Collector.CustomCACertFile) != 0 {
if _, err := os.Stat(opts.Collector.CustomCACertFile); os.IsNotExist(err) {
return err
}
}
return nil
}
// SetSpanID is a opentracing.StartSpanOption that sets an
// explicit SpanID. It must be used in conjunction with
// SetTraceID or the result is undefined.
type SetSpanID uint64
// Apply satisfies the StartSpanOption interface.
func (sid SetSpanID) Apply(sso *opentracing.StartSpanOptions) {}
func (sid SetSpanID) applyLS(sso *startSpanOptions) {
sso.SetSpanID = uint64(sid)
}
// SetTraceID is an opentracing.StartSpanOption that sets an
// explicit TraceID. It must be used in order to set an
// explicit SpanID or ParentSpanID. If a ChildOf or
// FollowsFrom span relation is also set in the start options,
// it will override this value.
type SetTraceID uint64
// Apply satisfies the StartSpanOption interface.
func (sid SetTraceID) Apply(sso *opentracing.StartSpanOptions) {}
func (sid SetTraceID) applyLS(sso *startSpanOptions) {
sso.SetTraceID = uint64(sid)
}
// SetParentSpanID is an opentracing.StartSpanOption that sets
// an explicit parent SpanID. It must be used in conjunction
// with SetTraceID or the result is undefined. If the value
// is zero, it will be disregarded. If a ChildOf or
// FollowsFrom span relation is also set in the start options,
// it will override this value.
type SetParentSpanID uint64
// Apply satisfies the StartSpanOption interface.
func (sid SetParentSpanID) Apply(sso *opentracing.StartSpanOptions) {}
func (sid SetParentSpanID) applyLS(sso *startSpanOptions) {
sso.SetParentSpanID = uint64(sid)
}
// lightStepStartSpanOption is used to identify lightstep-specific Span options.
type lightStepStartSpanOption interface {
applyLS(*startSpanOptions)
}
type SetSampled string
func (s SetSampled) Apply(sso *opentracing.StartSpanOptions) {}
func (s SetSampled) applyLS(sso *startSpanOptions) {
sso.SetSampled = string(s)
}
type startSpanOptions struct {
Options opentracing.StartSpanOptions
// Options to explicitly set span_id, trace_id,
// parent_span_id, expected to be used when exporting spans
// from another system into LightStep via opentracing APIs.
SetSpanID uint64
SetParentSpanID uint64
SetTraceID uint64
SetSampled string
}
func newStartSpanOptions(sso []opentracing.StartSpanOption) startSpanOptions {
opts := startSpanOptions{}
for _, o := range sso {
switch o := o.(type) {
case lightStepStartSpanOption:
o.applyLS(&opts)
default:
o.Apply(&opts.Options)
}
}
return opts
}