From 62c6bb61faef37e1967f91aa5bb54bca5761c6dd Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 2 Sep 2026 15:15:05 +0200 Subject: [PATCH 1/3] feat(aiohttp): Add http.route attribute --- sentry_sdk/integrations/aiohttp.py | 10 ++++-- tests/integrations/aiohttp/test_aiohttp.py | 36 ++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py index 3819256773..026b0b1911 100644 --- a/sentry_sdk/integrations/aiohttp.py +++ b/sentry_sdk/integrations/aiohttp.py @@ -233,6 +233,7 @@ async def sentry_app_handle( }, parent_span=None, ) + scope.get_current_scope()._server_segment_span = span_ctx else: transaction = continue_trace( headers, @@ -323,14 +324,19 @@ async def sentry_urldispatcher_resolve( if integration is None: return rv + route_info = rv.get_info() + pattern = route_info.get("path") or route_info.get("formatter") + + server_span = sentry_sdk.get_current_scope()._server_segment_span + if server_span is not None: + server_span.set_attribute(SPANDATA.HTTP_ROUTE, pattern) + name = None try: if integration.transaction_style == "handler_name": name = transaction_from_function(rv.handler) elif integration.transaction_style == "method_and_path_pattern": - route_info = rv.get_info() - pattern = route_info.get("path") or route_info.get("formatter") name = "{} {}".format(request.method, pattern) except Exception: pass diff --git a/tests/integrations/aiohttp/test_aiohttp.py b/tests/integrations/aiohttp/test_aiohttp.py index 3eefdc9444..8d4d32ab1d 100644 --- a/tests/integrations/aiohttp/test_aiohttp.py +++ b/tests/integrations/aiohttp/test_aiohttp.py @@ -1882,6 +1882,42 @@ async def hello(request): assert server_segment["attributes"]["sentry.segment.name.source"] == expected_source +@pytest.mark.asyncio +@pytest.mark.parametrize( + "url,expected_route", + [ + ("/message", "/{var}"), + ], +) +async def test_http_route( + sentry_init, + aiohttp_client, + capture_items, + url, + expected_route, +): + sentry_init( + integrations=[AioHttpIntegration()], + traces_sample_rate=1.0, + trace_lifecycle="stream", + ) + + async def hello(request): + return web.Response(text="hello") + + app = web.Application() + app.router.add_get(r"/{var}", hello) + + items = capture_items("span") + + client = await aiohttp_client(app) + await client.get(url) + + sentry_sdk.flush() + (segment,) = (item.payload for item in items if item.payload.get("is_segment")) + assert segment["attributes"]["http.route"] == expected_route + + @pytest.mark.asyncio async def test_server_error_span_streaming(sentry_init, aiohttp_client, capture_items): sentry_init( From b0e20d504d2daa34e0a06ee5783325ba2f393581 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 2 Sep 2026 15:25:53 +0200 Subject: [PATCH 2/3] only set if not None --- sentry_sdk/integrations/aiohttp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py index 026b0b1911..42f91739b6 100644 --- a/sentry_sdk/integrations/aiohttp.py +++ b/sentry_sdk/integrations/aiohttp.py @@ -328,7 +328,7 @@ async def sentry_urldispatcher_resolve( pattern = route_info.get("path") or route_info.get("formatter") server_span = sentry_sdk.get_current_scope()._server_segment_span - if server_span is not None: + if server_span is not None and pattern is not None: server_span.set_attribute(SPANDATA.HTTP_ROUTE, pattern) name = None From 8375cc98204b32c4156c995dd2c3c06b5f6f95e4 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Thu, 3 Sep 2026 08:56:59 +0200 Subject: [PATCH 3/3] use SPANDATA const in tests --- tests/integrations/aiohttp/test_aiohttp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integrations/aiohttp/test_aiohttp.py b/tests/integrations/aiohttp/test_aiohttp.py index 8d4d32ab1d..918148b062 100644 --- a/tests/integrations/aiohttp/test_aiohttp.py +++ b/tests/integrations/aiohttp/test_aiohttp.py @@ -1915,7 +1915,7 @@ async def hello(request): sentry_sdk.flush() (segment,) = (item.payload for item in items if item.payload.get("is_segment")) - assert segment["attributes"]["http.route"] == expected_route + assert segment["attributes"][SPANDATA.HTTP_ROUTE] == expected_route @pytest.mark.asyncio