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
69 changes: 57 additions & 12 deletions sentry_sdk/integrations/starlette.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,20 @@ async def _create_span_call(
if integration is None:
return await old_call(app, scope, receive, send, **kwargs)

route_path, name_source = _http_route_and_source_from_router(scope)

server_span = sentry_sdk.get_current_scope()._server_segment_span
if (
server_span is not None
and route_path is not None
and name_source == TransactionSource.ROUTE
):
server_span.set_attribute(SPANDATA.HTTP_ROUTE, route_path)

# Update transaction name with middleware name
name, source = _get_transaction_from_middleware(app, scope, integration)
name, source = _get_transaction_from_middleware(
app, integration, route_path=route_path, name_source=name_source
)

if name is not None:
sentry_sdk.get_current_scope().set_transaction_name(
Expand Down Expand Up @@ -541,10 +553,22 @@ async def _wrap_async_handler(

request = args[0]

route_path, name_source = _http_route_and_source_from_router(request.scope)

server_span = sentry_sdk.get_current_scope()._server_segment_span
if (
server_span is not None
and route_path is not None
and name_source == TransactionSource.ROUTE
):
server_span.set_attribute(SPANDATA.HTTP_ROUTE, route_path)

_set_transaction_name_and_source(
sentry_sdk.get_current_scope(),
integration.transaction_style,
request,
endpoint=request.scope.get("endpoint"),
route_path=route_path,
name_source=name_source,
)

sentry_scope = sentry_sdk.get_isolation_scope()
Expand Down Expand Up @@ -647,8 +671,24 @@ def _sentry_sync_func(*args: "Any", **kwargs: "Any") -> "Any":

request = args[0]

route_path, name_source = _http_route_and_source_from_router(
request.scope
)

server_span = sentry_sdk.get_current_scope()._server_segment_span
if (
server_span is not None
and route_path is not None
and name_source == TransactionSource.ROUTE
):
server_span.set_attribute(SPANDATA.HTTP_ROUTE, route_path)

_set_transaction_name_and_source(
current_scope, integration.transaction_style, request
current_scope,
integration.transaction_style,
endpoint=request.scope.get("endpoint"),
route_path=route_path,
name_source=name_source,
)

extractor = StarletteRequestExtractor(request)
Expand Down Expand Up @@ -843,7 +883,7 @@ async def json(self: "StarletteRequestExtractor") -> "Optional[Dict[str, Any]]":
return None


def _transaction_name_and_source_from_router(
def _http_route_and_source_from_router(
scope: "StarletteScope",
) -> "Tuple[Optional[str], TransactionSource]":
router = scope.get("router")
Expand All @@ -864,18 +904,20 @@ def _transaction_name_and_source_from_router(


def _set_transaction_name_and_source(
scope: "sentry_sdk.Scope", transaction_style: str, request: "Any"
scope: "sentry_sdk.Scope",
transaction_style: str,
endpoint: "Optional[Callable[..., Any]]",
route_path: "Optional[str]",
name_source: "TransactionSource",
) -> None:
name = None
source = SOURCE_FOR_STYLE[transaction_style]

if transaction_style == "endpoint":
endpoint = request.scope.get("endpoint")
if endpoint:
name = transaction_from_function(endpoint) or None
if transaction_style == "endpoint" and endpoint:
name = transaction_from_function(endpoint) or None

elif transaction_style == "url":
name, source = _transaction_name_and_source_from_router(request.scope)
name, source = route_path, name_source

if name is None:
name = _DEFAULT_TRANSACTION_NAME
Expand All @@ -885,7 +927,10 @@ def _set_transaction_name_and_source(


def _get_transaction_from_middleware(
app: "Any", asgi_scope: "Dict[str, Any]", integration: "StarletteIntegration"
app: "Any",
integration: "StarletteIntegration",
route_path: "Optional[str]",
name_source: "TransactionSource",
) -> "Tuple[Optional[str], Optional[str]]":
name = None
source = None
Expand All @@ -894,6 +939,6 @@ def _get_transaction_from_middleware(
name = transaction_from_function(app.__class__)
source = TransactionSource.COMPONENT
elif integration.transaction_style == "url":
name, source = _transaction_name_and_source_from_router(asgi_scope)
name, source = route_path, name_source

return name, source
5 changes: 2 additions & 3 deletions tests/integrations/starlette/test_starlette.py
Original file line number Diff line number Diff line change
Expand Up @@ -1638,9 +1638,7 @@ def test_active_thread_id_span_streaming(sentry_init, capture_items, endpoint):


@pytest.mark.parametrize("endpoint", ["/sync/thread_ids", "/async/thread_ids"])
def test_segment_name_is_route_resolved_name_span_streaming(
sentry_init, capture_items, endpoint
):
def test_http_route_span_streaming(sentry_init, capture_items, endpoint):
sentry_init(
auto_enabling_integrations=False,
integrations=[StarletteIntegration(transaction_style="url")],
Expand All @@ -1661,6 +1659,7 @@ def test_segment_name_is_route_resolved_name_span_streaming(
assert len(segments) == 1
assert segments[0]["name"] == endpoint
assert segments[0]["attributes"]["sentry.segment.name.source"] == "route"
assert segments[0]["attributes"]["http.route"] == endpoint


@pytest.mark.parametrize("endpoint", ["/sync/thread_ids", "/async/thread_ids"])
Expand Down
Loading