diff --git a/CHANGELOG.md b/CHANGELOG.md index efb766bda4..58347bbce4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `opentelemetry-instrumentation-botocore` Use `cloud.region` instead of `aws.region` span attribute as per semantic conventions. ([#3474](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3474)) +### Fixed + +- `opentelemetry-instrumentation-starlette` Fixes a crash when host-based routing is used ([#3507](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3507/)) +- `opentelemetry-instrumentation-fastapi` Fixes a crash when host-based routing is used ([#3507](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3507/)) ## Version 1.33.0/0.54b0 (2025-05-09) @@ -44,7 +48,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `opentelemetry-instrumentation-botocore` Capture server attributes for botocore API calls ([#3448](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3448)) - ## Version 1.32.0/0.53b0 (2025-04-10) ### Added @@ -70,7 +73,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `opentelemetry-instrumentation-aiokafka` Fix send_and_wait method no headers kwargs error. ([[#3332](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3332)]) - ## Version 1.31.0/0.52b0 (2025-03-12) ### Added diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py index 1abff1adcb..1a33b28ec6 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py @@ -428,7 +428,11 @@ def _get_route_details(scope): for starlette_route in app.routes: match, _ = starlette_route.matches(scope) if match == Match.FULL: - route = starlette_route.path + try: + route = starlette_route.path + except AttributeError: + # routes added via host routing won't have a path attribute + route = scope.get("path") break if match == Match.PARTIAL: route = starlette_route.path diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py index 439cebf427..6bf1c03a00 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py @@ -207,6 +207,7 @@ async def _(): return {"message": "ok"} app.mount("/sub", app=sub_app) + app.host("testserver2", sub_app) return app @@ -263,6 +264,10 @@ def test_sub_app_fastapi_call(self): span.attributes[SpanAttributes.HTTP_URL], ) + def test_host_fastapi_call(self): + client = TestClient(self._app, base_url="https://testserver2") + client.get("/") + class TestBaseAutoFastAPI(TestBaseFastAPI): @classmethod diff --git a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py index 8df666c740..8d8f5fe41d 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py @@ -355,7 +355,11 @@ def _get_route_details(scope: dict[str, Any]) -> str | None: for starlette_route in app.routes: match, _ = starlette_route.matches(scope) if match == Match.FULL: - route = starlette_route.path + try: + route = starlette_route.path + except AttributeError: + # routes added via host routing won't have a path attribute + route = scope.get("path") break if match == Match.PARTIAL: route = starlette_route.path diff --git a/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py b/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py index 3f9f1c7b0f..4782382bf8 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py @@ -18,7 +18,7 @@ from starlette import applications from starlette.responses import PlainTextResponse -from starlette.routing import Mount, Route +from starlette.routing import Host, Mount, Route from starlette.testclient import TestClient from starlette.websockets import WebSocket @@ -140,6 +140,10 @@ def test_sub_app_starlette_call(self): span.attributes[SpanAttributes.HTTP_URL], ) + def test_host_starlette_call(self): + client = TestClient(self._app, base_url="http://testserver2") + client.get("/") + def test_starlette_route_attribute_added(self): """Ensure that starlette routes are used as the span name.""" self._client.get("/user/123") @@ -298,6 +302,7 @@ def sub_home(_): Route("/user/{username}", home), Route("/healthzz", health), Mount("/sub", app=sub_app), + Host("testserver2", sub_app), ], )