state.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	"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}