1// Copyright The OpenTelemetry Authors
2// SPDX-License-Identifier: Apache-2.0
3
4package global // import "go.opentelemetry.io/otel/internal/global"
5
6import (
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.
16type 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.
25var _ propagation.TextMapPropagator = (*textMapPropagator)(nil)
26
27func 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.
36func (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.
49func (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.
59func (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.
64func (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.
69func (p *textMapPropagator) Fields() []string {
70 return p.effectiveDelegate().Fields()
71}