Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change NewSplitDriver paramater and initialization #1798

Merged
merged 25 commits into from Apr 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
dd93ab7
Change NewSplitDriver paramater and initialization
bryan-aguilar Apr 6, 2021
54f68d1
Update CHANGELOG.md
bryan-aguilar Apr 7, 2021
d47871b
Update CHANGELOG.md
bryan-aguilar Apr 7, 2021
81fcd4e
Update exporters/otlp/protocoldriver.go
bryan-aguilar Apr 7, 2021
e4bdb6d
Update exporters/otlp/protocoldriver.go
bryan-aguilar Apr 8, 2021
6743e4d
Update exporters/otlp/protocoldriver.go
bryan-aguilar Apr 8, 2021
f1c17af
Update exporters/otlp/protocoldriver.go
bryan-aguilar Apr 8, 2021
e0b1b2b
Move splitdriver option into options.go and rename
bryan-aguilar Apr 8, 2021
06fdd2d
Merge remote-tracking branch 'upstream/main' into NewSplitDriver_Update
bryan-aguilar Apr 8, 2021
dd623a8
Merge branch 'working' into NewSplitDriver_Update
bryan-aguilar Apr 12, 2021
cfa6a91
Update CHANGELOG.md
bryan-aguilar Apr 19, 2021
9493d37
Change option name and nil test to snapshots
bryan-aguilar Apr 19, 2021
8b9bc71
Merge branch 'main' into NewSplitDriver_Update
bryan-aguilar Apr 19, 2021
2694914
Update exporters/otlp/protocoldriver.go
bryan-aguilar Apr 19, 2021
419e4fc
Update exporters/otlp/protocoldriver.go
bryan-aguilar Apr 19, 2021
5e6841b
Update exporters/otlp/protocoldriver.go
bryan-aguilar Apr 19, 2021
06acaa7
Update exporters/otlp/protocoldriver.go
bryan-aguilar Apr 19, 2021
6ff5b28
Update exporters/otlp/options.go
bryan-aguilar Apr 19, 2021
4f5547d
Update exporters/otlp/options.go
bryan-aguilar Apr 19, 2021
845fc07
Update exporters/otlp/options.go
bryan-aguilar Apr 19, 2021
c9d4971
Update exporters/otlp/options.go
bryan-aguilar Apr 22, 2021
2a081bb
Change SplitDriverOption to match spec
bryan-aguilar Apr 22, 2021
2f0aa62
Merge branch 'main' into NewSplitDriver_Update
bryan-aguilar Apr 22, 2021
c9b5d1e
Merge branch 'main' into NewSplitDriver_Update
Aneurysm9 Apr 23, 2021
d6a784d
Update changelog entry
bryan-aguilar Apr 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -12,6 +12,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

### Changed

- Make `NewSplitDriver` from `go.opentelemetry.io/otel/exporters/otlp` take variadic arguments instead of a `SplitConfig` item.
`NewSplitDriver` now automically implements an internal `noopDriver` for `SplitConfig` fields that are not initialized. (#1798)

### Deprecated

### Removed
Expand Down
6 changes: 1 addition & 5 deletions exporters/otlp/example_test.go
Expand Up @@ -35,11 +35,7 @@ func ExampleNewExporter() {
tracesDriver := otlpgrpc.NewDriver(
// Configure traces driver here
)
config := otlp.SplitConfig{
ForMetrics: metricsDriver,
ForTraces: tracesDriver,
}
driver := otlp.NewSplitDriver(config)
driver := otlp.NewSplitDriver(otlp.WithMetricDriver(metricsDriver), otlp.WithTraceDriver(tracesDriver))
exporter, err := otlp.NewExporter(ctx, driver) // Configure as needed.
if err != nil {
log.Fatalf("failed to create exporter: %v", err)
Expand Down
33 changes: 33 additions & 0 deletions exporters/otlp/options.go
Expand Up @@ -43,3 +43,36 @@ func WithMetricExportKindSelector(selector metricsdk.ExportKindSelector) Exporte
cfg.exportKindSelector = selector
}
}

// SplitDriverOption provides options for setting up a split driver.
type SplitDriverOption interface {
Apply(*splitDriver)
}

// WithMetricDriver allows one to set the driver used for metrics
// in a SplitDriver.
func WithMetricDriver(dr ProtocolDriver) SplitDriverOption {
return metricDriverOption{dr}
}

type metricDriverOption struct {
driver ProtocolDriver
}

func (o metricDriverOption) Apply(s *splitDriver) {
s.metric = o.driver
}

// WithTraceDriver allows one to set the driver used for traces
// in a SplitDriver.
func WithTraceDriver(dr ProtocolDriver) SplitDriverOption {
return traceDriverOption{dr}
}

type traceDriverOption struct {
driver ProtocolDriver
}

func (o traceDriverOption) Apply(s *splitDriver) {
s.trace = o.driver
}
146 changes: 104 additions & 42 deletions exporters/otlp/otlp_test.go
Expand Up @@ -283,46 +283,112 @@ func TestNewExportPipeline(t *testing.T) {
}

func TestSplitDriver(t *testing.T) {
driverTraces := &stubProtocolDriver{}
driverMetrics := &stubProtocolDriver{}
config := otlp.SplitConfig{
ForMetrics: driverMetrics,
ForTraces: driverTraces,
}
driver := otlp.NewSplitDriver(config)
ctx := context.Background()
assert.NoError(t, driver.Start(ctx))
assert.Equal(t, 1, driverTraces.started)
assert.Equal(t, 1, driverMetrics.started)
assert.Equal(t, 0, driverTraces.stopped)
assert.Equal(t, 0, driverMetrics.stopped)
assert.Equal(t, 0, driverTraces.tracesExported)
assert.Equal(t, 0, driverTraces.metricsExported)
assert.Equal(t, 0, driverMetrics.tracesExported)
assert.Equal(t, 0, driverMetrics.metricsExported)

recordCount := 5
spanCount := 7
assert.NoError(t, driver.ExportMetrics(ctx, stubCheckpointSet{recordCount}, metricsdk.StatelessExportKindSelector()))
assert.NoError(t, driver.ExportTraces(ctx, stubSpanSnapshot(spanCount)))
assert.Len(t, driverTraces.rm, 0)
assert.Len(t, driverTraces.rs, spanCount)
assert.Len(t, driverMetrics.rm, recordCount)
assert.Len(t, driverMetrics.rs, 0)
assert.Equal(t, 1, driverTraces.tracesExported)
assert.Equal(t, 0, driverTraces.metricsExported)
assert.Equal(t, 0, driverMetrics.tracesExported)
assert.Equal(t, 1, driverMetrics.metricsExported)

assert.NoError(t, driver.Stop(ctx))
assert.Equal(t, 1, driverTraces.started)
assert.Equal(t, 1, driverMetrics.started)
assert.Equal(t, 1, driverTraces.stopped)
assert.Equal(t, 1, driverMetrics.stopped)
assert.Equal(t, 1, driverTraces.tracesExported)
assert.Equal(t, 0, driverTraces.metricsExported)
assert.Equal(t, 0, driverMetrics.tracesExported)
assert.Equal(t, 1, driverMetrics.metricsExported)
assertExport := func(t testing.TB, ctx context.Context, driver otlp.ProtocolDriver) {
t.Helper()
assert.NoError(t, driver.ExportMetrics(ctx, stubCheckpointSet{recordCount}, metricsdk.StatelessExportKindSelector()))
assert.NoError(t, driver.ExportTraces(ctx, stubSpanSnapshot(spanCount)))
}

t.Run("with metric/trace drivers configured", func(t *testing.T) {
driverTraces := &stubProtocolDriver{}
driverMetrics := &stubProtocolDriver{}

driver := otlp.NewSplitDriver(otlp.WithMetricDriver(driverMetrics), otlp.WithTraceDriver(driverTraces))
ctx := context.Background()
assert.NoError(t, driver.Start(ctx))
assert.Equal(t, 1, driverTraces.started)
assert.Equal(t, 1, driverMetrics.started)
assert.Equal(t, 0, driverTraces.stopped)
assert.Equal(t, 0, driverMetrics.stopped)
assert.Equal(t, 0, driverTraces.tracesExported)
assert.Equal(t, 0, driverTraces.metricsExported)
assert.Equal(t, 0, driverMetrics.tracesExported)
assert.Equal(t, 0, driverMetrics.metricsExported)

assertExport(t, ctx, driver)
assert.Len(t, driverTraces.rm, 0)
assert.Len(t, driverTraces.rs, spanCount)
assert.Len(t, driverMetrics.rm, recordCount)
assert.Len(t, driverMetrics.rs, 0)
assert.Equal(t, 1, driverTraces.tracesExported)
assert.Equal(t, 0, driverTraces.metricsExported)
assert.Equal(t, 0, driverMetrics.tracesExported)
assert.Equal(t, 1, driverMetrics.metricsExported)

assert.NoError(t, driver.Stop(ctx))
assert.Equal(t, 1, driverTraces.started)
assert.Equal(t, 1, driverMetrics.started)
assert.Equal(t, 1, driverTraces.stopped)
assert.Equal(t, 1, driverMetrics.stopped)
assert.Equal(t, 1, driverTraces.tracesExported)
assert.Equal(t, 0, driverTraces.metricsExported)
assert.Equal(t, 0, driverMetrics.tracesExported)
assert.Equal(t, 1, driverMetrics.metricsExported)
})

t.Run("with just metric driver", func(t *testing.T) {
driverMetrics := &stubProtocolDriver{}

driver := otlp.NewSplitDriver(otlp.WithMetricDriver(driverMetrics))
ctx := context.Background()
assert.NoError(t, driver.Start(ctx))

assert.Equal(t, 1, driverMetrics.started)
assert.Equal(t, 0, driverMetrics.stopped)
assert.Equal(t, 0, driverMetrics.tracesExported)
assert.Equal(t, 0, driverMetrics.metricsExported)

assertExport(t, ctx, driver)
assert.Len(t, driverMetrics.rm, recordCount)
assert.Len(t, driverMetrics.rs, 0)
assert.Equal(t, 0, driverMetrics.tracesExported)
assert.Equal(t, 1, driverMetrics.metricsExported)

assert.NoError(t, driver.Stop(ctx))
assert.Equal(t, 1, driverMetrics.started)
assert.Equal(t, 1, driverMetrics.stopped)
assert.Equal(t, 0, driverMetrics.tracesExported)
assert.Equal(t, 1, driverMetrics.metricsExported)
})

t.Run("with just trace driver", func(t *testing.T) {
driverTraces := &stubProtocolDriver{}

driver := otlp.NewSplitDriver(otlp.WithTraceDriver(driverTraces))
ctx := context.Background()
assert.NoError(t, driver.Start(ctx))
assert.Equal(t, 1, driverTraces.started)
assert.Equal(t, 0, driverTraces.stopped)
assert.Equal(t, 0, driverTraces.tracesExported)
assert.Equal(t, 0, driverTraces.metricsExported)

assertExport(t, ctx, driver)
assert.Len(t, driverTraces.rm, 0)
assert.Len(t, driverTraces.rs, spanCount)
assert.Equal(t, 1, driverTraces.tracesExported)
assert.Equal(t, 0, driverTraces.metricsExported)

assert.NoError(t, driver.Stop(ctx))
assert.Equal(t, 1, driverTraces.started)
assert.Equal(t, 1, driverTraces.stopped)
assert.Equal(t, 1, driverTraces.tracesExported)
assert.Equal(t, 0, driverTraces.metricsExported)
})

t.Run("with no drivers configured", func(t *testing.T) {

driver := otlp.NewSplitDriver()
ctx := context.Background()
assert.NoError(t, driver.Start(ctx))

assert.NoError(t, driver.ExportMetrics(ctx, stubCheckpointSet{recordCount}, metricsdk.StatelessExportKindSelector()))
assert.NoError(t, driver.ExportTraces(ctx, stubSpanSnapshot(spanCount)))
assert.NoError(t, driver.Stop(ctx))
})

}

func TestSplitDriverFail(t *testing.T) {
Expand Down Expand Up @@ -357,11 +423,7 @@ func TestSplitDriverFail(t *testing.T) {
injectedStartError: errStartMetric,
injectedStopError: errStopMetric,
}
config := otlp.SplitConfig{
ForMetrics: driverMetrics,
ForTraces: driverTraces,
}
driver := otlp.NewSplitDriver(config)
driver := otlp.NewSplitDriver(otlp.WithMetricDriver(driverMetrics), otlp.WithTraceDriver(driverTraces))
errStart := driver.Start(ctx)
if shouldStartFail {
assert.Error(t, errStart)
Expand Down
6 changes: 1 addition & 5 deletions exporters/otlp/otlpgrpc/example_test.go
Expand Up @@ -143,11 +143,7 @@ func Example_withDifferentSignalCollectors() {
otlpgrpc.WithInsecure(),
otlpgrpc.WithEndpoint("localhost:30082"),
)
splitCfg := otlp.SplitConfig{
ForMetrics: metricsDriver,
ForTraces: tracesDriver,
}
driver := otlp.NewSplitDriver(splitCfg)
driver := otlp.NewSplitDriver(otlp.WithMetricDriver(metricsDriver), otlp.WithTraceDriver(tracesDriver))
ctx := context.Background()
exp, err := otlp.NewExporter(ctx, driver)
if err != nil {
Expand Down
6 changes: 1 addition & 5 deletions exporters/otlp/otlpgrpc/otlp_integration_test.go
Expand Up @@ -626,11 +626,7 @@ func TestMultiConnectionDriver(t *testing.T) {

tracesDriver := otlpgrpc.NewDriver(optsTraces...)
metricsDriver := otlpgrpc.NewDriver(optsMetrics...)
splitCfg := otlp.SplitConfig{
ForMetrics: metricsDriver,
ForTraces: tracesDriver,
}
driver := otlp.NewSplitDriver(splitCfg)
driver := otlp.NewSplitDriver(otlp.WithMetricDriver(metricsDriver), otlp.WithTraceDriver(tracesDriver))
ctx := context.Background()
exp, err := otlp.NewExporter(ctx, driver)
if err != nil {
Expand Down
39 changes: 35 additions & 4 deletions exporters/otlp/protocoldriver.go
Expand Up @@ -66,16 +66,27 @@ type splitDriver struct {
trace ProtocolDriver
}

// noopDriver implements the ProtocolDriver interface and
// is used internally to implement split drivers that do not have
// all drivers configured.
type noopDriver struct{}

var _ ProtocolDriver = (*noopDriver)(nil)

var _ ProtocolDriver = (*splitDriver)(nil)

// NewSplitDriver creates a protocol driver which contains two other
// protocol drivers and will forward traces to one of them and metrics
// to another.
func NewSplitDriver(cfg SplitConfig) ProtocolDriver {
return &splitDriver{
metric: cfg.ForMetrics,
trace: cfg.ForTraces,
func NewSplitDriver(opts ...SplitDriverOption) ProtocolDriver {
driver := splitDriver{
metric: &noopDriver{},
trace: &noopDriver{},
}
for _, opt := range opts {
opt.Apply(&driver)
}
return &driver
}

// Start implements ProtocolDriver. It starts both drivers at the same
Expand Down Expand Up @@ -143,3 +154,23 @@ func (d *splitDriver) ExportMetrics(ctx context.Context, cps metricsdk.Checkpoin
func (d *splitDriver) ExportTraces(ctx context.Context, ss []*tracesdk.SpanSnapshot) error {
return d.trace.ExportTraces(ctx, ss)
}

// Start does nothing.
func (d *noopDriver) Start(ctx context.Context) error {
return nil
}

// Stop does nothing.
func (d *noopDriver) Stop(ctx context.Context) error {
return nil
}

// ExportMetrics does nothing.
func (d *noopDriver) ExportMetrics(ctx context.Context, cps metricsdk.CheckpointSet, selector metricsdk.ExportKindSelector) error {
return nil
}

// ExportTraces does nothing.
func (d *noopDriver) ExportTraces(ctx context.Context, ss []*tracesdk.SpanSnapshot) error {
return nil
}