mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2024-12-04 09:43:23 +02:00
Update global Handler delegate to atomic value
This commit is contained in:
parent
57e65fe7f8
commit
c50803d259
@ -18,47 +18,50 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"go.opentelemetry.io/otel/api/oterror"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultHandler = &handler{
|
||||
// globalHandler provides an oterror.Handler that can be used throughout
|
||||
// an OpenTelemetry instrumented project. When a user specified Handler
|
||||
// is registered (`SetHandler`) all calls to `Handle` will be delegated
|
||||
// to the registered Handler.
|
||||
globalHandler = &handler{
|
||||
l: log.New(os.Stderr, "", log.LstdFlags),
|
||||
}
|
||||
|
||||
// delegateHanderOnce ensures that a user provided Handler is only ever
|
||||
// registered once.
|
||||
delegateHanderOnce sync.Once
|
||||
|
||||
// Ensure the handler implements oterror.Handle at build time.
|
||||
_ oterror.Handler = (*handler)(nil)
|
||||
)
|
||||
|
||||
// handler logs all errors to STDERR.
|
||||
type handler struct {
|
||||
sync.Mutex
|
||||
delegate oterror.Handler
|
||||
delegate atomic.Value
|
||||
|
||||
l *log.Logger
|
||||
}
|
||||
|
||||
// setDelegate sets the handler delegate if one is not already set.
|
||||
func (h *handler) setDelegate(d oterror.Handler) {
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
if h.delegate != nil {
|
||||
// delegate already registered
|
||||
if h.delegate.Load() != nil {
|
||||
// Delegate already registered
|
||||
return
|
||||
}
|
||||
|
||||
h.delegate = d
|
||||
h.delegate.Store(d)
|
||||
}
|
||||
|
||||
// Handle implements oterror.Handler.
|
||||
func (h *handler) Handle(err error) {
|
||||
if h.delegate != nil {
|
||||
h.delegate.Handle(err)
|
||||
if d := h.delegate.Load(); d != nil {
|
||||
d.(oterror.Handler).Handle(err)
|
||||
return
|
||||
}
|
||||
|
||||
h.Lock()
|
||||
defer h.Unlock()
|
||||
h.l.Print(err)
|
||||
}
|
||||
|
||||
@ -67,15 +70,23 @@ func (h *handler) Handle(err error) {
|
||||
// until an Handler is set (all functionality is delegated to the set
|
||||
// Handler once it is set).
|
||||
func Handler() oterror.Handler {
|
||||
return defaultHandler
|
||||
return globalHandler
|
||||
}
|
||||
|
||||
// SetHandler sets the global Handler to be h.
|
||||
func SetHandler(h oterror.Handler) {
|
||||
defaultHandler.setDelegate(h)
|
||||
delegateHanderOnce.Do(func() {
|
||||
current := Handler()
|
||||
if current == h {
|
||||
return
|
||||
}
|
||||
if internalHandler, ok := current.(*handler); ok {
|
||||
internalHandler.setDelegate(h)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Handle is a convience function for Handler().Handle(err)
|
||||
func Handle(err error) {
|
||||
defaultHandler.Handle(err)
|
||||
globalHandler.Handle(err)
|
||||
}
|
||||
|
@ -44,20 +44,19 @@ type HandlerTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
origHandler *handler
|
||||
|
||||
errLogger *errLogger
|
||||
errLogger *errLogger
|
||||
}
|
||||
|
||||
func (s *HandlerTestSuite) SetupSuite() {
|
||||
s.errLogger = new(errLogger)
|
||||
s.origHandler = defaultHandler
|
||||
defaultHandler = &handler{
|
||||
s.origHandler = globalHandler
|
||||
globalHandler = &handler{
|
||||
l: log.New(s.errLogger, "", 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HandlerTestSuite) TearDownSuite() {
|
||||
defaultHandler = s.origHandler
|
||||
globalHandler = s.origHandler
|
||||
}
|
||||
|
||||
func (s *HandlerTestSuite) SetupTest() {
|
||||
|
Loading…
Reference in New Issue
Block a user