diff --git a/CHANGELOG.md b/CHANGELOG.md index 89f53c89f61..4f0962f4cf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Added +- The OTLP exporter now has two new convenience functions, `NewExportPipeline` and `InstallNewPipeline`, setup and install the exporter in tracing and metrics pipelines. (#1373) - Adds test to check BatchSpanProcessor ignores `OnEnd` and `ForceFlush` post `Shutdown`. (#1772) - Option `ExportTimeout` was added to batch span processor. (#1755) - Adds semantic conventions for exceptions. (#1492) diff --git a/exporters/otlp/otlp.go b/exporters/otlp/otlp.go index ce43da2c916..098d93b423a 100644 --- a/exporters/otlp/otlp.go +++ b/exporters/otlp/otlp.go @@ -19,9 +19,15 @@ import ( "errors" "sync" + "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/metric" metricsdk "go.opentelemetry.io/otel/sdk/export/metric" "go.opentelemetry.io/otel/sdk/export/metric/aggregation" + "go.opentelemetry.io/otel/sdk/metric/selector/simple" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + + "go.opentelemetry.io/otel/sdk/metric/controller/basic" + processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" tracesdk "go.opentelemetry.io/otel/sdk/trace" ) @@ -128,3 +134,46 @@ func (e *Exporter) ExportKindFor(desc *metric.Descriptor, kind aggregation.Kind) func (e *Exporter) ExportSpans(ctx context.Context, ss []*tracesdk.SpanSnapshot) error { return e.driver.ExportTraces(ctx, ss) } + +// NewExportPipeline sets up a complete export pipeline +// with the recommended TracerProvider setup. +func NewExportPipeline(ctx context.Context, driver ProtocolDriver, exporterOpts ...ExporterOption) (*Exporter, + *sdktrace.TracerProvider, *basic.Controller, error) { + + exp, err := NewExporter(ctx, driver, exporterOpts...) + if err != nil { + return nil, nil, nil, err + } + + tracerProvider := sdktrace.NewTracerProvider( + sdktrace.WithBatcher(exp), + ) + + cntr := basic.New( + processor.New( + simple.NewWithInexpensiveDistribution(), + exp, + ), + ) + + return exp, tracerProvider, cntr, nil +} + +// InstallNewPipeline instantiates a NewExportPipeline with the +// recommended configuration and registers it globally. +func InstallNewPipeline(ctx context.Context, driver ProtocolDriver, exporterOpts ...ExporterOption) (*Exporter, + *sdktrace.TracerProvider, *basic.Controller, error) { + + exp, tp, cntr, err := NewExportPipeline(ctx, driver, exporterOpts...) + if err != nil { + return nil, nil, nil, err + } + + otel.SetTracerProvider(tp) + err = cntr.Start(ctx) + if err != nil { + return nil, nil, nil, err + } + + return exp, tp, cntr, err +} diff --git a/exporters/otlp/otlp_test.go b/exporters/otlp/otlp_test.go index c9a30e901eb..c24c8ab5c60 100644 --- a/exporters/otlp/otlp_test.go +++ b/exporters/otlp/otlp_test.go @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp" "go.opentelemetry.io/otel/exporters/otlp/internal/transform" metricsdk "go.opentelemetry.io/otel/sdk/export/metric" @@ -244,6 +245,43 @@ func TestExporterShutdownManyTimes(t *testing.T) { } } +func TestInstallNewPipeline(t *testing.T) { + ctx := context.Background() + _, _, _, err := otlp.InstallNewPipeline(ctx, &stubProtocolDriver{}) + assert.NoError(t, err) + assert.IsType(t, &tracesdk.TracerProvider{}, otel.GetTracerProvider()) +} + +func TestNewExportPipeline(t *testing.T) { + testCases := []struct { + name string + expOpts []otlp.ExporterOption + testSpanSampling bool + }{ + { + name: "simple pipeline", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + _, tp, _, err := otlp.NewExportPipeline( + context.Background(), + &stubProtocolDriver{}, + tc.expOpts..., + ) + + assert.NoError(t, err) + assert.NotEqual(t, tp, otel.GetTracerProvider()) + + _, span := tp.Tracer("otlp test").Start(context.Background(), tc.name) + spanCtx := span.SpanContext() + assert.Equal(t, true, spanCtx.IsSampled()) + span.End() + }) + } +} + func TestSplitDriver(t *testing.T) { driverTraces := &stubProtocolDriver{} driverMetrics := &stubProtocolDriver{}