blob: ecdfd75ab55dd86a47550a3aa28097ff1142c447 [file] [log] [blame]
Joey Armstrong5f51f2e2023-01-17 17:06:26 -05001// Copyright The OpenTelemetry Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package internal
16
17import (
18 "sync"
19 "sync/atomic"
20
21 "go.opentelemetry.io/otel"
22 "go.opentelemetry.io/otel/api/metric"
23 "go.opentelemetry.io/otel/api/trace"
24)
25
26type (
27 tracerProviderHolder struct {
28 tp trace.TracerProvider
29 }
30
31 meterProviderHolder struct {
32 mp metric.MeterProvider
33 }
34
35 propagatorsHolder struct {
36 tm otel.TextMapPropagator
37 }
38)
39
40var (
41 globalTracer = defaultTracerValue()
42 globalMeter = defaultMeterValue()
43 globalPropagators = defaultPropagatorsValue()
44
45 delegateMeterOnce sync.Once
46 delegateTraceOnce sync.Once
47)
48
49// TracerProvider is the internal implementation for global.TracerProvider.
50func TracerProvider() trace.TracerProvider {
51 return globalTracer.Load().(tracerProviderHolder).tp
52}
53
54// SetTracerProvider is the internal implementation for global.SetTracerProvider.
55func SetTracerProvider(tp trace.TracerProvider) {
56 delegateTraceOnce.Do(func() {
57 current := TracerProvider()
58 if current == tp {
59 // Setting the provider to the prior default is nonsense, panic.
60 // Panic is acceptable because we are likely still early in the
61 // process lifetime.
62 panic("invalid TracerProvider, the global instance cannot be reinstalled")
63 } else if def, ok := current.(*tracerProvider); ok {
64 def.setDelegate(tp)
65 }
66
67 })
68 globalTracer.Store(tracerProviderHolder{tp: tp})
69}
70
71// MeterProvider is the internal implementation for global.MeterProvider.
72func MeterProvider() metric.MeterProvider {
73 return globalMeter.Load().(meterProviderHolder).mp
74}
75
76// SetMeterProvider is the internal implementation for global.SetMeterProvider.
77func SetMeterProvider(mp metric.MeterProvider) {
78 delegateMeterOnce.Do(func() {
79 current := MeterProvider()
80
81 if current == mp {
82 // Setting the provider to the prior default is nonsense, panic.
83 // Panic is acceptable because we are likely still early in the
84 // process lifetime.
85 panic("invalid MeterProvider, the global instance cannot be reinstalled")
86 } else if def, ok := current.(*meterProvider); ok {
87 def.setDelegate(mp)
88 }
89 })
90 globalMeter.Store(meterProviderHolder{mp: mp})
91}
92
93// TextMapPropagator is the internal implementation for global.TextMapPropagator.
94func TextMapPropagator() otel.TextMapPropagator {
95 return globalPropagators.Load().(propagatorsHolder).tm
96}
97
98// SetTextMapPropagator is the internal implementation for global.SetTextMapPropagator.
99func SetTextMapPropagator(p otel.TextMapPropagator) {
100 globalPropagators.Store(propagatorsHolder{tm: p})
101}
102
103func defaultTracerValue() *atomic.Value {
104 v := &atomic.Value{}
105 v.Store(tracerProviderHolder{tp: &tracerProvider{}})
106 return v
107}
108
109func defaultMeterValue() *atomic.Value {
110 v := &atomic.Value{}
111 v.Store(meterProviderHolder{mp: newMeterProvider()})
112 return v
113}
114
115func defaultPropagatorsValue() *atomic.Value {
116 v := &atomic.Value{}
117 v.Store(propagatorsHolder{tm: getDefaultTextMapPropagator()})
118 return v
119}
120
121// getDefaultTextMapPropagator returns the default TextMapPropagator,
122// configured with W3C trace and baggage propagation.
123func getDefaultTextMapPropagator() otel.TextMapPropagator {
124 return otel.NewCompositeTextMapPropagator()
125}
126
127// ResetForTest restores the initial global state, for testing purposes.
128func ResetForTest() {
129 globalTracer = defaultTracerValue()
130 globalMeter = defaultMeterValue()
131 globalPropagators = defaultPropagatorsValue()
132 delegateMeterOnce = sync.Once{}
133 delegateTraceOnce = sync.Once{}
134}