forked from open-telemetry/opentelemetry-go-contrib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
registry.go
169 lines (152 loc) · 5.42 KB
/
registry.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
// 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 autoprop // import "go.opentelemetry.io/contrib/propagators/autoprop"
import (
"errors"
"fmt"
"strings"
"sync"
"go.opentelemetry.io/contrib/propagators/aws/xray"
"go.opentelemetry.io/contrib/propagators/b3"
"go.opentelemetry.io/contrib/propagators/jaeger"
"go.opentelemetry.io/contrib/propagators/ot"
"go.opentelemetry.io/otel/propagation"
)
// none is the special "propagator" name that means no propagator shall be
// configured.
const none = "none"
// propagators is the registry of TextMapPropagators registered with this
// package. It includes all the OpenTelemetry defaults at startup.
var propagators = ®istry{
names: map[string]propagation.TextMapPropagator{
// W3C Trace Context.
"tracecontext": propagation.TraceContext{},
// W3C Baggage.
"baggage": propagation.Baggage{},
// B3 single-header format.
"b3": b3.New(),
// B3 multi-header format.
"b3multi": b3.New(b3.WithInjectEncoding(b3.B3MultipleHeader)),
// Jaeger.
"jaeger": jaeger.Jaeger{},
// AWS X-Ray.
"xray": xray.Propagator{},
// OpenTracing Trace.
"ottrace": ot.OT{},
// No-op TextMapPropagator.
none: propagation.NewCompositeTextMapPropagator(),
},
}
// registry maintains a map of propagator names to TextMapPropagator
// implementations that is safe for concurrent use by multiple goroutines
// without additional locking or coordination.
type registry struct {
mu sync.Mutex
names map[string]propagation.TextMapPropagator
}
// load returns the value stored in the registry index for a key, or nil if no
// value is present. The ok result indicates whether value was found in the
// index.
func (r *registry) load(key string) (p propagation.TextMapPropagator, ok bool) {
r.mu.Lock()
p, ok = r.names[key]
r.mu.Unlock()
return p, ok
}
var errDupReg = errors.New("duplicate registration")
// store sets the value for a key if is not already in the registry. errDupReg
// is returned if the registry already contains key.
func (r *registry) store(key string, value propagation.TextMapPropagator) error {
r.mu.Lock()
defer r.mu.Unlock()
if r.names == nil {
r.names = map[string]propagation.TextMapPropagator{key: value}
return nil
}
if _, ok := r.names[key]; ok {
return fmt.Errorf("%w: %q", errDupReg, key)
}
r.names[key] = value
return nil
}
// drop removes key from the registry if it exists, otherwise nothing.
func (r *registry) drop(key string) {
r.mu.Lock()
delete(r.names, key)
r.mu.Unlock()
}
// RegisterTextMapPropagator sets the TextMapPropagator p to be used when the
// OTEL_PROPAGATORS environment variable contains the propagator name. This
// will panic if name has already been registered or is a default
// (tracecontext, baggage, b3, b3multi, jaeger, xray, or ottrace).
func RegisterTextMapPropagator(name string, p propagation.TextMapPropagator) {
if err := propagators.store(name, p); err != nil {
// envRegistry.store will return errDupReg if name is already
// registered. Panic here so the user is made aware of the duplicate
// registration, which could be done by malicious code trying to
// intercept cross-cutting concerns.
//
// Panic for all other errors as well. At this point there should not
// be any other errors returned from the store operation. If there
// are, alert the developer that adding them as soon as possible that
// they need to be handled here.
panic(err)
}
}
// GetTextMapPropagator returns a TextMapPropagator composed from the
// passed names of registered TextMapPropagators. Each name must match an
// already registered TextMapPropagator (see the RegisterTextMapPropagator
// function for more information) or a default (tracecontext, baggage, b3,
// b3multi, jaeger, xray, or ottrace).
//
// If "none" is included in the arguments, or no names are provided, the
// returned TextMapPropagator will be a no-operation implementation.
//
// An error is returned for any un-registered names. The remaining, known,
// names will be used to compose a TextMapPropagator that is returned with the
// error.
func GetTextMapPropagator(names ...string) (propagation.TextMapPropagator, error) {
var (
props []propagation.TextMapPropagator
unknown []string
)
for _, name := range names {
if name == none {
// If "none" is passed in combination with any other propagator,
// the result still needs to be a no-op propagator. Therefore,
// short-circuit here.
return propagation.NewCompositeTextMapPropagator(), nil
}
p, ok := propagators.load(name)
if !ok {
unknown = append(unknown, name)
continue
}
props = append(props, p)
}
var err error
if len(unknown) > 0 {
joined := strings.Join(unknown, ",")
err = fmt.Errorf("%w: %s", errUnknownPropagator, joined)
}
switch len(props) {
case 0:
return nil, err
case 1:
// Do not return a composite of a single propagator.
return props[0], err
default:
return propagation.NewCompositeTextMapPropagator(props...), err
}
}