1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2024-12-02 08:52:21 +02:00

Test BatchSpanProcessor export timeout directly (#1982)

Test the export timeout by waiting indefinitely for the export to
timeout instead of having a second timer, in its own goroutine, timeout.
The algorithm this replaces fails on machines that are slow and the one
meta-timer is given priority to progress over the export timer that is
being testing, resulting in a false-negative test result.

Move the testing of a BatchSpanProcessor export timeout to its own test
function. This removes the bloat this introduces to the other testing
options and allows customization that enable the testing in a
deterministic manner.
This commit is contained in:
Tyler Yahn 2021-06-09 21:05:10 +00:00 committed by GitHub
parent 7ffe28457d
commit 87cc1e1fea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -36,7 +36,6 @@ type testBatchExporter struct {
sizes []int
batchCount int
shutdownCount int
delay time.Duration
errors []error
droppedCount int
idx int
@ -54,8 +53,6 @@ func (t *testBatchExporter) ExportSpans(ctx context.Context, spans []sdktrace.Re
return err
}
time.Sleep(t.delay)
select {
case <-ctx.Done():
t.err = ctx.Err()
@ -109,19 +106,16 @@ func TestNewBatchSpanProcessorWithNilExporter(t *testing.T) {
}
type testOption struct {
name string
o []sdktrace.BatchSpanProcessorOption
wantNumSpans int
wantBatchCount int
wantExportTimeout bool
genNumSpans int
delayExportBy time.Duration
parallel bool
name string
o []sdktrace.BatchSpanProcessorOption
wantNumSpans int
wantBatchCount int
genNumSpans int
parallel bool
}
func TestNewBatchSpanProcessorWithOptions(t *testing.T) {
schDelay := 200 * time.Millisecond
exportTimeout := time.Millisecond
options := []testOption{
{
name: "default BatchSpanProcessorOptions",
@ -129,15 +123,6 @@ func TestNewBatchSpanProcessorWithOptions(t *testing.T) {
wantBatchCount: 4,
genNumSpans: 2053,
},
{
name: "non-default ExportTimeout",
o: []sdktrace.BatchSpanProcessorOption{
sdktrace.WithExportTimeout(exportTimeout),
},
wantExportTimeout: true,
genNumSpans: 2053,
delayExportBy: 2 * exportTimeout, // to ensure export timeout
},
{
name: "non-default BatchTimeout",
o: []sdktrace.BatchSpanProcessorOption{
@ -204,9 +189,7 @@ func TestNewBatchSpanProcessorWithOptions(t *testing.T) {
}
for _, option := range options {
t.Run(option.name, func(t *testing.T) {
te := testBatchExporter{
delay: option.delayExportBy,
}
te := testBatchExporter{}
tp := basicTracerProvider(t)
ssp := createAndRegisterBatchSP(option, &te)
if ssp == nil {
@ -231,15 +214,41 @@ func TestNewBatchSpanProcessorWithOptions(t *testing.T) {
gotBatchCount, option.wantBatchCount)
t.Errorf("Batches %v\n", te.sizes)
}
if option.wantExportTimeout && te.err != context.DeadlineExceeded {
t.Errorf("context deadline: got err %+v, want %+v\n",
te.err, context.DeadlineExceeded)
}
})
}
}
type stuckExporter struct {
testBatchExporter
}
// ExportSpans waits for ctx to expire and returns that error.
func (e *stuckExporter) ExportSpans(ctx context.Context, _ []sdktrace.ReadOnlySpan) error {
<-ctx.Done()
e.err = ctx.Err()
return ctx.Err()
}
func TestBatchSpanProcessorExportTimeout(t *testing.T) {
exp := new(stuckExporter)
bsp := sdktrace.NewBatchSpanProcessor(
exp,
// Set a non-zero export timeout so a deadline is set.
sdktrace.WithExportTimeout(1*time.Microsecond),
sdktrace.WithBlocking(),
)
tp := basicTracerProvider(t)
tp.RegisterSpanProcessor(bsp)
tr := tp.Tracer("BatchSpanProcessorExportTimeout")
generateSpan(t, false, tr, testOption{genNumSpans: 1})
tp.UnregisterSpanProcessor(bsp)
if exp.err != context.DeadlineExceeded {
t.Errorf("context deadline error not returned: got %+v", exp.err)
}
}
func createAndRegisterBatchSP(option testOption, te *testBatchExporter) sdktrace.SpanProcessor {
// Always use blocking queue to avoid flaky tests.
options := append(option.o, sdktrace.WithBlocking())