1package zipkintracer
2
3import (
4	"bytes"
5	"fmt"
6	"net/http"
7	"testing"
8
9	opentracing "github.com/opentracing/opentracing-go"
10)
11
12var tags []string
13
14func init() {
15	tags = make([]string, 1000)
16	for j := 0; j < len(tags); j++ {
17		tags[j] = fmt.Sprintf("%d", randomID())
18	}
19}
20
21func executeOps(sp opentracing.Span, numEvent, numTag, numItems int) {
22	for j := 0; j < numEvent; j++ {
23		sp.LogEvent("event")
24	}
25	for j := 0; j < numTag; j++ {
26		sp.SetTag(tags[j], nil)
27	}
28	for j := 0; j < numItems; j++ {
29		sp.SetBaggageItem(tags[j], tags[j])
30	}
31}
32
33func benchmarkWithOps(b *testing.B, numEvent, numTag, numItems int) {
34	var r CountingRecorder
35	t, err := NewTracer(&r)
36	if err != nil {
37		b.Fatalf("Unable to create Tracer: %+v", err)
38	}
39	benchmarkWithOpsAndCB(b, func() opentracing.Span {
40		return t.StartSpan("test")
41	}, numEvent, numTag, numItems)
42	if int(r) != b.N {
43		b.Fatalf("missing traces: expected %d, got %d", b.N, r)
44	}
45}
46
47func benchmarkWithOpsAndCB(b *testing.B, create func() opentracing.Span,
48	numEvent, numTag, numItems int) {
49	b.ResetTimer()
50	for i := 0; i < b.N; i++ {
51		sp := create()
52		executeOps(sp, numEvent, numTag, numItems)
53		sp.Finish()
54	}
55	b.StopTimer()
56}
57
58func BenchmarkSpan_Empty(b *testing.B) {
59	benchmarkWithOps(b, 0, 0, 0)
60}
61
62func BenchmarkSpan_100Events(b *testing.B) {
63	benchmarkWithOps(b, 100, 0, 0)
64}
65
66func BenchmarkSpan_1000Events(b *testing.B) {
67	benchmarkWithOps(b, 1000, 0, 0)
68}
69
70func BenchmarkSpan_100Tags(b *testing.B) {
71	benchmarkWithOps(b, 0, 100, 0)
72}
73
74func BenchmarkSpan_1000Tags(b *testing.B) {
75	benchmarkWithOps(b, 0, 1000, 0)
76}
77
78func BenchmarkSpan_100BaggageItems(b *testing.B) {
79	benchmarkWithOps(b, 0, 0, 100)
80}
81
82func BenchmarkTrimmedSpan_100Events_100Tags_100BaggageItems(b *testing.B) {
83	var r CountingRecorder
84	t, err := NewTracer(
85		&r,
86		TrimUnsampledSpans(true),
87		WithSampler(neverSample),
88		TraceID128Bit(true),
89	)
90	if err != nil {
91		b.Fatalf("Unable to create Tracer: %+v", err)
92	}
93	benchmarkWithOpsAndCB(b, func() opentracing.Span {
94		sp := t.StartSpan("test")
95		return sp
96	}, 100, 100, 100)
97	if int(r) != b.N {
98		b.Fatalf("missing traces: expected %d, got %d", b.N, r)
99	}
100}
101
102func benchmarkInject(b *testing.B, format opentracing.BuiltinFormat, numItems int) {
103	var r CountingRecorder
104	tracer, err := NewTracer(&r)
105	if err != nil {
106		b.Fatalf("Unable to create Tracer: %+v", err)
107	}
108	sp := tracer.StartSpan("testing")
109	executeOps(sp, 0, 0, numItems)
110	var carrier interface{}
111	switch format {
112	case opentracing.TextMap, opentracing.HTTPHeaders:
113		carrier = opentracing.HTTPHeadersCarrier(http.Header{})
114	case opentracing.Binary:
115		carrier = &bytes.Buffer{}
116	default:
117		b.Fatalf("unhandled format %d", format)
118	}
119	b.ResetTimer()
120	for i := 0; i < b.N; i++ {
121		err := tracer.Inject(sp.Context(), format, carrier)
122		if err != nil {
123			b.Fatal(err)
124		}
125	}
126}
127
128func benchmarkExtract(b *testing.B, format opentracing.BuiltinFormat, numItems int) {
129	var r CountingRecorder
130	tracer, err := NewTracer(&r)
131	if err != nil {
132		b.Fatalf("Unable to create Tracer: %+v", err)
133	}
134	sp := tracer.StartSpan("testing")
135	executeOps(sp, 0, 0, numItems)
136	var carrier interface{}
137	switch format {
138	case opentracing.TextMap, opentracing.HTTPHeaders:
139		carrier = opentracing.HTTPHeadersCarrier(http.Header{})
140	case opentracing.Binary:
141		carrier = &bytes.Buffer{}
142	default:
143		b.Fatalf("unhandled format %d", format)
144	}
145	if err := tracer.Inject(sp.Context(), format, carrier); err != nil {
146		b.Fatal(err)
147	}
148
149	// We create a new bytes.Buffer every time for tracer.Extract() to keep
150	// this benchmark realistic.
151	var rawBinaryBytes []byte
152	if format == opentracing.Binary {
153		rawBinaryBytes = carrier.(*bytes.Buffer).Bytes()
154	}
155	b.ResetTimer()
156	for i := 0; i < b.N; i++ {
157		if format == opentracing.Binary {
158			carrier = bytes.NewBuffer(rawBinaryBytes)
159		}
160		_, err := tracer.Extract(format, carrier)
161		if err != nil {
162			b.Fatal(err)
163		}
164	}
165}
166
167func BenchmarkInject_TextMap_Empty(b *testing.B) {
168	benchmarkInject(b, opentracing.TextMap, 0)
169}
170
171func BenchmarkInject_TextMap_100BaggageItems(b *testing.B) {
172	benchmarkInject(b, opentracing.TextMap, 100)
173}
174
175func BenchmarkInject_Binary_Empty(b *testing.B) {
176	benchmarkInject(b, opentracing.Binary, 0)
177}
178
179func BenchmarkInject_Binary_100BaggageItems(b *testing.B) {
180	benchmarkInject(b, opentracing.Binary, 100)
181}
182
183func BenchmarkExtract_TextMap_Empty(b *testing.B) {
184	benchmarkExtract(b, opentracing.TextMap, 0)
185}
186
187func BenchmarkExtract_TextMap_100BaggageItems(b *testing.B) {
188	benchmarkExtract(b, opentracing.TextMap, 100)
189}
190
191func BenchmarkExtract_Binary_Empty(b *testing.B) {
192	benchmarkExtract(b, opentracing.Binary, 0)
193}
194
195func BenchmarkExtract_Binary_100BaggageItems(b *testing.B) {
196	benchmarkExtract(b, opentracing.Binary, 100)
197}
198