Skip to content

Commit 7cde973

Browse files
committed
capture_items
1 parent e93fd1b commit 7cde973

File tree

2 files changed

+95
-21
lines changed

2 files changed

+95
-21
lines changed

tests/conftest.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import brotli
88
import gzip
99
import io
10+
from dataclasses import dataclass
1011
from threading import Thread
1112
from contextlib import contextmanager
1213
from http.server import BaseHTTPRequestHandler, HTTPServer
@@ -320,6 +321,47 @@ def append_envelope(envelope):
320321
return inner
321322

322323

324+
@dataclass
325+
class UnwrappedItem:
326+
type: str
327+
payload: dict
328+
329+
330+
@pytest.fixture
331+
def capture_items(monkeypatch):
332+
"""Capture envelope payload, unfurling individual items."""
333+
334+
def inner(types=None):
335+
telemetry = []
336+
test_client = sentry_sdk.get_client()
337+
old_capture_envelope = test_client.transport.capture_envelope
338+
339+
def append_envelope(envelope):
340+
for item in envelope:
341+
if types is None or item.type not in types:
342+
continue
343+
344+
if item.type in ("metric", "log", "span"):
345+
for json in item.payload.json["items"]:
346+
t = {k: v for k, v in json.items() if k != "attributes"}
347+
t["attributes"] = {
348+
k: v["value"] for k, v in json["attributes"].items()
349+
}
350+
telemetry.append(UnwrappedItem(type=item.type, payload=t))
351+
else:
352+
telemetry.append(
353+
UnwrappedItem(type=item.type, payload=item.payload.json)
354+
)
355+
356+
return old_capture_envelope(envelope)
357+
358+
monkeypatch.setattr(test_client.transport, "capture_envelope", append_envelope)
359+
360+
return telemetry
361+
362+
return inner
363+
364+
323365
@pytest.fixture
324366
def capture_record_lost_event_calls(monkeypatch):
325367
def inner():

tests/integrations/asgi/test_asgi.py

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from sentry_sdk.tracing import TransactionSource
77
from sentry_sdk.integrations._asgi_common import _get_ip, _get_headers
88
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware, _looks_like_asgi3
9-
from tests.conftest import envelopes_to_spans
109

1110
from async_asgi_testclient import TestClient
1211

@@ -166,17 +165,18 @@ def test_invalid_transaction_style(asgi3_app):
166165

167166
@pytest.mark.asyncio
168167
@pytest.mark.parametrize(
169-
("span_streaming"),
170-
(True, False),
168+
"span_streaming",
169+
[True, False],
171170
)
172171
async def test_capture_transaction(
173172
sentry_init,
174173
asgi3_app,
175174
capture_events,
176-
capture_envelopes,
175+
capture_items,
177176
span_streaming,
178177
):
179178
sentry_init(
179+
send_default_pii=True,
180180
traces_sample_rate=1.0,
181181
_experiments={
182182
"trace_lifecycle": "stream" if span_streaming else "static",
@@ -186,17 +186,16 @@ async def test_capture_transaction(
186186

187187
async with TestClient(app) as client:
188188
if span_streaming:
189-
envelopes = capture_envelopes()
189+
items = capture_items(["span"])
190190
else:
191191
events = capture_events()
192192
await client.get("/some_url?somevalue=123")
193193

194194
sentry_sdk.flush()
195195

196196
if span_streaming:
197-
spans = envelopes_to_spans(envelopes)
198-
assert len(spans) == 1
199-
(span,) = spans
197+
assert len(items) == 1
198+
span = items[0].payload
200199

201200
assert span["is_segment"] is True
202201
assert span["name"] == "/some_url"
@@ -234,24 +233,48 @@ async def test_capture_transaction(
234233

235234

236235
@pytest.mark.asyncio
236+
@pytest.mark.parametrize(
237+
"span_streaming",
238+
[True, False],
239+
)
237240
async def test_capture_transaction_with_error(
238241
sentry_init,
239242
asgi3_app_with_error,
240243
capture_events,
244+
capture_items,
241245
DictionaryContaining, # noqa: N803
246+
span_streaming,
242247
):
243-
sentry_init(send_default_pii=True, traces_sample_rate=1.0)
248+
sentry_init(
249+
send_default_pii=True,
250+
traces_sample_rate=1.0,
251+
_experiments={
252+
"trace_lifecycle": "stream" if span_streaming else "static",
253+
},
254+
)
255+
244256
app = SentryAsgiMiddleware(asgi3_app_with_error)
245257

246-
events = capture_events()
258+
if span_streaming:
259+
items = capture_items(["event", "span"])
260+
else:
261+
events = capture_events()
262+
247263
with pytest.raises(ZeroDivisionError):
248264
async with TestClient(app) as client:
249265
await client.get("/some_url")
250266

251-
(
252-
error_event,
253-
transaction_event,
254-
) = events
267+
sentry_sdk.flush()
268+
269+
if span_streaming:
270+
assert len(items) == 2
271+
assert items[0].type == "event"
272+
assert items[1].type == "span"
273+
274+
error_event = items[0].payload
275+
span_item = items[1].payload
276+
else:
277+
(error_event, transaction_event) = events
255278

256279
assert error_event["transaction"] == "/some_url"
257280
assert error_event["transaction_info"] == {"source": "url"}
@@ -261,13 +284,22 @@ async def test_capture_transaction_with_error(
261284
assert error_event["exception"]["values"][0]["mechanism"]["handled"] is False
262285
assert error_event["exception"]["values"][0]["mechanism"]["type"] == "asgi"
263286

264-
assert transaction_event["type"] == "transaction"
265-
assert transaction_event["contexts"]["trace"] == DictionaryContaining(
266-
error_event["contexts"]["trace"]
267-
)
268-
assert transaction_event["contexts"]["trace"]["status"] == "internal_error"
269-
assert transaction_event["transaction"] == error_event["transaction"]
270-
assert transaction_event["request"] == error_event["request"]
287+
if span_streaming:
288+
assert span_item["trace_id"] == error_event["contexts"]["trace"]["trace_id"]
289+
assert span_item["span_id"] == error_event["contexts"]["trace"]["span_id"]
290+
assert span_item.get("parent_span_id") == error_event["contexts"]["trace"].get(
291+
"parent_span_id"
292+
)
293+
assert span_item["status"] == "error"
294+
295+
else:
296+
assert transaction_event["type"] == "transaction"
297+
assert transaction_event["contexts"]["trace"] == DictionaryContaining(
298+
error_event["contexts"]["trace"]
299+
)
300+
assert transaction_event["contexts"]["trace"]["status"] == "internal_error"
301+
assert transaction_event["transaction"] == error_event["transaction"]
302+
assert transaction_event["request"] == error_event["request"]
271303

272304

273305
@pytest.mark.asyncio

0 commit comments

Comments
 (0)