-
Notifications
You must be signed in to change notification settings - Fork 0
/
span_exporter.go
119 lines (99 loc) · 2.93 KB
/
span_exporter.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
package bugsnagperformance
import (
"context"
"encoding/json"
"go.opentelemetry.io/otel/sdk/trace"
)
type SpanExporter struct {
disabled bool
unmanagedMode bool
loggedFirstBatchDestination bool
probabilityManager *probabilityManager
sampler *Sampler
delivery *delivery
sampleHeaderEnc *samplingHeaderEncoder
paylodEnc *payloadEncoder
}
type managedSpan struct {
samplingProbability *float64
span trace.ReadOnlySpan
}
func createSpanExporter(probMgr *probabilityManager, sampler *Sampler, delivery *delivery, unmanaged bool) trace.SpanExporter {
sp := SpanExporter{
disabled: false,
loggedFirstBatchDestination: false,
probabilityManager: probMgr,
delivery: delivery,
sampler: sampler,
unmanagedMode: unmanaged,
}
return &sp
}
func (sp *SpanExporter) ExportSpans(ctx context.Context, spans []trace.ReadOnlySpan) error {
if sp.disabled {
return nil
}
sp.maybe_enter_unmanaged_mode()
managedStatus := "managed"
if sp.unmanagedMode {
managedStatus = "unmanaged"
}
filteredSpans := []managedSpan{}
headers := map[string]string{}
if !sp.unmanagedMode {
// resample spans
for _, span := range spans {
managedSpan, accepted := sp.sampler.resample(span)
if accepted {
filteredSpans = append(filteredSpans, managedSpan)
}
}
samplingHeader := sp.sampleHeaderEnc.encode(filteredSpans)
if samplingHeader == "" {
Config.Logger.Printf("One or more spans are missing the 'bugsnag.sampling.p' attribute. This trace will be sent as unmanaged.\n")
managedStatus = "unmanaged"
} else {
headers[samplingRequestHeader] = samplingHeader
}
} else {
for _, span := range spans {
filteredSpans = append(filteredSpans, managedSpan{span: span})
}
}
if !sp.loggedFirstBatchDestination {
Config.Logger.Printf("Sending %+v spans to %+v\n", managedStatus, sp.delivery.uri)
sp.loggedFirstBatchDestination = true
}
// encode to JSON
encodedPayload := sp.paylodEnc.encode(filteredSpans)
payload, err := json.Marshal(encodedPayload)
if err != nil {
Config.Logger.Printf("Error encoding spans: %v\n", err)
}
// send payload
resp, err := sp.delivery.send(headers, payload)
if err != nil {
Config.Logger.Printf("Error sending payload: %v\n", err)
}
// update sampling probability in ProbabilityManager
if resp != nil {
parsedResp := newParsedResponse(*resp)
if parsedResp.samplingProbablity != nil {
sp.probabilityManager.setProbability(*parsedResp.samplingProbablity)
}
}
return nil
}
func (sp *SpanExporter) Shutdown(ctx context.Context) error {
return nil
}
func (sp *SpanExporter) maybe_enter_unmanaged_mode() {
if sp.unmanagedMode {
return
}
if Config.CustomSampler != nil && sp.sampler != Config.CustomSampler {
sp.unmanagedMode = true
} else {
sp.unmanagedMode = false
}
}