-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathtracer.go
139 lines (110 loc) · 3.02 KB
/
tracer.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
// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2016
package instana
import (
"context"
"time"
ot "github.com/opentracing/opentracing-go"
)
const (
// MaxLogsPerSpan The maximum number of logs allowed on a span.
MaxLogsPerSpan = 2
)
var _ Tracer = (*tracerS)(nil)
type tracerS struct {
recorder SpanRecorder
}
// NewTracer initializes a new tracer with default options
func NewTracer() *tracerS {
return NewTracerWithOptions(nil)
}
// NewTracerWithOptions initializes and configures a new tracer that collects and sends spans to the agent
func NewTracerWithOptions(options *Options) *tracerS {
return NewTracerWithEverything(options, nil)
}
// NewTracerWithEverything initializes and configures a new tracer. It uses instana.DefaultOptions() if nil
// is provided
func NewTracerWithEverything(options *Options, recorder SpanRecorder) *tracerS {
InitSensor(options)
if recorder == nil {
recorder = NewRecorder()
}
tracer := &tracerS{
recorder: recorder,
}
return tracer
}
func (r *tracerS) Inject(spanContext ot.SpanContext, format interface{}, carrier interface{}) error {
switch format {
case ot.TextMap, ot.HTTPHeaders:
sc, ok := spanContext.(SpanContext)
if !ok {
return ot.ErrInvalidSpanContext
}
return injectTraceContext(sc, carrier)
}
return ot.ErrUnsupportedFormat
}
func (r *tracerS) Extract(format interface{}, carrier interface{}) (ot.SpanContext, error) {
switch format {
case ot.TextMap, ot.HTTPHeaders:
sc, err := extractTraceContext(carrier)
if err != nil {
return nil, err
}
return sc, nil
}
return nil, ot.ErrUnsupportedFormat
}
func (r *tracerS) StartSpan(operationName string, opts ...ot.StartSpanOption) ot.Span {
sso := ot.StartSpanOptions{}
for _, o := range opts {
o.Apply(&sso)
}
return r.StartSpanWithOptions(operationName, sso)
}
func (r *tracerS) StartSpanWithOptions(operationName string, opts ot.StartSpanOptions) ot.Span {
startTime := opts.StartTime
if startTime.IsZero() {
startTime = time.Now()
}
var corrData EUMCorrelationData
sc := NewRootSpanContext()
for _, ref := range opts.References {
if ref.Type == ot.ChildOfRef || ref.Type == ot.FollowsFromRef {
if parent, ok := ref.ReferencedContext.(SpanContext); ok {
corrData = parent.Correlation
sc = NewSpanContext(parent)
break
}
}
}
if tag, ok := opts.Tags[suppressTracingTag]; ok {
sc.Suppressed = tag.(bool)
delete(opts.Tags, suppressTracingTag)
}
return &spanS{
context: sc,
tracer: r,
Service: sensor.serviceName,
Operation: operationName,
Start: startTime,
Duration: -1,
Correlation: corrData,
Tags: cloneTags(opts.Tags),
}
}
// Options returns current tracer options
func (r *tracerS) Options() TracerOptions {
if sensor.options == nil {
return DefaultTracerOptions()
}
return sensor.options.Tracer
}
// Flush forces sending any queued finished spans to the agent
func (r *tracerS) Flush(ctx context.Context) error {
if err := r.recorder.Flush(ctx); err != nil {
return err
}
return sensor.Agent().Flush(ctx)
}