2022-03-09 03:18:32 +08:00
package tracing
import (
"context"
"fmt"
"sync"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.uber.org/zap"
2024-09-14 01:16:37 +08:00
"go.uber.org/zap/zapcore"
2022-03-09 03:18:32 +08:00
)
// globalTracerProvider stores global tracer provider and is responsible for graceful shutdown when nobody is using it.
var globalTracerProvider = & tracerProvider { }
type tracerProvider struct {
mu sync . Mutex
tracerProvider * sdktrace . TracerProvider
tracerProvidersCounter int
}
// getTracerProvider create or return an existing global TracerProvider
func ( t * tracerProvider ) getTracerProvider ( opts ... sdktrace . TracerProviderOption ) * sdktrace . TracerProvider {
t . mu . Lock ( )
defer t . mu . Unlock ( )
t . tracerProvidersCounter ++
if t . tracerProvider == nil {
t . tracerProvider = sdktrace . NewTracerProvider (
opts ... ,
)
}
return t . tracerProvider
}
// cleanupTracerProvider gracefully shutdown a TracerProvider
func ( t * tracerProvider ) cleanupTracerProvider ( logger * zap . Logger ) error {
t . mu . Lock ( )
defer t . mu . Unlock ( )
if t . tracerProvidersCounter > 0 {
t . tracerProvidersCounter --
}
if t . tracerProvidersCounter == 0 {
if t . tracerProvider != nil {
// tracerProvider.ForceFlush SHOULD be invoked according to https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#forceflush
if err := t . tracerProvider . ForceFlush ( context . Background ( ) ) ; err != nil {
2024-09-14 01:16:37 +08:00
if c := logger . Check ( zapcore . ErrorLevel , "forcing flush" ) ; c != nil {
c . Write ( zap . Error ( err ) )
}
2022-03-09 03:18:32 +08:00
}
// tracerProvider.Shutdown MUST be invoked according to https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#shutdown
if err := t . tracerProvider . Shutdown ( context . Background ( ) ) ; err != nil {
return fmt . Errorf ( "tracerProvider shutdown error: %w" , err )
}
}
t . tracerProvider = nil
}
return nil
}