// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package trace // import "go.opentelemetry.io/otel/sdk/trace"

import (
	
	

	
	
)

// simpleSpanProcessor is a SpanProcessor that synchronously sends all
// completed Spans to a trace.Exporter immediately.
type simpleSpanProcessor struct {
	exporterMu sync.Mutex
	exporter   SpanExporter
	stopOnce   sync.Once
}

var _ SpanProcessor = (*simpleSpanProcessor)(nil)

// NewSimpleSpanProcessor returns a new SpanProcessor that will synchronously
// send completed spans to the exporter immediately.
//
// This SpanProcessor is not recommended for production use. The synchronous
// nature of this SpanProcessor makes it good for testing, debugging, or showing
// examples of other features, but it will be slow and have a high computation
// resource usage overhead. The BatchSpanProcessor is recommended for production
// use instead.
func ( SpanExporter) SpanProcessor {
	 := &simpleSpanProcessor{
		exporter: ,
	}
	global.Warn("SimpleSpanProcessor is not recommended for production use, consider using BatchSpanProcessor instead.")

	return 
}

// OnStart does nothing.
func (*simpleSpanProcessor) (context.Context, ReadWriteSpan) {}

// OnEnd immediately exports a ReadOnlySpan.
func ( *simpleSpanProcessor) ( ReadOnlySpan) {
	.exporterMu.Lock()
	defer .exporterMu.Unlock()

	if .exporter != nil && .SpanContext().TraceFlags().IsSampled() {
		if  := .exporter.ExportSpans(context.Background(), []ReadOnlySpan{});  != nil {
			otel.Handle()
		}
	}
}

// Shutdown shuts down the exporter this SimpleSpanProcessor exports to.
func ( *simpleSpanProcessor) ( context.Context) error {
	var  error
	.stopOnce.Do(func() {
		 := func( SpanExporter) (<-chan error, func()) {
			 := make(chan error, 1)
			return , func() {  <- .Shutdown() }
		}

		// The exporter field of the simpleSpanProcessor needs to be zeroed to
		// signal it is shut down, meaning all subsequent calls to OnEnd will
		// be gracefully ignored. This needs to be done synchronously to avoid
		// any race condition.
		//
		// A closure is used to keep reference to the exporter and then the
		// field is zeroed. This ensures the simpleSpanProcessor is shut down
		// before the exporter. This order is important as it avoids a potential
		// deadlock. If the exporter shut down operation generates a span, that
		// span would need to be exported. Meaning, OnEnd would be called and
		// try acquiring the lock that is held here.
		.exporterMu.Lock()
		,  := (.exporter)
		.exporter = nil
		.exporterMu.Unlock()

		go ()

		// Wait for the exporter to shut down or the deadline to expire.
		select {
		case  = <-:
		case <-.Done():
			// It is possible for the exporter to have immediately shut down and
			// the context to be done simultaneously. In that case this outer
			// select statement will randomly choose a case. This will result in
			// a different returned error for similar scenarios. Instead, double
			// check if the exporter shut down at the same time and return that
			// error if so. This will ensure consistency as well as ensure
			// the caller knows the exporter shut down successfully (they can
			// already determine if the deadline is expired given they passed
			// the context).
			select {
			case  = <-:
			default:
				 = .Err()
			}
		}
	})
	return 
}

// ForceFlush does nothing as there is no data to flush.
func (*simpleSpanProcessor) (context.Context) error {
	return nil
}

// MarshalLog is the marshaling function used by the logging system to represent
// this Span Processor.
func ( *simpleSpanProcessor) () any {
	return struct {
		     string
		 SpanExporter
	}{
		:     "SimpleSpanProcessor",
		: .exporter,
	}
}