Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions sentry_sdk/integrations/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,11 @@ async def _run_app(
),
)

if headers.get("user-agent"):
sentry_scope.set_attribute(
SPANDATA.USER_AGENT_ORIGINAL, headers["user-agent"]
)

ty = scope["type"]
(
transaction_name,
Expand Down
111 changes: 63 additions & 48 deletions tests/integrations/asgi/test_asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,33 @@ async def app(scope, receive, send):
return app


@pytest.fixture
def asgi3_app_with_span():
async def app(scope, receive, send):
if scope["type"] == "lifespan":
while True:
message = await receive()
if message["type"] == "lifespan.startup":
await send({"type": "lifespan.startup.complete"})
elif message["type"] == "lifespan.shutdown":
await send({"type": "lifespan.shutdown.complete"})
return

with sentry_sdk.traces.start_span(name="child-span"):
pass

await send(
{
"type": "http.response.start",
"status": 200,
"headers": [[b"content-type", b"text/plain"]],
}
)
await send({"type": "http.response.body", "body": b"Hello, world!"})

return app


def test_invalid_transaction_style(asgi3_app):
with pytest.raises(ValueError) as exp:
SentryAsgiMiddleware(asgi3_app, transaction_style="URL")
Expand Down Expand Up @@ -1441,40 +1468,20 @@ async def test_user_ip_address_on_all_spans(
capture_items,
init_kwargs,
expect_ip,
asgi3_app_with_span,
):
async def app(scope, receive, send):
if scope["type"] == "lifespan":
while True:
message = await receive()
if message["type"] == "lifespan.startup":
await send({"type": "lifespan.startup.complete"})
elif message["type"] == "lifespan.shutdown":
await send({"type": "lifespan.shutdown.complete"})
return

with sentry_sdk.traces.start_span(name="child-span"):
pass

await send(
{
"type": "http.response.start",
"status": 200,
"headers": [[b"content-type", b"text/plain"]],
}
)
await send({"type": "http.response.body", "body": b"Hello, world!"})

kwargs = dict(init_kwargs)
sentry_init(
trace_lifecycle="stream",
traces_sample_rate=1.0,
**kwargs,
)
sentry_app = SentryAsgiMiddleware(app)

app = SentryAsgiMiddleware(asgi3_app_with_span)

async def wrapped_app(scope, receive, send):
scope["client"] = ("127.0.0.1", 0)
await sentry_app(scope, receive, send)
await app(scope, receive, send)

async with TestClient(wrapped_app) as client:
items = capture_items("span")
Expand Down Expand Up @@ -1517,31 +1524,14 @@ async def test_is_localhost_attribute(
server,
host_header,
is_localhost,
asgi3_app_with_span,
):
async def app(scope, receive, send):
if scope["type"] == "lifespan":
while True:
message = await receive()
if message["type"] == "lifespan.startup":
await send({"type": "lifespan.startup.complete"})
elif message["type"] == "lifespan.shutdown":
await send({"type": "lifespan.shutdown.complete"})
return

with sentry_sdk.traces.start_span(name="child-span"):
pass

await send(
{
"type": "http.response.start",
"status": 200,
"headers": [[b"content-type", b"text/plain"]],
}
)
await send({"type": "http.response.body", "body": b"Hello, world!"})
sentry_init(
traces_sample_rate=1.0,
trace_lifecycle="stream",
)

sentry_init(traces_sample_rate=1.0, trace_lifecycle="stream")
sentry_app = SentryAsgiMiddleware(app)
app = SentryAsgiMiddleware(asgi3_app_with_span)

async def wrapped_app(scope, receive, send):
if scope["type"] != "lifespan":
Expand All @@ -1551,7 +1541,7 @@ async def wrapped_app(scope, receive, send):
if host_header is not None:
scope["headers"].append((b"host", host_header))

await sentry_app(scope, receive, send)
await app(scope, receive, send)

async with TestClient(wrapped_app) as client:
items = capture_items("span")
Expand All @@ -1563,3 +1553,28 @@ async def wrapped_app(scope, receive, send):

assert server_span["attributes"]["sentry.is_localhost"] is is_localhost
assert child_span["attributes"]["sentry.is_localhost"] is is_localhost


@pytest.mark.asyncio
async def test_user_agent_original_attribute(
sentry_init,
capture_items,
asgi3_app_with_span,
):
sentry_init(
traces_sample_rate=1.0,
trace_lifecycle="stream",
)

app = SentryAsgiMiddleware(asgi3_app_with_span)

async with TestClient(app) as client:
items = capture_items("span")
await client.get("/some_url", headers={"User-Agent": "TestBrowser/1.0"})

sentry_sdk.flush()

child_span, server_span = [item.payload for item in items]

assert server_span["attributes"]["user_agent.original"] == "TestBrowser/1.0"
assert child_span["attributes"]["user_agent.original"] == "TestBrowser/1.0"
Loading