@@ -20,14 +20,17 @@ type fanoutExporter struct {
2020// When only one exporter is provided it is returned directly to avoid overhead.
2121func newFanoutExporter (exporters []sdktrace.SpanExporter ) sdktrace.SpanExporter {
2222 if len (exporters ) == 1 {
23+ logTracing .Printf ("newFanoutExporter: single exporter, bypassing fanout" )
2324 return exporters [0 ]
2425 }
26+ logTracing .Printf ("newFanoutExporter: creating fanout exporter with %d backends" , len (exporters ))
2527 return & fanoutExporter {exporters : exporters }
2628}
2729
2830// forEachExporter calls fn on each underlying exporter concurrently,
29- // collecting and joining all errors.
30- func (f * fanoutExporter ) forEachExporter (fn func (sdktrace.SpanExporter ) error ) error {
31+ // collecting and joining all errors. The op label is used in debug log
32+ // messages to identify which operation is running.
33+ func (f * fanoutExporter ) forEachExporter (op string , fn func (sdktrace.SpanExporter ) error ) error {
3134 var (
3235 wg sync.WaitGroup
3336 mu sync.Mutex
@@ -38,13 +41,17 @@ func (f *fanoutExporter) forEachExporter(fn func(sdktrace.SpanExporter) error) e
3841 go func (e sdktrace.SpanExporter ) {
3942 defer wg .Done ()
4043 if err := fn (e ); err != nil {
44+ logTracing .Printf ("fanoutExporter.%s: backend (%T) error: %v" , op , e , err )
4145 mu .Lock ()
4246 errs = append (errs , err )
4347 mu .Unlock ()
4448 }
4549 }(exp )
4650 }
4751 wg .Wait ()
52+ if len (errs ) > 0 {
53+ logTracing .Printf ("fanoutExporter.%s: %d/%d backends failed" , op , len (errs ), len (f .exporters ))
54+ }
4855 return errors .Join (errs ... )
4956}
5057
@@ -53,15 +60,19 @@ func (f *fanoutExporter) forEachExporter(fn func(sdktrace.SpanExporter) error) e
5360// delay delivery to the others. Errors from all exporters are collected and
5461// joined before returning.
5562func (f * fanoutExporter ) ExportSpans (ctx context.Context , spans []sdktrace.ReadOnlySpan ) error {
56- return f .forEachExporter (func (e sdktrace.SpanExporter ) error {
63+ logTracing .Printf ("fanoutExporter.ExportSpans: exporting %d spans to %d backends" , len (spans ), len (f .exporters ))
64+ return f .forEachExporter ("ExportSpans" , func (e sdktrace.SpanExporter ) error {
5765 return e .ExportSpans (ctx , spans )
5866 })
5967}
6068
6169// Shutdown shuts down each underlying exporter concurrently, collecting any
6270// errors. All errors are joined and returned.
6371func (f * fanoutExporter ) Shutdown (ctx context.Context ) error {
64- return f .forEachExporter (func (e sdktrace.SpanExporter ) error {
72+ logTracing .Printf ("fanoutExporter.Shutdown: shutting down %d backends" , len (f .exporters ))
73+ err := f .forEachExporter ("Shutdown" , func (e sdktrace.SpanExporter ) error {
6574 return e .Shutdown (ctx )
6675 })
76+ logTracing .Printf ("fanoutExporter.Shutdown: completed" )
77+ return err
6778}
0 commit comments