1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package trace
16
17 import (
18 "context"
19 "os"
20 "testing"
21
22 "github.com/stretchr/testify/assert"
23 "github.com/stretchr/testify/require"
24
25 "go.opentelemetry.io/otel/attribute"
26 "go.opentelemetry.io/otel/sdk/internal/env"
27 ottest "go.opentelemetry.io/otel/sdk/internal/internaltest"
28 "go.opentelemetry.io/otel/trace"
29 )
30
31 func TestSettingSpanLimits(t *testing.T) {
32 envLimits := func(val string) map[string]string {
33 return map[string]string{
34 env.SpanAttributeValueLengthKey: val,
35 env.SpanEventCountKey: val,
36 env.SpanAttributeCountKey: val,
37 env.SpanLinkCountKey: val,
38 env.SpanEventAttributeCountKey: val,
39 env.SpanLinkAttributeCountKey: val,
40 }
41 }
42
43 limits := func(n int) *SpanLimits {
44 lims := NewSpanLimits()
45 lims.AttributeValueLengthLimit = n
46 lims.AttributeCountLimit = n
47 lims.EventCountLimit = n
48 lims.LinkCountLimit = n
49 lims.AttributePerEventCountLimit = n
50 lims.AttributePerLinkCountLimit = n
51 return &lims
52 }
53
54 tests := []struct {
55 name string
56 env map[string]string
57 opt *SpanLimits
58 rawOpt *SpanLimits
59 want SpanLimits
60 }{
61 {
62 name: "defaults",
63 want: NewSpanLimits(),
64 },
65 {
66 name: "env",
67 env: envLimits("42"),
68 want: *(limits(42)),
69 },
70 {
71 name: "opt",
72 opt: limits(42),
73 want: *(limits(42)),
74 },
75 {
76 name: "raw-opt",
77 rawOpt: limits(42),
78 want: *(limits(42)),
79 },
80 {
81 name: "opt-override",
82 env: envLimits("-2"),
83
84 opt: limits(43),
85 want: *(limits(43)),
86 },
87 {
88 name: "raw-opt-override",
89 env: envLimits("-2"),
90
91 rawOpt: limits(43),
92 want: *(limits(43)),
93 },
94 {
95 name: "last-opt-wins",
96 opt: limits(-2),
97 rawOpt: limits(-3),
98 want: *(limits(-3)),
99 },
100 {
101 name: "env(unlimited)",
102
103
104
105
106 env: envLimits("-1"),
107 want: *(limits(-1)),
108 },
109 {
110 name: "opt(unlimited)",
111
112 opt: limits(-1),
113 want: NewSpanLimits(),
114 },
115 {
116 name: "raw-opt(unlimited)",
117 rawOpt: limits(-1),
118 want: *(limits(-1)),
119 },
120 }
121
122 for _, test := range tests {
123 t.Run(test.name, func(t *testing.T) {
124 if test.env != nil {
125 es := ottest.NewEnvStore()
126 t.Cleanup(func() { require.NoError(t, es.Restore()) })
127 for k, v := range test.env {
128 es.Record(k)
129 require.NoError(t, os.Setenv(k, v))
130 }
131 }
132
133 var opts []TracerProviderOption
134 if test.opt != nil {
135 opts = append(opts, WithSpanLimits(*test.opt))
136 }
137 if test.rawOpt != nil {
138 opts = append(opts, WithRawSpanLimits(*test.rawOpt))
139 }
140
141 assert.Equal(t, test.want, NewTracerProvider(opts...).spanLimits)
142 })
143 }
144 }
145
146 type recorder []ReadOnlySpan
147
148 func (r *recorder) OnStart(context.Context, ReadWriteSpan) {}
149 func (r *recorder) OnEnd(s ReadOnlySpan) { *r = append(*r, s) }
150 func (r *recorder) ForceFlush(context.Context) error { return nil }
151 func (r *recorder) Shutdown(context.Context) error { return nil }
152
153 func testSpanLimits(t *testing.T, limits SpanLimits) ReadOnlySpan {
154 rec := new(recorder)
155 tp := NewTracerProvider(WithRawSpanLimits(limits), WithSpanProcessor(rec))
156 tracer := tp.Tracer("testSpanLimits")
157
158 ctx := context.Background()
159 a := []attribute.KeyValue{attribute.Bool("one", true), attribute.Bool("two", true)}
160 l := trace.Link{
161 SpanContext: trace.NewSpanContext(trace.SpanContextConfig{
162 TraceID: [16]byte{0x01},
163 SpanID: [8]byte{0x01},
164 }),
165 Attributes: a,
166 }
167 _, span := tracer.Start(ctx, "span-name", trace.WithLinks(l, l))
168 span.SetAttributes(
169 attribute.String("string", "abc"),
170 attribute.StringSlice("stringSlice", []string{"abc", "def"}),
171 attribute.String("euro", "€"),
172 )
173 span.AddEvent("event 1", trace.WithAttributes(a...))
174 span.AddEvent("event 2", trace.WithAttributes(a...))
175 span.End()
176 require.NoError(t, tp.Shutdown(ctx))
177
178 require.Len(t, *rec, 1, "exported spans")
179 return (*rec)[0]
180 }
181
182 func TestSpanLimits(t *testing.T) {
183 t.Run("AttributeValueLengthLimit", func(t *testing.T) {
184 limits := NewSpanLimits()
185
186 limits.AttributeValueLengthLimit = -1
187 attrs := testSpanLimits(t, limits).Attributes()
188 assert.Contains(t, attrs, attribute.String("string", "abc"))
189 assert.Contains(t, attrs, attribute.StringSlice("stringSlice", []string{"abc", "def"}))
190 assert.Contains(t, attrs, attribute.String("euro", "€"))
191
192 limits.AttributeValueLengthLimit = 2
193 attrs = testSpanLimits(t, limits).Attributes()
194
195 assert.Contains(t, attrs, attribute.String("string", "ab"))
196 assert.Contains(t, attrs, attribute.StringSlice("stringSlice", []string{"ab", "de"}))
197 assert.Contains(t, attrs, attribute.String("euro", ""))
198
199 limits.AttributeValueLengthLimit = 0
200 attrs = testSpanLimits(t, limits).Attributes()
201 assert.Contains(t, attrs, attribute.String("string", ""))
202 assert.Contains(t, attrs, attribute.StringSlice("stringSlice", []string{"", ""}))
203 assert.Contains(t, attrs, attribute.String("euro", ""))
204 })
205
206 t.Run("AttributeCountLimit", func(t *testing.T) {
207 limits := NewSpanLimits()
208
209 limits.AttributeCountLimit = -1
210 assert.Len(t, testSpanLimits(t, limits).Attributes(), 3)
211
212 limits.AttributeCountLimit = 1
213 assert.Len(t, testSpanLimits(t, limits).Attributes(), 1)
214
215
216 limits.AttributeCountLimit = 0
217 assert.Len(t, testSpanLimits(t, limits).Attributes(), 0)
218 })
219
220 t.Run("EventCountLimit", func(t *testing.T) {
221 limits := NewSpanLimits()
222
223 limits.EventCountLimit = -1
224 assert.Len(t, testSpanLimits(t, limits).Events(), 2)
225
226 limits.EventCountLimit = 1
227 assert.Len(t, testSpanLimits(t, limits).Events(), 1)
228
229
230 limits.EventCountLimit = 0
231 assert.Len(t, testSpanLimits(t, limits).Events(), 0)
232 })
233
234 t.Run("AttributePerEventCountLimit", func(t *testing.T) {
235 limits := NewSpanLimits()
236
237 limits.AttributePerEventCountLimit = -1
238 for _, e := range testSpanLimits(t, limits).Events() {
239 assert.Len(t, e.Attributes, 2)
240 }
241
242 limits.AttributePerEventCountLimit = 1
243 for _, e := range testSpanLimits(t, limits).Events() {
244 assert.Len(t, e.Attributes, 1)
245 }
246
247
248 limits.AttributePerEventCountLimit = 0
249 for _, e := range testSpanLimits(t, limits).Events() {
250 assert.Len(t, e.Attributes, 0)
251 }
252 })
253
254 t.Run("LinkCountLimit", func(t *testing.T) {
255 limits := NewSpanLimits()
256
257 limits.LinkCountLimit = -1
258 assert.Len(t, testSpanLimits(t, limits).Links(), 2)
259
260 limits.LinkCountLimit = 1
261 assert.Len(t, testSpanLimits(t, limits).Links(), 1)
262
263
264 limits.LinkCountLimit = 0
265 assert.Len(t, testSpanLimits(t, limits).Links(), 0)
266 })
267
268 t.Run("AttributePerLinkCountLimit", func(t *testing.T) {
269 limits := NewSpanLimits()
270
271 limits.AttributePerLinkCountLimit = -1
272 for _, l := range testSpanLimits(t, limits).Links() {
273 assert.Len(t, l.Attributes, 2)
274 }
275
276 limits.AttributePerLinkCountLimit = 1
277 for _, l := range testSpanLimits(t, limits).Links() {
278 assert.Len(t, l.Attributes, 1)
279 }
280
281
282 limits.AttributePerLinkCountLimit = 0
283 for _, l := range testSpanLimits(t, limits).Links() {
284 assert.Len(t, l.Attributes, 0)
285 }
286 })
287 }
288
View as plain text