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 "errors"
8 "sync"
9 "sync/atomic"
10
11 "go.opentelemetry.io/otel/metric"
12 "go.opentelemetry.io/otel/propagation"
13 "go.opentelemetry.io/otel/trace"
14)
15
16type (
17 errorHandlerHolder struct {
18 eh ErrorHandler
19 }
20
21 tracerProviderHolder struct {
22 tp trace.TracerProvider
23 }
24
25 propagatorsHolder struct {
26 tm propagation.TextMapPropagator
27 }
28
29 meterProviderHolder struct {
30 mp metric.MeterProvider
31 }
32)
33
34var (
35 globalErrorHandler = defaultErrorHandler()
36 globalTracer = defaultTracerValue()
37 globalPropagators = defaultPropagatorsValue()
38 globalMeterProvider = defaultMeterProvider()
39
40 delegateErrorHandlerOnce sync.Once
41 delegateTraceOnce sync.Once
42 delegateTextMapPropagatorOnce sync.Once
43 delegateMeterOnce sync.Once
44)
45
46// GetErrorHandler returns the global ErrorHandler instance.
47//
48// The default ErrorHandler instance returned will log all errors to STDERR
49// until an override ErrorHandler is set with SetErrorHandler. All
50// ErrorHandler returned prior to this will automatically forward errors to
51// the set instance instead of logging.
52//
53// Subsequent calls to SetErrorHandler after the first will not forward errors
54// to the new ErrorHandler for prior returned instances.
55func GetErrorHandler() ErrorHandler {
56 return globalErrorHandler.Load().(errorHandlerHolder).eh
57}
58
59// SetErrorHandler sets the global ErrorHandler to h.
60//
61// The first time this is called all ErrorHandler previously returned from
62// GetErrorHandler will send errors to h instead of the default logging
63// ErrorHandler. Subsequent calls will set the global ErrorHandler, but not
64// delegate errors to h.
65func SetErrorHandler(h ErrorHandler) {
66 current := GetErrorHandler()
67
68 if _, cOk := current.(*ErrDelegator); cOk {
69 if _, ehOk := h.(*ErrDelegator); ehOk && current == h {
70 // Do not assign to the delegate of the default ErrDelegator to be
71 // itself.
72 Error(
73 errors.New("no ErrorHandler delegate configured"),
74 "ErrorHandler remains its current value.",
75 )
76 return
77 }
78 }
79
80 delegateErrorHandlerOnce.Do(func() {
81 if def, ok := current.(*ErrDelegator); ok {
82 def.setDelegate(h)
83 }
84 })
85 globalErrorHandler.Store(errorHandlerHolder{eh: h})
86}
87
88// TracerProvider is the internal implementation for global.TracerProvider.
89func TracerProvider() trace.TracerProvider {
90 return globalTracer.Load().(tracerProviderHolder).tp
91}
92
93// SetTracerProvider is the internal implementation for global.SetTracerProvider.
94func SetTracerProvider(tp trace.TracerProvider) {
95 current := TracerProvider()
96
97 if _, cOk := current.(*tracerProvider); cOk {
98 if _, tpOk := tp.(*tracerProvider); tpOk && current == tp {
99 // Do not assign the default delegating TracerProvider to delegate
100 // to itself.
101 Error(
102 errors.New("no delegate configured in tracer provider"),
103 "Setting tracer provider to its current value. No delegate will be configured",
104 )
105 return
106 }
107 }
108
109 delegateTraceOnce.Do(func() {
110 if def, ok := current.(*tracerProvider); ok {
111 def.setDelegate(tp)
112 }
113 })
114 globalTracer.Store(tracerProviderHolder{tp: tp})
115}
116
117// TextMapPropagator is the internal implementation for global.TextMapPropagator.
118func TextMapPropagator() propagation.TextMapPropagator {
119 return globalPropagators.Load().(propagatorsHolder).tm
120}
121
122// SetTextMapPropagator is the internal implementation for global.SetTextMapPropagator.
123func SetTextMapPropagator(p propagation.TextMapPropagator) {
124 current := TextMapPropagator()
125
126 if _, cOk := current.(*textMapPropagator); cOk {
127 if _, pOk := p.(*textMapPropagator); pOk && current == p {
128 // Do not assign the default delegating TextMapPropagator to
129 // delegate to itself.
130 Error(
131 errors.New("no delegate configured in text map propagator"),
132 "Setting text map propagator to its current value. No delegate will be configured",
133 )
134 return
135 }
136 }
137
138 // For the textMapPropagator already returned by TextMapPropagator
139 // delegate to p.
140 delegateTextMapPropagatorOnce.Do(func() {
141 if def, ok := current.(*textMapPropagator); ok {
142 def.SetDelegate(p)
143 }
144 })
145 // Return p when subsequent calls to TextMapPropagator are made.
146 globalPropagators.Store(propagatorsHolder{tm: p})
147}
148
149// MeterProvider is the internal implementation for global.MeterProvider.
150func MeterProvider() metric.MeterProvider {
151 return globalMeterProvider.Load().(meterProviderHolder).mp
152}
153
154// SetMeterProvider is the internal implementation for global.SetMeterProvider.
155func SetMeterProvider(mp metric.MeterProvider) {
156 current := MeterProvider()
157 if _, cOk := current.(*meterProvider); cOk {
158 if _, mpOk := mp.(*meterProvider); mpOk && current == mp {
159 // Do not assign the default delegating MeterProvider to delegate
160 // to itself.
161 Error(
162 errors.New("no delegate configured in meter provider"),
163 "Setting meter provider to its current value. No delegate will be configured",
164 )
165 return
166 }
167 }
168
169 delegateMeterOnce.Do(func() {
170 if def, ok := current.(*meterProvider); ok {
171 def.setDelegate(mp)
172 }
173 })
174 globalMeterProvider.Store(meterProviderHolder{mp: mp})
175}
176
177func defaultErrorHandler() *atomic.Value {
178 v := &atomic.Value{}
179 v.Store(errorHandlerHolder{eh: &ErrDelegator{}})
180 return v
181}
182
183func defaultTracerValue() *atomic.Value {
184 v := &atomic.Value{}
185 v.Store(tracerProviderHolder{tp: &tracerProvider{}})
186 return v
187}
188
189func defaultPropagatorsValue() *atomic.Value {
190 v := &atomic.Value{}
191 v.Store(propagatorsHolder{tm: newTextMapPropagator()})
192 return v
193}
194
195func defaultMeterProvider() *atomic.Value {
196 v := &atomic.Value{}
197 v.Store(meterProviderHolder{mp: &meterProvider{}})
198 return v
199}