forked from open-telemetry/opentelemetry-go-contrib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
config.go
138 lines (113 loc) · 4.53 KB
/
config.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
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package otellambda
import (
"context"
"runtime"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
)
// A Flusher dictates how the instrumentation will attempt to flush
// unexported spans at the end of each Lambda innovation. This is
// very important in asynchronous settings because the Lambda runtime
// may enter a 'frozen' state any time after the invocation completes.
// Should this freeze happen and spans are left unexported, there can be a
// long delay before those spans are exported.
type Flusher interface {
ForceFlush(context.Context) error
}
type noopFlusher struct{}
func (*noopFlusher) ForceFlush(context.Context) error { return nil }
// Compile time check our noopFlusher implements Flusher
var _ Flusher = &noopFlusher{}
// An EventToCarrier function defines how the instrumentation should
// prepare a TextMapCarrier for the configured propagator to read from. This
// extra step is necessary because Lambda does not have HTTP headers to read
// from and instead stores the headers it was invoked with (including TraceID, etc.)
// as part of the invocation event. If using the AWS XRay tracing then the
// trace information is instead stored in the Lambda environment.
type EventToCarrier func(eventJSON []byte) propagation.TextMapCarrier
func emptyEventToCarrier([]byte) propagation.TextMapCarrier {
return propagation.HeaderCarrier{}
}
// Compile time check our emptyEventToCarrier implements EventToCarrier
var _ EventToCarrier = emptyEventToCarrier
type Option interface {
apply(*config)
}
type optionFunc func(*config)
func (o optionFunc) apply(c *config) {
o(c)
}
type config struct {
// TracerProvider is the TracerProvider which will be used
// to create instrumentation spans
// The default value of TracerProvider the global otel TracerProvider
// returned by otel.GetTracerProvider()
TracerProvider trace.TracerProvider
// Flusher is the mechanism used to flush any unexported spans
// each Lambda Invocation to avoid spans being unexported for long
// when periods of time if Lambda freezes the execution environment
// The default value of Flusher is a noop Flusher, using this
// default can result in long data delays in asynchronous settings
Flusher Flusher
// EventToCarrier is the mechanism used to retrieve the TraceID
// from the event or environment and generate a TextMapCarrier which
// can then be used by a Propagator to extract the TraceID into our context
// The default value of eventToCarrier is emptyEventToCarrier which returns
// an empty HeaderCarrier, using this default will cause new spans to be part
// of a new Trace and have no parent past our Lambda instrumentation span
EventToCarrier EventToCarrier
// Propagator is the Propagator which will be used
// to extract Trace info into the context
// The default value of Propagator the global otel Propagator
// returned by otel.GetTextMapPropagator()
Propagator propagation.TextMapPropagator
}
type asyncSafeFlusher struct {
flusher Flusher
}
func (f asyncSafeFlusher) ForceFlush(ctx context.Context) error {
// yield processor to attempt to ensure all spans have
// been consumed and are ready to be flushed
// - see https://github.com/open-telemetry/opentelemetry-go/issues/2080
// to be removed upon resolution of above issue
runtime.Gosched()
return f.flusher.ForceFlush(ctx)
}
func WithTracerProvider(tracerProvider trace.TracerProvider) Option {
return optionFunc(func(c *config) {
c.TracerProvider = tracerProvider
})
}
func WithFlusher(flusher Flusher) Option {
return optionFunc(func(c *config) {
c.Flusher = flusher
})
}
func WithEventToCarrier(eventToCarrier EventToCarrier) Option {
return optionFunc(func(c *config) {
c.EventToCarrier = eventToCarrier
})
}
func WithPropagator(propagator propagation.TextMapPropagator) Option {
return optionFunc(func(c *config) {
c.Propagator = propagator
})
}
func WithAsyncSafeFlusher(f Flusher) Option {
return optionFunc(func(c *config) {
c.Flusher = asyncSafeFlusher{f}
})
}