You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-11-25 22:41:46 +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:
@@ -36,7 +36,6 @@ type testBatchExporter struct {
|
|||||||
sizes []int
|
sizes []int
|
||||||
batchCount int
|
batchCount int
|
||||||
shutdownCount int
|
shutdownCount int
|
||||||
delay time.Duration
|
|
||||||
errors []error
|
errors []error
|
||||||
droppedCount int
|
droppedCount int
|
||||||
idx int
|
idx int
|
||||||
@@ -54,8 +53,6 @@ func (t *testBatchExporter) ExportSpans(ctx context.Context, spans []sdktrace.Re
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(t.delay)
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
t.err = ctx.Err()
|
t.err = ctx.Err()
|
||||||
@@ -113,15 +110,12 @@ type testOption struct {
|
|||||||
o []sdktrace.BatchSpanProcessorOption
|
o []sdktrace.BatchSpanProcessorOption
|
||||||
wantNumSpans int
|
wantNumSpans int
|
||||||
wantBatchCount int
|
wantBatchCount int
|
||||||
wantExportTimeout bool
|
|
||||||
genNumSpans int
|
genNumSpans int
|
||||||
delayExportBy time.Duration
|
|
||||||
parallel bool
|
parallel bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewBatchSpanProcessorWithOptions(t *testing.T) {
|
func TestNewBatchSpanProcessorWithOptions(t *testing.T) {
|
||||||
schDelay := 200 * time.Millisecond
|
schDelay := 200 * time.Millisecond
|
||||||
exportTimeout := time.Millisecond
|
|
||||||
options := []testOption{
|
options := []testOption{
|
||||||
{
|
{
|
||||||
name: "default BatchSpanProcessorOptions",
|
name: "default BatchSpanProcessorOptions",
|
||||||
@@ -129,15 +123,6 @@ func TestNewBatchSpanProcessorWithOptions(t *testing.T) {
|
|||||||
wantBatchCount: 4,
|
wantBatchCount: 4,
|
||||||
genNumSpans: 2053,
|
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",
|
name: "non-default BatchTimeout",
|
||||||
o: []sdktrace.BatchSpanProcessorOption{
|
o: []sdktrace.BatchSpanProcessorOption{
|
||||||
@@ -204,9 +189,7 @@ func TestNewBatchSpanProcessorWithOptions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
t.Run(option.name, func(t *testing.T) {
|
t.Run(option.name, func(t *testing.T) {
|
||||||
te := testBatchExporter{
|
te := testBatchExporter{}
|
||||||
delay: option.delayExportBy,
|
|
||||||
}
|
|
||||||
tp := basicTracerProvider(t)
|
tp := basicTracerProvider(t)
|
||||||
ssp := createAndRegisterBatchSP(option, &te)
|
ssp := createAndRegisterBatchSP(option, &te)
|
||||||
if ssp == nil {
|
if ssp == nil {
|
||||||
@@ -231,15 +214,41 @@ func TestNewBatchSpanProcessorWithOptions(t *testing.T) {
|
|||||||
gotBatchCount, option.wantBatchCount)
|
gotBatchCount, option.wantBatchCount)
|
||||||
t.Errorf("Batches %v\n", te.sizes)
|
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 {
|
func createAndRegisterBatchSP(option testOption, te *testBatchExporter) sdktrace.SpanProcessor {
|
||||||
// Always use blocking queue to avoid flaky tests.
|
// Always use blocking queue to avoid flaky tests.
|
||||||
options := append(option.o, sdktrace.WithBlocking())
|
options := append(option.o, sdktrace.WithBlocking())
|
||||||
|
|||||||
Reference in New Issue
Block a user