From e5587114e9c04933bf0afd16517921a2dc1299e8 Mon Sep 17 00:00:00 2001 From: Pavol Loffay Date: Wed, 2 Sep 2020 10:12:37 +0200 Subject: [PATCH] Use queue retry per exporter (#2444) * Use queue retry per exporter Signed-off-by: Pavol Loffay * enable qretry by default Signed-off-by: Pavol Loffay --- .../app/defaultconfig/default_config.go | 4 ---- .../app/defaultconfig/default_config_test.go | 10 ++++---- .../app/exporter/badgerexporter/config.go | 9 ++++++-- .../app/exporter/badgerexporter/factory.go | 23 +++++++++++-------- .../exporter/badgerexporter/factory_test.go | 7 ------ .../app/exporter/cassandraexporter/config.go | 9 ++++++-- .../exporter/cassandraexporter/exporter.go | 6 ++++- .../app/exporter/cassandraexporter/factory.go | 12 +++++----- .../cassandraexporter/factory_test.go | 7 ------ .../exporter/elasticsearchexporter/config.go | 9 ++++++-- .../elasticsearchexporter/exporter.go | 3 +++ .../exporter/elasticsearchexporter/factory.go | 6 ++++- .../app/exporter/grpcpluginexporter/config.go | 9 ++++++-- .../exporter/grpcpluginexporter/exporter.go | 6 ++++- .../exporter/grpcpluginexporter/factory.go | 13 ++++++----- .../grpcpluginexporter/factory_test.go | 7 ------ .../app/exporter/span_writer_exporter.go | 15 ++++++------ 17 files changed, 85 insertions(+), 70 deletions(-) diff --git a/cmd/opentelemetry/app/defaultconfig/default_config.go b/cmd/opentelemetry/app/defaultconfig/default_config.go index ec93868947e..d0e372cc4b8 100644 --- a/cmd/opentelemetry/app/defaultconfig/default_config.go +++ b/cmd/opentelemetry/app/defaultconfig/default_config.go @@ -24,7 +24,6 @@ import ( "go.opentelemetry.io/collector/config/configmodels" "go.opentelemetry.io/collector/config/confignet" "go.opentelemetry.io/collector/processor/batchprocessor" - "go.opentelemetry.io/collector/processor/queuedprocessor" "go.opentelemetry.io/collector/processor/resourceprocessor" "go.opentelemetry.io/collector/receiver/jaegerreceiver" "go.opentelemetry.io/collector/receiver/zipkinreceiver" @@ -107,9 +106,6 @@ func createProcessors(factories component.Factories) (configmodels.Processors, [ batch := factories.Processors["batch"].CreateDefaultConfig().(*batchprocessor.Config) processors[batch.Name()] = batch names = append(names, batch.Name()) - queuedRetry := factories.Processors["queued_retry"].CreateDefaultConfig().(*queuedprocessor.Config) - processors[queuedRetry.Name()] = queuedRetry - names = append(names, queuedRetry.Name()) return processors, names } diff --git a/cmd/opentelemetry/app/defaultconfig/default_config_test.go b/cmd/opentelemetry/app/defaultconfig/default_config_test.go index 5fddab7a59a..bff1c7ebae9 100644 --- a/cmd/opentelemetry/app/defaultconfig/default_config_test.go +++ b/cmd/opentelemetry/app/defaultconfig/default_config_test.go @@ -53,7 +53,7 @@ func TestService(t *testing.T) { "traces": &configmodels.Pipeline{ InputType: configmodels.TracesDataType, Receivers: []string{"otlp", "jaeger"}, - Processors: []string{"batch", "queued_retry"}, + Processors: []string{"batch"}, Exporters: []string{"jaeger"}, }, }, @@ -71,7 +71,7 @@ func TestService(t *testing.T) { "traces": &configmodels.Pipeline{ InputType: configmodels.TracesDataType, Receivers: []string{"otlp", "jaeger"}, - Processors: []string{"resource", "batch", "queued_retry"}, + Processors: []string{"resource", "batch"}, Exporters: []string{elasticsearchexporter.TypeStr, kafkaexporter.TypeStr, memoryexporter.TypeStr}, }, }, @@ -88,7 +88,7 @@ func TestService(t *testing.T) { "traces": &configmodels.Pipeline{ InputType: configmodels.TracesDataType, Receivers: []string{kafkareceiver.TypeStr}, - Processors: []string{"batch", "queued_retry"}, + Processors: []string{"batch"}, Exporters: []string{elasticsearchexporter.TypeStr}, }, }, @@ -105,7 +105,7 @@ func TestService(t *testing.T) { "traces": &configmodels.Pipeline{ InputType: configmodels.TracesDataType, Receivers: []string{kafkareceiver.TypeStr}, - Processors: []string{"batch", "queued_retry"}, + Processors: []string{"batch"}, Exporters: []string{cassandraexporter.TypeStr, elasticsearchexporter.TypeStr, grpcpluginexporter.TypeStr}, }, }, @@ -123,7 +123,7 @@ func TestService(t *testing.T) { "traces": &configmodels.Pipeline{ InputType: configmodels.TracesDataType, Receivers: []string{"otlp", "jaeger", "zipkin"}, - Processors: []string{"batch", "queued_retry"}, + Processors: []string{"batch"}, Exporters: []string{elasticsearchexporter.TypeStr}, }, }, diff --git a/cmd/opentelemetry/app/exporter/badgerexporter/config.go b/cmd/opentelemetry/app/exporter/badgerexporter/config.go index 81ea7b45764..57ca58da950 100644 --- a/cmd/opentelemetry/app/exporter/badgerexporter/config.go +++ b/cmd/opentelemetry/app/exporter/badgerexporter/config.go @@ -16,12 +16,17 @@ package badgerexporter import ( "go.opentelemetry.io/collector/config/configmodels" + "go.opentelemetry.io/collector/exporter/exporterhelper" "github.com/jaegertracing/jaeger/plugin/storage/badger" ) // Config holds configuration of Jaeger Badger exporter/storage. type Config struct { - badger.Options `mapstructure:",squash"` - configmodels.ExporterSettings `mapstructure:",squash"` + configmodels.ExporterSettings `mapstructure:",squash"` + exporterhelper.TimeoutSettings `mapstructure:",squash"` + exporterhelper.QueueSettings `mapstructure:"sending_queue"` + exporterhelper.RetrySettings `mapstructure:"retry_on_failure"` + + badger.Options `mapstructure:",squash"` } diff --git a/cmd/opentelemetry/app/exporter/badgerexporter/factory.go b/cmd/opentelemetry/app/exporter/badgerexporter/factory.go index 7b7e42ea997..35c8add027b 100644 --- a/cmd/opentelemetry/app/exporter/badgerexporter/factory.go +++ b/cmd/opentelemetry/app/exporter/badgerexporter/factory.go @@ -16,13 +16,13 @@ package badgerexporter import ( "context" - "fmt" "sync" "github.com/uber/jaeger-lib/metrics" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configerror" "go.opentelemetry.io/collector/config/configmodels" + "go.opentelemetry.io/collector/exporter/exporterhelper" "github.com/jaegertracing/jaeger/cmd/opentelemetry/app/exporter" "github.com/jaegertracing/jaeger/plugin/storage/badger" @@ -78,11 +78,14 @@ func (f Factory) Type() configmodels.Type { func (f Factory) CreateDefaultConfig() configmodels.Exporter { opts := f.optionsFactory() return &Config{ - Options: *opts, ExporterSettings: configmodels.ExporterSettings{ TypeVal: TypeStr, NameVal: TypeStr, }, + TimeoutSettings: exporterhelper.CreateDefaultTimeoutSettings(), + RetrySettings: exporterhelper.CreateDefaultRetrySettings(), + QueueSettings: exporterhelper.CreateDefaultQueueSettings(), + Options: *opts, } } @@ -93,11 +96,15 @@ func (f Factory) CreateTraceExporter( params component.ExporterCreateParams, cfg configmodels.Exporter, ) (component.TraceExporter, error) { - factory, err := f.createStorageFactory(params, cfg) + config := cfg.(*Config) + factory, err := f.createStorageFactory(params, config) if err != nil { return nil, err } - return exporter.NewSpanWriterExporter(cfg, factory) + return exporter.NewSpanWriterExporter(cfg, factory, + exporterhelper.WithTimeout(config.TimeoutSettings), + exporterhelper.WithQueue(config.QueueSettings), + exporterhelper.WithRetry(config.RetrySettings)) } // CreateMetricsExporter is not implemented. @@ -110,18 +117,14 @@ func (f Factory) CreateMetricsExporter( return nil, configerror.ErrDataTypeIsNotSupported } -func (f Factory) createStorageFactory(params component.ExporterCreateParams, cfg configmodels.Exporter) (storage.Factory, error) { - config, ok := cfg.(*Config) - if !ok { - return nil, fmt.Errorf("could not cast configuration to %s", TypeStr) - } +func (f Factory) createStorageFactory(params component.ExporterCreateParams, cfg *Config) (storage.Factory, error) { f.mutex.Lock() defer f.mutex.Unlock() if instance != nil { return instance, nil } factory := badger.NewFactory() - factory.InitFromOptions(config.Options) + factory.InitFromOptions(cfg.Options) err := factory.Initialize(metrics.NullFactory, params.Logger) if err != nil { return nil, err diff --git a/cmd/opentelemetry/app/exporter/badgerexporter/factory_test.go b/cmd/opentelemetry/app/exporter/badgerexporter/factory_test.go index 283c65d2d23..ef280f64699 100644 --- a/cmd/opentelemetry/app/exporter/badgerexporter/factory_test.go +++ b/cmd/opentelemetry/app/exporter/badgerexporter/factory_test.go @@ -42,13 +42,6 @@ func TestCreateTraceExporter(t *testing.T) { assert.NotNil(t, exporter) } -func TestCreateTraceExporter_NilConfig(t *testing.T) { - factory := Factory{} - exporter, err := factory.CreateTraceExporter(context.Background(), component.ExporterCreateParams{}, nil) - require.Nil(t, exporter) - assert.Contains(t, err.Error(), "could not cast configuration to jaeger_badger") -} - func TestCreateDefaultConfig(t *testing.T) { factory := NewFactory(DefaultOptions) cfg := factory.CreateDefaultConfig() diff --git a/cmd/opentelemetry/app/exporter/cassandraexporter/config.go b/cmd/opentelemetry/app/exporter/cassandraexporter/config.go index ed32d76bec9..c4222b67342 100644 --- a/cmd/opentelemetry/app/exporter/cassandraexporter/config.go +++ b/cmd/opentelemetry/app/exporter/cassandraexporter/config.go @@ -16,12 +16,17 @@ package cassandraexporter import ( "go.opentelemetry.io/collector/config/configmodels" + "go.opentelemetry.io/collector/exporter/exporterhelper" "github.com/jaegertracing/jaeger/plugin/storage/cassandra" ) // Config holds configuration of Jaeger Cassandra exporter/storage. type Config struct { - configmodels.ExporterSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. - cassandra.Options `mapstructure:",squash"` + configmodels.ExporterSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. + exporterhelper.TimeoutSettings `mapstructure:",squash"` + exporterhelper.QueueSettings `mapstructure:"sending_queue"` + exporterhelper.RetrySettings `mapstructure:"retry_on_failure"` + + cassandra.Options `mapstructure:",squash"` } diff --git a/cmd/opentelemetry/app/exporter/cassandraexporter/exporter.go b/cmd/opentelemetry/app/exporter/cassandraexporter/exporter.go index bd6b60d26a1..74234e0bf32 100644 --- a/cmd/opentelemetry/app/exporter/cassandraexporter/exporter.go +++ b/cmd/opentelemetry/app/exporter/cassandraexporter/exporter.go @@ -17,6 +17,7 @@ package cassandraexporter import ( "github.com/uber/jaeger-lib/metrics" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/exporter/exporterhelper" "github.com/jaegertracing/jaeger/cmd/opentelemetry/app/exporter" "github.com/jaegertracing/jaeger/plugin/storage/cassandra" @@ -31,5 +32,8 @@ func new(config *Config, params component.ExporterCreateParams) (component.Trace if err != nil { return nil, err } - return exporter.NewSpanWriterExporter(config, f) + return exporter.NewSpanWriterExporter(config, f, + exporterhelper.WithTimeout(config.TimeoutSettings), + exporterhelper.WithQueue(config.QueueSettings), + exporterhelper.WithRetry(config.RetrySettings)) } diff --git a/cmd/opentelemetry/app/exporter/cassandraexporter/factory.go b/cmd/opentelemetry/app/exporter/cassandraexporter/factory.go index f4e4b2ca149..0173d1cad24 100644 --- a/cmd/opentelemetry/app/exporter/cassandraexporter/factory.go +++ b/cmd/opentelemetry/app/exporter/cassandraexporter/factory.go @@ -16,11 +16,11 @@ package cassandraexporter import ( "context" - "fmt" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configerror" "go.opentelemetry.io/collector/config/configmodels" + "go.opentelemetry.io/collector/exporter/exporterhelper" "github.com/jaegertracing/jaeger/plugin/storage/cassandra" ) @@ -55,11 +55,14 @@ func (Factory) Type() configmodels.Type { func (f Factory) CreateDefaultConfig() configmodels.Exporter { opts := f.OptionsFactory() return &Config{ - Options: *opts, ExporterSettings: configmodels.ExporterSettings{ TypeVal: TypeStr, NameVal: TypeStr, }, + TimeoutSettings: exporterhelper.CreateDefaultTimeoutSettings(), + RetrySettings: exporterhelper.CreateDefaultRetrySettings(), + QueueSettings: exporterhelper.CreateDefaultQueueSettings(), + Options: *opts, } } @@ -70,10 +73,7 @@ func (f Factory) CreateTraceExporter( params component.ExporterCreateParams, cfg configmodels.Exporter, ) (component.TraceExporter, error) { - config, ok := cfg.(*Config) - if !ok { - return nil, fmt.Errorf("could not cast configuration to %s", TypeStr) - } + config := cfg.(*Config) return new(config, params) } diff --git a/cmd/opentelemetry/app/exporter/cassandraexporter/factory_test.go b/cmd/opentelemetry/app/exporter/cassandraexporter/factory_test.go index f10c9ad8f79..ebf055c4262 100644 --- a/cmd/opentelemetry/app/exporter/cassandraexporter/factory_test.go +++ b/cmd/opentelemetry/app/exporter/cassandraexporter/factory_test.go @@ -41,13 +41,6 @@ func TestCreateTraceExporter(t *testing.T) { assert.Contains(t, err.Error(), "gocql: unable to create session") } -func TestCreateTraceExporter_NilConfig(t *testing.T) { - factory := Factory{} - exporter, err := factory.CreateTraceExporter(context.Background(), component.ExporterCreateParams{}, nil) - require.Nil(t, exporter) - assert.Contains(t, err.Error(), "could not cast configuration to jaeger_cassandra") -} - func TestCreateDefaultConfig(t *testing.T) { factory := Factory{OptionsFactory: DefaultOptions} cfg := factory.CreateDefaultConfig() diff --git a/cmd/opentelemetry/app/exporter/elasticsearchexporter/config.go b/cmd/opentelemetry/app/exporter/elasticsearchexporter/config.go index 7533e4e3fcd..380a16fe58e 100644 --- a/cmd/opentelemetry/app/exporter/elasticsearchexporter/config.go +++ b/cmd/opentelemetry/app/exporter/elasticsearchexporter/config.go @@ -16,12 +16,17 @@ package elasticsearchexporter import ( "go.opentelemetry.io/collector/config/configmodels" + "go.opentelemetry.io/collector/exporter/exporterhelper" "github.com/jaegertracing/jaeger/plugin/storage/es" ) // Config holds configuration of Jaeger Elasticsearch exporter/storage. type Config struct { - configmodels.ExporterSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. - es.Options `mapstructure:",squash"` + configmodels.ExporterSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. + exporterhelper.TimeoutSettings `mapstructure:",squash"` + exporterhelper.QueueSettings `mapstructure:"sending_queue"` + exporterhelper.RetrySettings `mapstructure:"retry_on_failure"` + + es.Options `mapstructure:",squash"` } diff --git a/cmd/opentelemetry/app/exporter/elasticsearchexporter/exporter.go b/cmd/opentelemetry/app/exporter/elasticsearchexporter/exporter.go index db1f7f9f8ff..1e837e66a19 100644 --- a/cmd/opentelemetry/app/exporter/elasticsearchexporter/exporter.go +++ b/cmd/opentelemetry/app/exporter/elasticsearchexporter/exporter.go @@ -39,6 +39,9 @@ func new(ctx context.Context, config *Config, params component.ExporterCreatePar return exporterhelper.NewTraceExporter( config, w.WriteTraces, + exporterhelper.WithTimeout(config.TimeoutSettings), + exporterhelper.WithQueue(config.QueueSettings), + exporterhelper.WithRetry(config.RetrySettings), exporterhelper.WithShutdown(func(ctx context.Context) error { return esCfg.TLS.Close() })) diff --git a/cmd/opentelemetry/app/exporter/elasticsearchexporter/factory.go b/cmd/opentelemetry/app/exporter/elasticsearchexporter/factory.go index 5105311eebd..8d42c88745b 100644 --- a/cmd/opentelemetry/app/exporter/elasticsearchexporter/factory.go +++ b/cmd/opentelemetry/app/exporter/elasticsearchexporter/factory.go @@ -21,6 +21,7 @@ import ( "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configerror" "go.opentelemetry.io/collector/config/configmodels" + "go.opentelemetry.io/collector/exporter/exporterhelper" "github.com/jaegertracing/jaeger/plugin/storage/es" ) @@ -55,11 +56,14 @@ var _ component.ExporterFactory = (*Factory)(nil) func (f Factory) CreateDefaultConfig() configmodels.Exporter { opts := f.OptionsFactory() return &Config{ - Options: *opts, ExporterSettings: configmodels.ExporterSettings{ TypeVal: TypeStr, NameVal: TypeStr, }, + TimeoutSettings: exporterhelper.CreateDefaultTimeoutSettings(), + RetrySettings: exporterhelper.CreateDefaultRetrySettings(), + QueueSettings: exporterhelper.CreateDefaultQueueSettings(), + Options: *opts, } } diff --git a/cmd/opentelemetry/app/exporter/grpcpluginexporter/config.go b/cmd/opentelemetry/app/exporter/grpcpluginexporter/config.go index 8a12d3e9cd8..715c130dfbf 100644 --- a/cmd/opentelemetry/app/exporter/grpcpluginexporter/config.go +++ b/cmd/opentelemetry/app/exporter/grpcpluginexporter/config.go @@ -16,12 +16,17 @@ package grpcpluginexporter import ( "go.opentelemetry.io/collector/config/configmodels" + "go.opentelemetry.io/collector/exporter/exporterhelper" grpcStorage "github.com/jaegertracing/jaeger/plugin/storage/grpc" ) // Config holds configuration of Jaeger gRPC exporter/storage. type Config struct { - configmodels.ExporterSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. - grpcStorage.Options `mapstructure:",squash"` + configmodels.ExporterSettings `mapstructure:",squash"` // squash ensures fields are correctly decoded in embedded struct. + exporterhelper.TimeoutSettings `mapstructure:",squash"` + exporterhelper.QueueSettings `mapstructure:"sending_queue"` + exporterhelper.RetrySettings `mapstructure:"retry_on_failure"` + + grpcStorage.Options `mapstructure:",squash"` } diff --git a/cmd/opentelemetry/app/exporter/grpcpluginexporter/exporter.go b/cmd/opentelemetry/app/exporter/grpcpluginexporter/exporter.go index 3c426c74d95..c9ba8dda60b 100644 --- a/cmd/opentelemetry/app/exporter/grpcpluginexporter/exporter.go +++ b/cmd/opentelemetry/app/exporter/grpcpluginexporter/exporter.go @@ -17,6 +17,7 @@ package grpcpluginexporter import ( "github.com/uber/jaeger-lib/metrics" "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/exporter/exporterhelper" storageOtelExporter "github.com/jaegertracing/jaeger/cmd/opentelemetry/app/exporter" storageGrpc "github.com/jaegertracing/jaeger/plugin/storage/grpc" @@ -30,5 +31,8 @@ func new(config *Config, params component.ExporterCreateParams) (component.Trace if err != nil { return nil, err } - return storageOtelExporter.NewSpanWriterExporter(&config.ExporterSettings, factory) + return storageOtelExporter.NewSpanWriterExporter(&config.ExporterSettings, factory, + exporterhelper.WithTimeout(config.TimeoutSettings), + exporterhelper.WithQueue(config.QueueSettings), + exporterhelper.WithRetry(config.RetrySettings)) } diff --git a/cmd/opentelemetry/app/exporter/grpcpluginexporter/factory.go b/cmd/opentelemetry/app/exporter/grpcpluginexporter/factory.go index 8b22ca9f541..1683cb4ed96 100644 --- a/cmd/opentelemetry/app/exporter/grpcpluginexporter/factory.go +++ b/cmd/opentelemetry/app/exporter/grpcpluginexporter/factory.go @@ -16,11 +16,11 @@ package grpcpluginexporter import ( "context" - "fmt" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/config/configerror" "go.opentelemetry.io/collector/config/configmodels" + "go.opentelemetry.io/collector/exporter/exporterhelper" storageGrpc "github.com/jaegertracing/jaeger/plugin/storage/grpc" ) @@ -53,11 +53,15 @@ func (f Factory) Type() configmodels.Type { func (f Factory) CreateDefaultConfig() configmodels.Exporter { opts := f.OptionsFactory() return &Config{ - Options: *opts, ExporterSettings: configmodels.ExporterSettings{ TypeVal: TypeStr, NameVal: TypeStr, }, + TimeoutSettings: exporterhelper.CreateDefaultTimeoutSettings(), + RetrySettings: exporterhelper.CreateDefaultRetrySettings(), + QueueSettings: exporterhelper.CreateDefaultQueueSettings(), + + Options: *opts, } } @@ -68,10 +72,7 @@ func (f Factory) CreateTraceExporter( params component.ExporterCreateParams, cfg configmodels.Exporter, ) (component.TraceExporter, error) { - grpcCfg, ok := cfg.(*Config) - if !ok { - return nil, fmt.Errorf("could not cast configuration to %s", TypeStr) - } + grpcCfg := cfg.(*Config) return new(grpcCfg, params) } diff --git a/cmd/opentelemetry/app/exporter/grpcpluginexporter/factory_test.go b/cmd/opentelemetry/app/exporter/grpcpluginexporter/factory_test.go index 6025f5329e0..b0d1b649520 100644 --- a/cmd/opentelemetry/app/exporter/grpcpluginexporter/factory_test.go +++ b/cmd/opentelemetry/app/exporter/grpcpluginexporter/factory_test.go @@ -41,13 +41,6 @@ func TestCreateTraceExporter(t *testing.T) { assert.Contains(t, err.Error(), "error attempting to connect to plugin rpc client: fork/exec : no such file or directory") } -func TestCreateTraceExporter_nilConfig(t *testing.T) { - factory := &Factory{} - exporter, err := factory.CreateTraceExporter(context.Background(), component.ExporterCreateParams{}, nil) - require.Nil(t, exporter) - assert.Contains(t, err.Error(), "could not cast configuration to jaeger_grpc_plugin") -} - func TestCreateMetricsExporter(t *testing.T) { f := Factory{OptionsFactory: DefaultOptions} mReceiver, err := f.CreateMetricsExporter(context.Background(), component.ExporterCreateParams{}, f.CreateDefaultConfig()) diff --git a/cmd/opentelemetry/app/exporter/span_writer_exporter.go b/cmd/opentelemetry/app/exporter/span_writer_exporter.go index e5ad8885b47..edb78031530 100644 --- a/cmd/opentelemetry/app/exporter/span_writer_exporter.go +++ b/cmd/opentelemetry/app/exporter/span_writer_exporter.go @@ -31,21 +31,22 @@ import ( ) // NewSpanWriterExporter returns component.TraceExporter -func NewSpanWriterExporter(config configmodels.Exporter, factory storage.Factory) (component.TraceExporter, error) { +func NewSpanWriterExporter(config configmodels.Exporter, factory storage.Factory, opts ...exporterhelper.ExporterOption) (component.TraceExporter, error) { spanWriter, err := factory.CreateSpanWriter() if err != nil { return nil, err } storage := store{Writer: spanWriter} + opts = append(opts, exporterhelper.WithShutdown(func(ctx context.Context) error { + if closer, ok := spanWriter.(io.Closer); ok { + return closer.Close() + } + return nil + })) return exporterhelper.NewTraceExporter( config, storage.traceDataPusher, - exporterhelper.WithShutdown(func(context.Context) error { - if closer, ok := spanWriter.(io.Closer); ok { - return closer.Close() - } - return nil - })) + opts...) } type store struct {