-
Notifications
You must be signed in to change notification settings - Fork 53
/
exporter.go
107 lines (87 loc) · 2.94 KB
/
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
package lightstepoc
import (
"context"
"errors"
"github.com/lightstep/lightstep-tracer-go"
"github.com/lightstep/lightstep-tracer-go/lightstepoc/internal/conversions"
"github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/ext"
"github.com/opentracing/opentracing-go/log"
"go.opencensus.io/trace"
)
var (
// ErrFailedToCreateExporter indicates that the underlying tracer could not be created,
// but the root reason is not known.
ErrFailedToCreateExporter = errors.New("lightstepoc: failed to create exporter")
)
// Exporter may be registered with OpenCensus so that span data can be exported to LightStep
type Exporter struct {
tracer lightstep.Tracer
}
// NewExporter creates a new Exporter.
// It returns an error if the underlying tracer could not be created, e.g., due to invalid options
func NewExporter(opts ...Option) (*Exporter, error) {
c := defaultConfig()
for _, opt := range opts {
opt(c)
}
tracer := lightstep.NewTracer(c.tracerOptions)
if tracer == nil {
if err := c.tracerOptions.Validate(); err != nil {
return nil, err
}
return nil, ErrFailedToCreateExporter
}
return &Exporter{
tracer: tracer,
}, nil
}
// ExportSpan queues the span to be sent LightStep.
// Spans are typically batched for performance reasons. Call `Exporter#Flush` to send all queued spans.
func (e *Exporter) ExportSpan(sd *trace.SpanData) {
opts := []opentracing.StartSpanOption{
opentracing.StartTime(sd.StartTime),
lightstep.SetTraceID(conversions.ConvertTraceID(sd.SpanContext.TraceID)),
lightstep.SetSpanID(conversions.ConvertSpanID(sd.SpanContext.SpanID)),
lightstep.SetParentSpanID(conversions.ConvertSpanID(sd.ParentSpanID)),
}
for _, link := range sd.Links {
if link.Type == trace.LinkTypeChild {
spanContext := conversions.ConvertLinkToSpanContext(link)
opts = append(opts, opentracing.ChildOf(spanContext))
}
}
switch sd.SpanKind {
case trace.SpanKindServer:
opts = append(opts, ext.SpanKindRPCServer)
case trace.SpanKindClient:
opts = append(opts, ext.SpanKindRPCClient)
}
span := e.tracer.StartSpan(sd.Name, opts...)
for _, entry := range sd.SpanContext.Tracestate.Entries() {
span.SetBaggageItem(entry.Key, entry.Value)
}
ext.HTTPStatusCode.Set(span, uint16(sd.Status.Code))
for k, v := range sd.Attributes {
span.SetTag(k, v)
}
var logRecords []opentracing.LogRecord
for _, annotation := range sd.Annotations {
logRecords = append(logRecords, opentracing.LogRecord{
Timestamp: annotation.Time,
Fields: []log.Field{log.Object(annotation.Message, annotation.Attributes)},
})
}
span.FinishWithOptions(opentracing.FinishOptions{
FinishTime: sd.EndTime,
LogRecords: logRecords,
})
}
// Flush sends all buffered spans to LightStep
func (e *Exporter) Flush(ctx context.Context) {
e.tracer.Flush(ctx)
}
// Close flushes all buffered spans and then kills open connections to LightStep, releasing resources
func (e *Exporter) Close(ctx context.Context) {
e.tracer.Close(ctx)
}