1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-11-25 22:41:46 +02:00

small contingency improvement in global error handler (#3543)

Signed-off-by: Bogdan Drutu <bogdandrutu@gmail.com>

Signed-off-by: Bogdan Drutu <bogdandrutu@gmail.com>
This commit is contained in:
Bogdan Drutu
2022-12-16 11:38:01 -08:00
committed by GitHub
parent 7a60bc785d
commit ca4cdfe4c0
3 changed files with 19 additions and 16 deletions

View File

@@ -16,6 +16,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Add `Producer` interface and `Reader.RegisterProducer(Producer)` to `go.opentelemetry.io/otel/sdk/metric` to enable external metric Producers. (#3524) - Add `Producer` interface and `Reader.RegisterProducer(Producer)` to `go.opentelemetry.io/otel/sdk/metric` to enable external metric Producers. (#3524)
### Changed
- Global error handler uses an atomic value instead of a mutex. (#3543)
## [1.11.2/0.34.0] 2022-12-05 ## [1.11.2/0.34.0] 2022-12-05
### Added ### Added

View File

@@ -17,7 +17,8 @@ package otel // import "go.opentelemetry.io/otel"
import ( import (
"log" "log"
"os" "os"
"sync" "sync/atomic"
"unsafe"
) )
var ( var (
@@ -34,28 +35,26 @@ var (
) )
type delegator struct { type delegator struct {
lock *sync.RWMutex delegate unsafe.Pointer
eh ErrorHandler
} }
func (d *delegator) Handle(err error) { func (d *delegator) Handle(err error) {
d.lock.RLock() d.getDelegate().Handle(err)
defer d.lock.RUnlock() }
d.eh.Handle(err)
func (d *delegator) getDelegate() ErrorHandler {
return *(*ErrorHandler)(atomic.LoadPointer(&d.delegate))
} }
// setDelegate sets the ErrorHandler delegate. // setDelegate sets the ErrorHandler delegate.
func (d *delegator) setDelegate(eh ErrorHandler) { func (d *delegator) setDelegate(eh ErrorHandler) {
d.lock.Lock() atomic.StorePointer(&d.delegate, unsafe.Pointer(&eh))
defer d.lock.Unlock()
d.eh = eh
} }
func defaultErrorHandler() *delegator { func defaultErrorHandler() *delegator {
return &delegator{ d := &delegator{}
lock: &sync.RWMutex{}, d.setDelegate(&errLogger{l: log.New(os.Stderr, "", log.LstdFlags)})
eh: &errLogger{l: log.New(os.Stderr, "", log.LstdFlags)}, return d
}
} }
// errLogger logs errors if no delegate is set, otherwise they are delegated. // errLogger logs errors if no delegate is set, otherwise they are delegated.

View File

@@ -54,7 +54,7 @@ type HandlerTestSuite struct {
func (s *HandlerTestSuite) SetupSuite() { func (s *HandlerTestSuite) SetupSuite() {
s.errCatcher = new(testErrCatcher) s.errCatcher = new(testErrCatcher)
s.origHandler = globalErrorHandler.eh s.origHandler = globalErrorHandler.getDelegate()
globalErrorHandler.setDelegate(&errLogger{l: log.New(s.errCatcher, "", 0)}) globalErrorHandler.setDelegate(&errLogger{l: log.New(s.errCatcher, "", 0)})
} }
@@ -111,12 +111,12 @@ func (s *HandlerTestSuite) TestAllowMultipleSets() {
secondary := &errLogger{l: log.New(notUsed, "", 0)} secondary := &errLogger{l: log.New(notUsed, "", 0)}
SetErrorHandler(secondary) SetErrorHandler(secondary)
s.Require().Same(GetErrorHandler(), globalErrorHandler, "set changed globalErrorHandler") s.Require().Same(GetErrorHandler(), globalErrorHandler, "set changed globalErrorHandler")
s.Require().Same(globalErrorHandler.eh, secondary, "new Handler not set") s.Require().Same(globalErrorHandler.getDelegate(), secondary, "new Handler not set")
tertiary := &errLogger{l: log.New(notUsed, "", 0)} tertiary := &errLogger{l: log.New(notUsed, "", 0)}
SetErrorHandler(tertiary) SetErrorHandler(tertiary)
s.Require().Same(GetErrorHandler(), globalErrorHandler, "set changed globalErrorHandler") s.Require().Same(GetErrorHandler(), globalErrorHandler, "set changed globalErrorHandler")
s.Assert().Same(globalErrorHandler.eh, tertiary, "user Handler not overridden") s.Assert().Same(globalErrorHandler.getDelegate(), tertiary, "user Handler not overridden")
} }
func TestHandlerTestSuite(t *testing.T) { func TestHandlerTestSuite(t *testing.T) {