Skip to content
Open
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c5c2dfe
refactor(starlette): centralize active thread updates
faizansaiyed123 Oct 2, 2026
a14cd78
refactor(fastapi): use Starlette active thread helper
faizansaiyed123 Oct 2, 2026
87d3a13
chore(fastapi): remove unused thread helper import
faizansaiyed123 Oct 2, 2026
bdaadd5
refactor(fastapi): register active thread dependency globally
faizansaiyed123 Oct 2, 2026
1301df5
refactor(fastapi): remove private request handler patch
faizansaiyed123 Oct 2, 2026
4b487a3
test(fastapi): cover global dependency websocket compatibility
faizansaiyed123 Oct 2, 2026
ba306d1
style(fastapi): tidy global dependency setup
faizansaiyed123 Oct 2, 2026
d287e61
test(fastapi): preserve user global dependencies
faizansaiyed123 Oct 2, 2026
24f7914
test(fastapi): fix global dependency test placement
faizansaiyed123 Oct 2, 2026
19407b5
fix(starlette): preserve sync request scope access
faizansaiyed123 Oct 2, 2026
c0459e3
refactor(fastapi): move request setup into global dependency
faizansaiyed123 Oct 2, 2026
475f391
style(fastapi): tidy global dependency signature
faizansaiyed123 Oct 2, 2026
070f150
refactor(starlette): centralize sync thread wrapper
faizansaiyed123 Oct 2, 2026
3008a93
fix(fastapi): preserve sync endpoint thread tracking
faizansaiyed123 Oct 2, 2026
2af5b30
fix(fastapi): wrap effective route dependant
faizansaiyed123 Oct 2, 2026
ebcff1b
fix(fastapi): use effective dependant for sync routes
faizansaiyed123 Oct 2, 2026
6a70b84
test(fastapi): cover sync thread tracking in prefixed routes
faizansaiyed123 Oct 2, 2026
b55b5d6
style(fastapi): format thread metadata assertion
faizansaiyed123 Oct 2, 2026
b3e43e3
refactor(fastapi): restore request lifecycle in global dependency
faizansaiyed123 Oct 2, 2026
9a187d9
refactor(fastapi): simplify request event processor helper
faizansaiyed123 Oct 2, 2026
99ae098
test(fastapi): cover dependency order and request data
faizansaiyed123 Oct 2, 2026
cfb86e0
test(fastapi): enable tracing for dependency order check
faizansaiyed123 Oct 2, 2026
6f39b1e
test(fastapi): cover dependency order and request data
faizansaiyed123 Oct 2, 2026
fd54812
fix(fastapi): fall back to the routed dependant
faizansaiyed123 Oct 2, 2026
7b76b1f
test(fastapi): cover request data on all supported versions
faizansaiyed123 Oct 2, 2026
f824525
fix(fastapi): install request isolation with integration
faizansaiyed123 Oct 2, 2026
c428c6e
test(fastapi): isolate request event processors
faizansaiyed123 Oct 2, 2026
4cb785b
fix(starlette): reuse ASGI instrumentation for FastAPI
faizansaiyed123 Oct 2, 2026
0468859
test(fastapi): verify request processor cleanup
faizansaiyed123 Oct 2, 2026
1fc5ea8
sync starlette integration with verified PR state
faizansaiyed123 Oct 2, 2026
1e3d9c2
sync fastapi tests with verified PR state
faizansaiyed123 Oct 2, 2026
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
Prev Previous commit
Next Next commit
refactor(fastapi): restore request lifecycle in global dependency
  • Loading branch information
faizansaiyed123 committed Oct 2, 2026
commit b3e43e3c3f7c20c6aa1e8722fc6b2c37932c332d
72 changes: 66 additions & 6 deletions sentry_sdk/integrations/fastapi.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
from copy import deepcopy
from functools import wraps
from typing import TYPE_CHECKING

import sentry_sdk
from sentry_sdk.consts import SPANDATA
from sentry_sdk.integrations import DidNotEnable
from sentry_sdk.traces import StreamedSpan, get_current_span
from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource
from sentry_sdk.utils import transaction_from_function
from sentry_sdk.utils import has_data_collection_enabled, transaction_from_function

if TYPE_CHECKING:
from typing import Any, Callable, Optional

try:
from sentry_sdk.integrations.starlette import (
StarletteIntegration,
StarletteRequestExtractor,
_get_cached_request_body_attribute,
_is_async_callable,
_wrap_sync_handler,
)
Expand All @@ -37,12 +41,15 @@ def setup_once() -> None:
patch_fastapi_init()
Comment thread
cursor[bot] marked this conversation as resolved.


async def _sentry_fastapi_dependency(request: "HTTPConnection") -> None:
async def _sentry_fastapi_dependency(request: "HTTPConnection"):
if not isinstance(request, Request):
yield
return

integration = sentry_sdk.get_client().get_integration(FastApiIntegration)
client = sentry_sdk.get_client()
integration = client.get_integration(FastApiIntegration)
if integration is None:
yield
return

current_scope = sentry_sdk.get_current_scope()
Expand All @@ -68,6 +75,8 @@ async def _sentry_fastapi_dependency(request: "HTTPConnection") -> None:
route_path=route_path,
)
Comment thread
cursor[bot] marked this conversation as resolved.

# FastAPI 0.137+ may execute the dependant stored on the effective route
# context instead of the original APIRoute.
dependant = getattr(route, "dependant", None)
if (
dependant is not None
Expand All @@ -76,7 +85,59 @@ async def _sentry_fastapi_dependency(request: "HTTPConnection") -> None:
):
dependant.call = _wrap_sync_handler(dependant.call)
Comment thread
cursor[bot] marked this conversation as resolved.

sentry_sdk.get_isolation_scope()._name = FastApiIntegration.identifier
sentry_scope = sentry_sdk.get_isolation_scope()
extractor = StarletteRequestExtractor(request)
info = await extractor.extract_request_info()

def _make_request_event_processor(
request_info: "dict[str, Any]",
) -> "Callable[[Any, dict[str, Any]], Any]":
def event_processor(
event: "dict[str, Any]", hint: "dict[str, Any]"
) -> "dict[str, Any]":
event_request = event.get("request", {})
if info:
if "cookies" in info:
event_request["cookies"] = info["cookies"]
if "data" in info:
attach_request_data = True
if has_data_collection_enabled(client.options):
attach_request_data = (
"incoming_request"
in client.options["data_collection"]["http_bodies"]
)

if attach_request_data:
event_request["data"] = info["data"]
event["request"] = deepcopy(event_request)
return event

return event_processor

sentry_scope._name = FastApiIntegration.identifier
sentry_scope.add_event_processor(_make_request_event_processor(info))
Comment thread
cursor[bot] marked this conversation as resolved.

try:
yield
finally:
current_span = get_current_span()
if type(current_span) is StreamedSpan:
attach_request_data = True
if has_data_collection_enabled(client.options):
attach_request_data = (
"incoming_request"
in client.options["data_collection"]["http_bodies"]
)

if attach_request_data:
request_body = _get_cached_request_body_attribute(
client=client, request=request
)
if request_body:
current_span._segment.set_attribute(
SPANDATA.HTTP_REQUEST_BODY_DATA,
request_body,
)


def patch_fastapi_init() -> None:
Expand All @@ -92,8 +153,8 @@ def _sentry_fastapi_init(self: "Any", *args: "Any", **kwargs: "Any") -> None:
dependencies = []

kwargs["dependencies"] = [
*dependencies,
fastapi.Depends(_sentry_fastapi_dependency),
*dependencies,
]

old_fastapi_init(self, *args, **kwargs)
Expand Down Expand Up @@ -123,4 +184,3 @@ def _set_transaction_name_and_source(
source = SOURCE_FOR_STYLE[transaction_style]

scope.set_transaction_name(name, source=source)