diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index deb05059d5..dbb47dff58 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -693,7 +693,11 @@ def _transaction_name_from_router(scope): for route in router.routes: match = route.matches(scope) if match[0] == Match.FULL: - return route.path + try: + return route.path + except AttributeError: + # routes added via app.host() won't have a path attribute + return scope.get("path") return None diff --git a/tests/integrations/fastapi/test_fastapi.py b/tests/integrations/fastapi/test_fastapi.py index f1c0a69305..4cb9ea1716 100644 --- a/tests/integrations/fastapi/test_fastapi.py +++ b/tests/integrations/fastapi/test_fastapi.py @@ -682,3 +682,38 @@ async def _error(): client.get("/error") assert len(events) == int(expected_error) + + +@pytest.mark.parametrize("transaction_style", ["endpoint", "url"]) +def test_app_host(sentry_init, capture_events, transaction_style): + sentry_init( + traces_sample_rate=1.0, + integrations=[ + StarletteIntegration(transaction_style=transaction_style), + FastApiIntegration(transaction_style=transaction_style), + ], + ) + + app = FastAPI() + subapp = FastAPI() + + @subapp.get("/subapp") + async def subapp_route(): + return {"message": "Hello world!"} + + app.host("subapp", subapp) + + events = capture_events() + + client = TestClient(app) + client.get("/subapp", headers={"Host": "subapp"}) + + assert len(events) == 1 + + (event,) = events + assert "transaction" in event + + if transaction_style == "url": + assert event["transaction"] == "/subapp" + else: + assert event["transaction"].endswith("subapp_route")