forked from lightstep/lightstep-tracer-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
options.go
340 lines (282 loc) · 11.1 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
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/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"
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 = "lightstep.component_name"
GUIDKey = "lightstep.guid" // <- runtime guid, not span guid
HostnameKey = "lightstep.hostname"
CommandLineKey = "lightstep.command_line"
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 thrift 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
}
// 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 applicaiton'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, GRPC is defaulted to.
UseHttp bool `yaml:"use_http"`
UseGRPC bool `yaml:"usegrpc"`
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"`
}
// 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[ComponentNameKey]; !found {
opts.Tags[ComponentNameKey] = path.Base(os.Args[0])
}
if _, found := opts.Tags[HostnameKey]; !found {
hostname, _ := os.Hostname()
opts.Tags[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 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
}
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
}