// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 package global // import "go.opentelemetry.io/otel/internal/global" import ( "errors" "sync" "sync/atomic" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/trace" ) type ( errorHandlerHolder struct { eh ErrorHandler } tracerProviderHolder struct { tp trace.TracerProvider } propagatorsHolder struct { tm propagation.TextMapPropagator } meterProviderHolder struct { mp metric.MeterProvider } ) var ( globalErrorHandler = defaultErrorHandler() globalTracer = defaultTracerValue() globalPropagators = defaultPropagatorsValue() globalMeterProvider = defaultMeterProvider() delegateErrorHandlerOnce sync.Once delegateTraceOnce sync.Once delegateTextMapPropagatorOnce sync.Once delegateMeterOnce sync.Once ) // GetErrorHandler returns the global ErrorHandler instance. // // The default ErrorHandler instance returned will log all errors to STDERR // until an override ErrorHandler is set with SetErrorHandler. All // ErrorHandler returned prior to this will automatically forward errors to // the set instance instead of logging. // // Subsequent calls to SetErrorHandler after the first will not forward errors // to the new ErrorHandler for prior returned instances. func GetErrorHandler() ErrorHandler { return globalErrorHandler.Load().(errorHandlerHolder).eh } // SetErrorHandler sets the global ErrorHandler to h. // // The first time this is called all ErrorHandler previously returned from // GetErrorHandler will send errors to h instead of the default logging // ErrorHandler. Subsequent calls will set the global ErrorHandler, but not // delegate errors to h. func SetErrorHandler(h ErrorHandler) { current := GetErrorHandler() if _, cOk := current.(*ErrDelegator); cOk { if _, ehOk := h.(*ErrDelegator); ehOk && current == h { // Do not assign to the delegate of the default ErrDelegator to be // itself. Error( errors.New("no ErrorHandler delegate configured"), "ErrorHandler remains its current value.", ) return } } delegateErrorHandlerOnce.Do(func() { if def, ok := current.(*ErrDelegator); ok { def.setDelegate(h) } }) globalErrorHandler.Store(errorHandlerHolder{eh: h}) } // TracerProvider is the internal implementation for global.TracerProvider. func TracerProvider() trace.TracerProvider { return globalTracer.Load().(tracerProviderHolder).tp } // SetTracerProvider is the internal implementation for global.SetTracerProvider. func SetTracerProvider(tp trace.TracerProvider) { current := TracerProvider() if _, cOk := current.(*tracerProvider); cOk { if _, tpOk := tp.(*tracerProvider); tpOk && current == tp { // Do not assign the default delegating TracerProvider to delegate // to itself. Error( errors.New("no delegate configured in tracer provider"), "Setting tracer provider to its current value. No delegate will be configured", ) return } } delegateTraceOnce.Do(func() { if def, ok := current.(*tracerProvider); ok { def.setDelegate(tp) } }) globalTracer.Store(tracerProviderHolder{tp: tp}) } // TextMapPropagator is the internal implementation for global.TextMapPropagator. func TextMapPropagator() propagation.TextMapPropagator { return globalPropagators.Load().(propagatorsHolder).tm } // SetTextMapPropagator is the internal implementation for global.SetTextMapPropagator. func SetTextMapPropagator(p propagation.TextMapPropagator) { current := TextMapPropagator() if _, cOk := current.(*textMapPropagator); cOk { if _, pOk := p.(*textMapPropagator); pOk && current == p { // Do not assign the default delegating TextMapPropagator to // delegate to itself. Error( errors.New("no delegate configured in text map propagator"), "Setting text map propagator to its current value. No delegate will be configured", ) return } } // For the textMapPropagator already returned by TextMapPropagator // delegate to p. delegateTextMapPropagatorOnce.Do(func() { if def, ok := current.(*textMapPropagator); ok { def.SetDelegate(p) } }) // Return p when subsequent calls to TextMapPropagator are made. globalPropagators.Store(propagatorsHolder{tm: p}) } // MeterProvider is the internal implementation for global.MeterProvider. func MeterProvider() metric.MeterProvider { return globalMeterProvider.Load().(meterProviderHolder).mp } // SetMeterProvider is the internal implementation for global.SetMeterProvider. func SetMeterProvider(mp metric.MeterProvider) { current := MeterProvider() if _, cOk := current.(*meterProvider); cOk { if _, mpOk := mp.(*meterProvider); mpOk && current == mp { // Do not assign the default delegating MeterProvider to delegate // to itself. Error( errors.New("no delegate configured in meter provider"), "Setting meter provider to its current value. No delegate will be configured", ) return } } delegateMeterOnce.Do(func() { if def, ok := current.(*meterProvider); ok { def.setDelegate(mp) } }) globalMeterProvider.Store(meterProviderHolder{mp: mp}) } func defaultErrorHandler() *atomic.Value { v := &atomic.Value{} v.Store(errorHandlerHolder{eh: &ErrDelegator{}}) return v } func defaultTracerValue() *atomic.Value { v := &atomic.Value{} v.Store(tracerProviderHolder{tp: &tracerProvider{}}) return v } func defaultPropagatorsValue() *atomic.Value { v := &atomic.Value{} v.Store(propagatorsHolder{tm: newTextMapPropagator()}) return v } func defaultMeterProvider() *atomic.Value { v := &atomic.Value{} v.Store(meterProviderHolder{mp: &meterProvider{}}) return v }