Skip to content

Commit 79de90a

Browse files
authoredMar 5, 2020
fix data race in BatchedSpanProcessor (#518)
* fix data race in BatchedSpanProcessor - fixes #517 * fix ci. * fix another test. * move wait group to generateSpan func.
1 parent 161556a commit 79de90a

File tree

2 files changed

+32
-21
lines changed

2 files changed

+32
-21
lines changed
 

‎sdk/trace/batch_span_processor.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"context"
1919
"errors"
2020
"sync"
21+
"sync/atomic"
2122
"time"
2223

2324
export "go.opentelemetry.io/otel/sdk/export/trace"
@@ -206,7 +207,7 @@ func (bsp *BatchSpanProcessor) enqueue(sd *export.SpanData) {
206207
ok = false
207208
}
208209
if !ok {
209-
bsp.dropped++
210+
atomic.AddUint32(&bsp.dropped, 1)
210211
}
211212
}
212213
}

‎sdk/trace/batch_span_processor_test.go

+30-20
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,6 @@ func (t *testBatchExporter) getBatchCount() int {
5555
return t.batchCount
5656
}
5757

58-
func (t *testBatchExporter) get(idx int) *export.SpanData {
59-
t.mu.Lock()
60-
defer t.mu.Unlock()
61-
return t.spans[idx]
62-
}
63-
6458
var _ export.SpanBatcher = (*testBatchExporter)(nil)
6559

6660
func TestNewBatchSpanProcessorWithNilExporter(t *testing.T) {
@@ -77,6 +71,7 @@ type testOption struct {
7771
wantBatchCount int
7872
genNumSpans int
7973
waitTime time.Duration
74+
parallel bool
8075
}
8176

8277
func TestNewBatchSpanProcessorWithOptions(t *testing.T) {
@@ -136,18 +131,30 @@ func TestNewBatchSpanProcessorWithOptions(t *testing.T) {
136131
genNumSpans: 205,
137132
waitTime: waitTime,
138133
},
134+
{
135+
name: "parallel span generation",
136+
o: []sdktrace.BatchSpanProcessorOption{
137+
sdktrace.WithScheduleDelayMillis(schDelay),
138+
sdktrace.WithMaxQueueSize(200),
139+
},
140+
wantNumSpans: 200,
141+
wantBatchCount: 1,
142+
genNumSpans: 205,
143+
waitTime: waitTime,
144+
parallel: true,
145+
},
139146
}
140147
for _, option := range options {
141148
te := testBatchExporter{}
142149
tp := basicProvider(t)
143150
ssp := createAndRegisterBatchSP(t, option, &te)
144151
if ssp == nil {
145-
t.Errorf("%s: Error creating new instance of BatchSpanProcessor\n", option.name)
152+
t.Fatalf("%s: Error creating new instance of BatchSpanProcessor\n", option.name)
146153
}
147154
tp.RegisterSpanProcessor(ssp)
148155
tr := tp.Tracer("BatchSpanProcessorWithOptions")
149156

150-
generateSpan(t, tr, option)
157+
generateSpan(t, option.parallel, tr, option)
151158

152159
time.Sleep(option.waitTime)
153160

@@ -162,14 +169,6 @@ func TestNewBatchSpanProcessorWithOptions(t *testing.T) {
162169
t.Errorf("Batches %v\n", te.sizes)
163170
}
164171

165-
// Check first Span is reported. Most recent one is dropped.
166-
sc := getSpanContext()
167-
wantTraceID := sc.TraceID
168-
binary.BigEndian.PutUint64(wantTraceID[0:8], uint64(1))
169-
gotTraceID := te.get(0).SpanContext.TraceID
170-
if wantTraceID != gotTraceID {
171-
t.Errorf("%s: first exported span: got %+v, want %+v\n", option.name, gotTraceID, wantTraceID)
172-
}
173172
tp.UnregisterSpanProcessor(ssp)
174173
}
175174
}
@@ -182,15 +181,26 @@ func createAndRegisterBatchSP(t *testing.T, option testOption, te *testBatchExpo
182181
return ssp
183182
}
184183

185-
func generateSpan(t *testing.T, tr apitrace.Tracer, option testOption) {
184+
func generateSpan(t *testing.T, parallel bool, tr apitrace.Tracer, option testOption) {
186185
sc := getSpanContext()
187186

187+
wg := &sync.WaitGroup{}
188188
for i := 0; i < option.genNumSpans; i++ {
189189
binary.BigEndian.PutUint64(sc.TraceID[0:8], uint64(i+1))
190-
ctx := apitrace.ContextWithRemoteSpanContext(context.Background(), sc)
191-
_, span := tr.Start(ctx, option.name)
192-
span.End()
190+
wg.Add(1)
191+
f := func(sc core.SpanContext) {
192+
ctx := apitrace.ContextWithRemoteSpanContext(context.Background(), sc)
193+
_, span := tr.Start(ctx, option.name)
194+
span.End()
195+
wg.Done()
196+
}
197+
if parallel {
198+
go f(sc)
199+
} else {
200+
f(sc)
201+
}
193202
}
203+
wg.Wait()
194204
}
195205

196206
func getSpanContext() core.SpanContext {

0 commit comments

Comments
 (0)
Please sign in to comment.