1// 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 otel // import "go.opentelemetry.io/otel" 16 17import ( 18 "log" 19 "os" 20 "sync" 21 "sync/atomic" 22) 23 24var ( 25 // globalErrorHandler provides an ErrorHandler that can be used 26 // throughout an OpenTelemetry instrumented project. When a user 27 // specified ErrorHandler is registered (`SetErrorHandler`) all calls to 28 // `Handle` and will be delegated to the registered ErrorHandler. 29 globalErrorHandler = defaultErrorHandler() 30 31 // delegateErrorHandlerOnce ensures that a user provided ErrorHandler is 32 // only ever registered once. 33 delegateErrorHandlerOnce sync.Once 34 35 // Compile-time check that delegator implements ErrorHandler. 36 _ ErrorHandler = (*delegator)(nil) 37) 38 39type holder struct { 40 eh ErrorHandler 41} 42 43func defaultErrorHandler() *atomic.Value { 44 v := &atomic.Value{} 45 v.Store(holder{eh: &delegator{l: log.New(os.Stderr, "", log.LstdFlags)}}) 46 return v 47} 48 49// delegator logs errors if no delegate is set, otherwise they are delegated. 50type delegator struct { 51 delegate atomic.Value 52 53 l *log.Logger 54} 55 56// setDelegate sets the ErrorHandler delegate. 57func (h *delegator) setDelegate(d ErrorHandler) { 58 // It is critical this is guarded with delegateErrorHandlerOnce, if it is 59 // called again with a different concrete type it will panic. 60 h.delegate.Store(d) 61} 62 63// Handle logs err if no delegate is set, otherwise it is delegated. 64func (h *delegator) Handle(err error) { 65 if d := h.delegate.Load(); d != nil { 66 d.(ErrorHandler).Handle(err) 67 return 68 } 69 h.l.Print(err) 70} 71 72// GetErrorHandler returns the global ErrorHandler instance. 73// 74// The default ErrorHandler instance returned will log all errors to STDERR 75// until an override ErrorHandler is set with SetErrorHandler. All 76// ErrorHandler returned prior to this will automatically forward errors to 77// the set instance instead of logging. 78// 79// Subsequent calls to SetErrorHandler after the first will not forward errors 80// to the new ErrorHandler for prior returned instances. 81func GetErrorHandler() ErrorHandler { 82 return globalErrorHandler.Load().(holder).eh 83} 84 85// SetErrorHandler sets the global ErrorHandler to h. 86// 87// The first time this is called all ErrorHandler previously returned from 88// GetErrorHandler will send errors to h instead of the default logging 89// ErrorHandler. Subsequent calls will set the global ErrorHandler, but not 90// delegate errors to h. 91func SetErrorHandler(h ErrorHandler) { 92 delegateErrorHandlerOnce.Do(func() { 93 current := GetErrorHandler() 94 if current == h { 95 return 96 } 97 if internalHandler, ok := current.(*delegator); ok { 98 internalHandler.setDelegate(h) 99 } 100 }) 101 globalErrorHandler.Store(holder{eh: h}) 102} 103 104// Handle is a convenience function for ErrorHandler().Handle(err) 105func Handle(err error) { 106 GetErrorHandler().Handle(err) 107} 108