From afb01a74de439b3993ec383d5aae66c5b303fcaf Mon Sep 17 00:00:00 2001 From: Gahl Saraf Date: Sat, 6 Aug 2022 21:47:13 +0300 Subject: [PATCH] Solve panic due to concurrent access to ExportSpans Signed-off-by: Gahl Saraf --- util/tracing/detect/detect.go | 22 ++++++++++++++++------ util/tracing/detect/threadsafe.go | 26 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 util/tracing/detect/threadsafe.go diff --git a/util/tracing/detect/detect.go b/util/tracing/detect/detect.go index e005b14d0dfe..13e54bdefc01 100644 --- a/util/tracing/detect/detect.go +++ b/util/tracing/detect/detect.go @@ -73,21 +73,31 @@ func detectExporter() (sdktrace.SpanExporter, error) { return nil, nil } -func detect() error { - tp = trace.NewNoopTracerProvider() - +func getExporter() (sdktrace.SpanExporter, error) { exp, err := detectExporter() if err != nil { - return err + return nil, err + } + + if exp != nil { + exp = &threadSafeExporterWrapper{ + exporter: exp, + } } if Recorder != nil { Recorder.SpanExporter = exp exp = Recorder } + return exp, nil +} + +func detect() error { + tp = trace.NewNoopTracerProvider() - if exp == nil { - return nil + exp, err := getExporter() + if err != nil || exp == nil { + return err } // enable log with traceID when valid exporter diff --git a/util/tracing/detect/threadsafe.go b/util/tracing/detect/threadsafe.go new file mode 100644 index 000000000000..51d14448dfed --- /dev/null +++ b/util/tracing/detect/threadsafe.go @@ -0,0 +1,26 @@ +package detect + +import ( + "context" + "sync" + + sdktrace "go.opentelemetry.io/otel/sdk/trace" +) + +// threadSafeExporterWrapper wraps an OpenTelemetry SpanExporter and makes it thread-safe. +type threadSafeExporterWrapper struct { + mu sync.Mutex + exporter sdktrace.SpanExporter +} + +func (tse *threadSafeExporterWrapper) ExportSpans(ctx context.Context, spans []sdktrace.ReadOnlySpan) error { + tse.mu.Lock() + defer tse.mu.Unlock() + return tse.exporter.ExportSpans(ctx, spans) +} + +func (tse *threadSafeExporterWrapper) Shutdown(ctx context.Context) error { + tse.mu.Lock() + defer tse.mu.Unlock() + return tse.exporter.Shutdown(ctx) +}