Skip to content

Commit c0bf515

Browse files
committed
simple tests
1 parent ab49b1c commit c0bf515

1 file changed

Lines changed: 373 additions & 0 deletions

File tree

Lines changed: 373 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,373 @@
1+
import time
2+
from unittest import mock
3+
4+
import sentry_sdk
5+
6+
7+
def envelopes_to_spans(envelopes):
8+
res = [] # type: List[Metric]
9+
for envelope in envelopes:
10+
for item in envelope.items:
11+
if item.type == "span":
12+
for span_json in item.payload.json["items"]:
13+
span = {
14+
"start_timestamp": span_json["start_timestamp"],
15+
"end_timestamp": span_json.get("end_timestamp"),
16+
"trace_id": span_json["trace_id"],
17+
"span_id": span_json["span_id"],
18+
"name": span_json["name"],
19+
"status": span_json["status"],
20+
"is_segment": span_json["is_segment"],
21+
"parent_span_id": span_json.get("parent_span_id"),
22+
"attributes": {
23+
k: v["value"] for (k, v) in span_json["attributes"].items()
24+
},
25+
}
26+
res.append(span)
27+
return res
28+
29+
30+
def test_start_span(sentry_init, capture_envelopes):
31+
sentry_init(
32+
traces_sample_rate=1.0,
33+
_experiments={"trace_lifecycle": "stream"},
34+
)
35+
36+
events = capture_envelopes()
37+
38+
with sentry_sdk.traces.start_span(name="segment"):
39+
with sentry_sdk.traces.start_span(name="child"):
40+
...
41+
42+
sentry_sdk.get_client().flush()
43+
spans = envelopes_to_spans(events)
44+
45+
assert len(spans) == 2
46+
child, segment = spans
47+
48+
assert segment["name"] == "segment"
49+
assert segment["attributes"]["sentry.segment.name"] == "segment"
50+
assert child["name"] == "child"
51+
assert child["attributes"]["sentry.segment.name"] == "segment"
52+
53+
assert segment["is_segment"] is True
54+
assert segment["parent_span_id"] is None
55+
assert child["is_segment"] is False
56+
assert child["parent_span_id"] == segment["span_id"]
57+
assert child["trace_id"] == segment["trace_id"]
58+
59+
assert segment["start_timestamp"] is not None
60+
assert child["start_timestamp"] is not None
61+
assert segment["end_timestamp"] is not None
62+
assert child["end_timestamp"] is not None
63+
64+
assert child["status"] == "ok"
65+
assert segment["status"] == "ok"
66+
67+
68+
def test_start_span_no_context_manager(sentry_init, capture_envelopes):
69+
sentry_init(
70+
traces_sample_rate=1.0,
71+
_experiments={"trace_lifecycle": "stream"},
72+
)
73+
74+
events = capture_envelopes()
75+
76+
segment = sentry_sdk.traces.start_span(name="segment")
77+
segment.start()
78+
child = sentry_sdk.traces.start_span(name="child")
79+
child.start()
80+
child.finish()
81+
segment.finish()
82+
83+
sentry_sdk.get_client().flush()
84+
spans = envelopes_to_spans(events)
85+
86+
assert len(spans) == 2
87+
child, segment = spans
88+
89+
assert segment["name"] == "segment"
90+
assert segment["attributes"]["sentry.segment.name"] == "segment"
91+
assert child["name"] == "child"
92+
assert child["attributes"]["sentry.segment.name"] == "segment"
93+
94+
assert segment["is_segment"] is True
95+
assert child["is_segment"] is False
96+
assert child["parent_span_id"] == segment["span_id"]
97+
assert child["trace_id"] == segment["trace_id"]
98+
99+
assert segment["start_timestamp"] is not None
100+
assert child["start_timestamp"] is not None
101+
assert segment["end_timestamp"] is not None
102+
assert child["end_timestamp"] is not None
103+
104+
assert child["status"] == "ok"
105+
assert segment["status"] == "ok"
106+
107+
108+
def test_start_span_attributes(sentry_init, capture_envelopes):
109+
sentry_init(
110+
traces_sample_rate=1.0,
111+
_experiments={"trace_lifecycle": "stream"},
112+
)
113+
114+
events = capture_envelopes()
115+
116+
with sentry_sdk.traces.start_span(
117+
name="segment", attributes={"my_attribute": "my_value"}
118+
):
119+
...
120+
121+
sentry_sdk.get_client().flush()
122+
spans = envelopes_to_spans(events)
123+
124+
assert len(spans) == 1
125+
(span,) = spans
126+
127+
assert span["name"] == "segment"
128+
assert span["attributes"]["my_attribute"] == "my_value"
129+
130+
131+
def test_start_span_attributes_in_traces_sampler(sentry_init, capture_envelopes):
132+
def traces_sampler(sampling_context):
133+
assert "attributes" in sampling_context
134+
assert "my_attribute" in sampling_context["attributes"]
135+
assert sampling_context["attributes"]["my_attribute"] == "my_value"
136+
return 1.0
137+
138+
sentry_init(
139+
traces_sampler=traces_sampler,
140+
_experiments={"trace_lifecycle": "stream"},
141+
)
142+
143+
events = capture_envelopes()
144+
145+
with sentry_sdk.traces.start_span(
146+
name="segment", attributes={"my_attribute": "my_value"}
147+
):
148+
...
149+
150+
sentry_sdk.get_client().flush()
151+
spans = envelopes_to_spans(events)
152+
153+
assert len(spans) == 1
154+
(span,) = spans
155+
156+
assert span["name"] == "segment"
157+
assert span["attributes"]["my_attribute"] == "my_value"
158+
159+
160+
def test_traces_sampler_drops_span(sentry_init, capture_envelopes):
161+
def traces_sampler(sampling_context):
162+
assert "attributes" in sampling_context
163+
assert "drop" in sampling_context["attributes"]
164+
165+
if sampling_context["attributes"]["drop"] is True:
166+
return 0.0
167+
168+
return 1.0
169+
170+
sentry_init(
171+
traces_sampler=traces_sampler,
172+
_experiments={"trace_lifecycle": "stream"},
173+
)
174+
175+
events = capture_envelopes()
176+
177+
with sentry_sdk.traces.start_span(name="dropped", attributes={"drop": True}):
178+
...
179+
with sentry_sdk.traces.start_span(name="retained", attributes={"drop": False}):
180+
...
181+
182+
sentry_sdk.get_client().flush()
183+
spans = envelopes_to_spans(events)
184+
185+
assert len(spans) == 1
186+
(span,) = spans
187+
188+
assert span["name"] == "retained"
189+
assert span["attributes"]["drop"] is False
190+
191+
192+
def test_traces_sampler_called_once_per_segment(sentry_init):
193+
traces_sampler_called = 0
194+
span_id_in_traces_sampler = None
195+
196+
def traces_sampler(sampling_context):
197+
nonlocal traces_sampler_called, span_id_in_traces_sampler
198+
traces_sampler_called += 1
199+
span_id_in_traces_sampler = sampling_context["transaction_context"]["span_id"]
200+
return 1.0
201+
202+
sentry_init(
203+
traces_sampler=traces_sampler,
204+
_experiments={"trace_lifecycle": "stream"},
205+
)
206+
207+
with sentry_sdk.traces.start_span(name="segment") as segment:
208+
with sentry_sdk.traces.start_span(name="child1"):
209+
...
210+
with sentry_sdk.traces.start_span(name="child2"):
211+
with sentry_sdk.traces.start_span(name="child3"):
212+
...
213+
214+
assert traces_sampler_called == 1
215+
assert span_id_in_traces_sampler == segment.span_id
216+
217+
218+
def test_start_span_override_parent(sentry_init, capture_envelopes):
219+
sentry_init(
220+
traces_sample_rate=1.0,
221+
_experiments={"trace_lifecycle": "stream"},
222+
)
223+
224+
events = capture_envelopes()
225+
226+
with sentry_sdk.traces.start_span(name="segment") as segment:
227+
with sentry_sdk.traces.start_span(name="child1"):
228+
with sentry_sdk.traces.start_span(name="child2", parent_span=segment):
229+
pass
230+
231+
sentry_sdk.get_client().flush()
232+
spans = envelopes_to_spans(events)
233+
234+
assert len(spans) == 3
235+
child2, child1, segment = spans
236+
237+
assert segment["name"] == "segment"
238+
assert segment["attributes"]["sentry.segment.name"] == "segment"
239+
240+
assert child1["name"] == "child1"
241+
assert child1["attributes"]["sentry.segment.name"] == "segment"
242+
243+
assert child2["name"] == "child2"
244+
assert child2["attributes"]["sentry.segment.name"] == "segment"
245+
246+
assert segment["is_segment"] is True
247+
248+
assert child1["is_segment"] is False
249+
assert child1["parent_span_id"] == segment["span_id"]
250+
assert child1["trace_id"] == segment["trace_id"]
251+
252+
assert child2["is_segment"] is False
253+
assert child2["parent_span_id"] == segment["span_id"]
254+
assert child2["trace_id"] == segment["trace_id"]
255+
256+
257+
def test_sibling_segments(sentry_init, capture_envelopes):
258+
sentry_init(
259+
traces_sample_rate=1.0,
260+
_experiments={"trace_lifecycle": "stream"},
261+
)
262+
263+
events = capture_envelopes()
264+
265+
with sentry_sdk.traces.start_span(name="segment1"):
266+
...
267+
268+
with sentry_sdk.traces.start_span(name="segment2"):
269+
...
270+
271+
sentry_sdk.get_client().flush()
272+
spans = envelopes_to_spans(events)
273+
274+
assert len(spans) == 2
275+
segment1, segment2 = spans
276+
277+
assert segment1["name"] == "segment1"
278+
assert segment1["attributes"]["sentry.segment.name"] == "segment1"
279+
assert segment1["is_segment"] is True
280+
assert segment1["parent_span_id"] is None
281+
282+
assert segment2["name"] == "segment2"
283+
assert segment2["attributes"]["sentry.segment.name"] == "segment2"
284+
assert segment2["is_segment"] is True
285+
assert segment2["parent_span_id"] is None
286+
287+
assert segment1["trace_id"] == segment1["trace_id"]
288+
289+
290+
def test_sibling_segments_new_trace(sentry_init, capture_envelopes):
291+
sentry_init(
292+
traces_sample_rate=1.0,
293+
_experiments={"trace_lifecycle": "stream"},
294+
)
295+
296+
events = capture_envelopes()
297+
298+
with sentry_sdk.traces.start_span(name="segment1"):
299+
...
300+
301+
sentry_sdk.traces.new_trace()
302+
303+
with sentry_sdk.traces.start_span(name="segment2"):
304+
...
305+
306+
sentry_sdk.get_client().flush()
307+
spans = envelopes_to_spans(events)
308+
309+
assert len(spans) == 2
310+
segment1, segment2 = spans
311+
312+
assert segment1["name"] == "segment1"
313+
assert segment1["attributes"]["sentry.segment.name"] == "segment1"
314+
assert segment1["is_segment"] is True
315+
assert segment1["parent_span_id"] is None
316+
317+
assert segment2["name"] == "segment2"
318+
assert segment2["attributes"]["sentry.segment.name"] == "segment2"
319+
assert segment2["is_segment"] is True
320+
assert segment2["parent_span_id"] is None
321+
322+
assert segment1["trace_id"] != segment2["trace_id"]
323+
324+
325+
def test_transport_format(sentry_init, capture_envelopes):
326+
sentry_init(
327+
server_name="test-server",
328+
release="1.0.0",
329+
traces_sample_rate=1.0,
330+
_experiments={"trace_lifecycle": "stream"},
331+
)
332+
333+
envelopes = capture_envelopes()
334+
335+
with sentry_sdk.traces.start_span(name="test"):
336+
...
337+
338+
sentry_sdk.get_client().flush()
339+
340+
assert len(envelopes) == 1
341+
assert len(envelopes[0].items) == 1
342+
item = envelopes[0].items[0]
343+
344+
assert item.type == "span"
345+
assert item.headers == {
346+
"type": "span",
347+
"item_count": 1,
348+
"content_type": "application/vnd.sentry.items.span.v2+json",
349+
}
350+
assert item.payload.json == {
351+
"items": [
352+
{
353+
"trace_id": mock.ANY,
354+
"span_id": mock.ANY,
355+
"name": "test",
356+
"status": "ok",
357+
"is_segment": True,
358+
"start_timestamp": mock.ANY,
359+
"end_timestamp": mock.ANY,
360+
"attributes": {
361+
"sentry.span.source": {"value": "custom", "type": "string"},
362+
"thread.id": {"value": mock.ANY, "type": "string"},
363+
"thread.name": {"value": "MainThread", "type": "string"},
364+
"sentry.segment.name": {"value": "test", "type": "string"},
365+
"sentry.sdk.name": {"value": "sentry.python", "type": "string"},
366+
"sentry.sdk.version": {"value": mock.ANY, "type": "string"},
367+
"server.address": {"value": "test-server", "type": "string"},
368+
"sentry.environment": {"value": "production", "type": "string"},
369+
"sentry.release": {"value": "1.0.0", "type": "string"},
370+
},
371+
}
372+
]
373+
}

0 commit comments

Comments
 (0)