Skip to content

Commit 8689cfc

Browse files
krnrYuri Lobanoff
authored andcommitted
Use canonical name for aiohttp request span name
1 parent 34db73e commit 8689cfc

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
1212
## Unreleased
1313

14+
- `opentelemetry-instrumentation-aiohttp-server`: Use `canonical` attribute of the `Resource` as a span name.
15+
1416
## Version 1.38.0/0.59b0 (2025-10-16)
1517

1618
### Fixed

instrumentation/opentelemetry-instrumentation-aiohttp-server/src/opentelemetry/instrumentation/aiohttp_server/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ def get_default_span_details(request: web.Request) -> Tuple[str, dict]:
123123
a tuple of the span name, and any attributes to attach to the span.
124124
"""
125125
span_name = request.path.strip() or f"HTTP {request.method}"
126+
if request.match_info and request.match_info.route.resource:
127+
resource = request.match_info.route.resource
128+
if resource.canonical:
129+
span_name = resource.canonical
126130
return span_name, {}
127131

128132

instrumentation/opentelemetry-instrumentation-aiohttp-server/tests/test_aiohttp_server_integration.py

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from opentelemetry.semconv._incubating.attributes.http_attributes import (
2828
HTTP_METHOD,
2929
HTTP_STATUS_CODE,
30+
HTTP_TARGET,
3031
HTTP_URL,
3132
)
3233
from opentelemetry.test.globals_test import reset_trace_globals
@@ -81,7 +82,15 @@ async def fixture_server_fixture(tracer, aiohttp_server, suppress):
8182
AioHttpServerInstrumentor().instrument()
8283

8384
app = aiohttp.web.Application()
84-
app.add_routes([aiohttp.web.get("/test-path", default_handler)])
85+
app.add_routes(
86+
[
87+
aiohttp.web.get("/test-path", default_handler),
88+
aiohttp.web.get("/test-path/{url_param}", default_handler),
89+
aiohttp.web.get(
90+
"/object/{object_id}/action/{another_param}", default_handler
91+
),
92+
]
93+
)
8594
if suppress:
8695
with suppress_http_instrumentation():
8796
server = await aiohttp_server(app)
@@ -139,6 +148,53 @@ async def test_status_code_instrumentation(
139148
)
140149

141150

151+
@pytest.mark.asyncio
152+
@pytest.mark.parametrize(
153+
"url, example_paths",
154+
[
155+
(
156+
"/test-path/{url_param}",
157+
(
158+
"/test-path/foo",
159+
"/test-path/bar",
160+
),
161+
),
162+
(
163+
"/object/{object_id}/action/{another_param}",
164+
(
165+
"/object/1/action/bar",
166+
"/object/234/action/baz",
167+
),
168+
),
169+
],
170+
)
171+
async def test_url_params_instrumentation(
172+
tracer,
173+
server_fixture,
174+
aiohttp_client,
175+
url,
176+
example_paths,
177+
):
178+
_, memory_exporter = tracer
179+
server, _ = server_fixture
180+
181+
assert len(memory_exporter.get_finished_spans()) == 0
182+
183+
client = await aiohttp_client(server)
184+
for path in example_paths:
185+
await client.get(path)
186+
187+
assert len(memory_exporter.get_finished_spans()) == 2
188+
189+
for request_path, span in zip(
190+
example_paths, memory_exporter.get_finished_spans()
191+
):
192+
assert url == span.name
193+
assert request_path == span.attributes[HTTP_TARGET]
194+
full_url = f"http://{server.host}:{server.port}{request_path}"
195+
assert full_url == span.attributes[HTTP_URL]
196+
197+
142198
@pytest.mark.asyncio
143199
@pytest.mark.parametrize("suppress", [True])
144200
async def test_suppress_instrumentation(

0 commit comments

Comments
 (0)