propagator.go raw
1 // Copyright The OpenTelemetry Authors
2 // SPDX-License-Identifier: Apache-2.0
3
4 package global // import "go.opentelemetry.io/otel/internal/global"
5
6 import (
7 "context"
8 "sync"
9
10 "go.opentelemetry.io/otel/propagation"
11 )
12
13 // textMapPropagator is a default TextMapPropagator that delegates calls to a
14 // registered delegate if one is set, otherwise it defaults to delegating the
15 // calls to a the default no-op propagation.TextMapPropagator.
16 type textMapPropagator struct {
17 mtx sync.Mutex
18 once sync.Once
19 delegate propagation.TextMapPropagator
20 noop propagation.TextMapPropagator
21 }
22
23 // Compile-time guarantee that textMapPropagator implements the
24 // propagation.TextMapPropagator interface.
25 var _ propagation.TextMapPropagator = (*textMapPropagator)(nil)
26
27 func newTextMapPropagator() *textMapPropagator {
28 return &textMapPropagator{
29 noop: propagation.NewCompositeTextMapPropagator(),
30 }
31 }
32
33 // SetDelegate sets a delegate propagation.TextMapPropagator that all calls are
34 // forwarded to. Delegation can only be performed once, all subsequent calls
35 // perform no delegation.
36 func (p *textMapPropagator) SetDelegate(delegate propagation.TextMapPropagator) {
37 if delegate == nil {
38 return
39 }
40
41 p.mtx.Lock()
42 p.once.Do(func() { p.delegate = delegate })
43 p.mtx.Unlock()
44 }
45
46 // effectiveDelegate returns the current delegate of p if one is set,
47 // otherwise the default noop TextMapPropagator is returned. This method
48 // can be called concurrently.
49 func (p *textMapPropagator) effectiveDelegate() propagation.TextMapPropagator {
50 p.mtx.Lock()
51 defer p.mtx.Unlock()
52 if p.delegate != nil {
53 return p.delegate
54 }
55 return p.noop
56 }
57
58 // Inject set cross-cutting concerns from the Context into the carrier.
59 func (p *textMapPropagator) Inject(ctx context.Context, carrier propagation.TextMapCarrier) {
60 p.effectiveDelegate().Inject(ctx, carrier)
61 }
62
63 // Extract reads cross-cutting concerns from the carrier into a Context.
64 func (p *textMapPropagator) Extract(ctx context.Context, carrier propagation.TextMapCarrier) context.Context {
65 return p.effectiveDelegate().Extract(ctx, carrier)
66 }
67
68 // Fields returns the keys whose values are set with Inject.
69 func (p *textMapPropagator) Fields() []string {
70 return p.effectiveDelegate().Fields()
71 }
72