1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-11-29 23:07:45 +02:00

simplifies error handling, uses internal logger by default

This commit is contained in:
Aaron Clawson
2021-11-17 16:17:04 +00:00
committed by GitHub
parent 8d0b098602
commit 8b210d20d4
5 changed files with 108 additions and 130 deletions

View File

@@ -15,10 +15,9 @@
package otel // import "go.opentelemetry.io/otel"
import (
"log"
"os"
"sync"
"sync/atomic"
"go.opentelemetry.io/otel/internal/debug"
)
var (
@@ -26,79 +25,61 @@ var (
// throughout an OpenTelemetry instrumented project. When a user
// specified ErrorHandler is registered (`SetErrorHandler`) all calls to
// `Handle` and will be delegated to the registered ErrorHandler.
globalErrorHandler = defaultErrorHandler()
globalErrorHandler = &errorHandlerDelegate{
delegate: &defaultErrorHandler{},
}
// delegateErrorHandlerOnce ensures that a user provided ErrorHandler is
// only ever registered once.
delegateErrorHandlerOnce sync.Once
// Compile-time check that delegator implements ErrorHandler.
_ ErrorHandler = (*delegator)(nil)
_ ErrorHandler = (*errorHandlerDelegate)(nil)
_ ErrorHandler = (*defaultErrorHandler)(nil)
)
type holder struct {
eh ErrorHandler
// errorHandlerDelegate is a box type to enable updating of all handlers returned by GetErrorHandler()
type errorHandlerDelegate struct {
delegate ErrorHandler
}
func defaultErrorHandler() *atomic.Value {
v := &atomic.Value{}
v.Store(holder{eh: &delegator{l: log.New(os.Stderr, "", log.LstdFlags)}})
return v
func (h *errorHandlerDelegate) setDelegate(d ErrorHandler) {
h.delegate = d
}
// delegator logs errors if no delegate is set, otherwise they are delegated.
type delegator struct {
delegate atomic.Value
l *log.Logger
}
// setDelegate sets the ErrorHandler delegate.
func (h *delegator) setDelegate(d ErrorHandler) {
// It is critical this is guarded with delegateErrorHandlerOnce, if it is
// called again with a different concrete type it will panic.
h.delegate.Store(d)
}
// Handle logs err if no delegate is set, otherwise it is delegated.
func (h *delegator) Handle(err error) {
if d := h.delegate.Load(); d != nil {
d.(ErrorHandler).Handle(err)
// Handle handles any error deemed irremediable by an OpenTelemetry component.
func (h *errorHandlerDelegate) Handle(err error) {
if h == nil {
return
}
h.l.Print(err)
h.delegate.Handle(err)
}
// defaultErrorHandler utilizes the internal logger to manage the messages.
type defaultErrorHandler struct{}
func (h *defaultErrorHandler) Handle(err error) {
debug.Error(err, "")
}
// DiscardErrorHandler drops all errors.
// Use `SetErrorHandler(DiscardErrorHandler{})` to disable error handling
type DiscardErrorHandler struct{}
func (DiscardErrorHandler) Handle(error) {}
// 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().(holder).eh
return globalErrorHandler
}
// 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) {
delegateErrorHandlerOnce.Do(func() {
current := GetErrorHandler()
if current == h {
return
}
if internalHandler, ok := current.(*delegator); ok {
internalHandler.setDelegate(h)
}
})
globalErrorHandler.Store(holder{eh: h})
globalErrorHandler.setDelegate(h)
}
// Handle is a convenience function for ErrorHandler().Handle(err)