propagator.go

 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}