Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a163f83
Do not set and then overwrite middlewares __call__
sentrivana Aug 5, 2025
6aec4fb
Remove logging from asgi
sentrivana Aug 6, 2025
a454b21
Merge branch 'master' into ivana/random-perf-improvements
sentrivana Aug 6, 2025
8278cf3
format
sentrivana Aug 6, 2025
f63d40c
Cache is_gevent
sentrivana Aug 6, 2025
78368b3
Cache _looks_like_asgi3
sentrivana Aug 6, 2025
155e9aa
Do not guess ASGI version in Quart integration
sentrivana Aug 6, 2025
0e37a51
Use asgi_version in Starlite, Litestar too
sentrivana Aug 7, 2025
9f0c233
mypy fixes
sentrivana Aug 7, 2025
f4d06af
feat(tracing): Improve `@trace` decorator. (#4648)
antonpirker Aug 7, 2025
0926981
.copy() instead of copy()
sentrivana Aug 8, 2025
5d62424
ref(clickhouse): List `send_data` parameters (#4667)
szokeasaurusrex Aug 7, 2025
fac580d
fix(clickhouse): Don't eat the generator data (#4669)
szokeasaurusrex Aug 7, 2025
66f47ec
feat(anthropic) Update span attributes to use `gen_ai.*` namespace in…
constantinius Aug 8, 2025
dd323d6
Help for debugging Cron problems (#4686)
antonpirker Aug 11, 2025
c9230c5
Make UUID generation lazy
sl0thentr0py Mar 15, 2024
b7768c5
Merge branch 'master' into ivana/random-perf-improvements
sentrivana Aug 12, 2025
f8962cc
Merge branch 'master' into ivana/random-perf-improvements
sentrivana Aug 12, 2025
3f9c41b
Merge branch 'master' into ivana/random-perf-improvements
sentrivana Aug 12, 2025
e297728
fix mypy
sentrivana Aug 12, 2025
f344c2d
do not cache looks_like_asgi3
sentrivana Aug 12, 2025
f1a67a2
remove gevent cache too
sentrivana Aug 12, 2025
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
36 changes: 11 additions & 25 deletions sentry_sdk/integrations/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import sentry_sdk
from sentry_sdk.api import continue_trace
from sentry_sdk.consts import OP

from sentry_sdk.integrations._asgi_common import (
_get_headers,
_get_request_data,
Expand Down Expand Up @@ -42,7 +41,6 @@

if TYPE_CHECKING:
from typing import Any
from typing import Callable
from typing import Dict
from typing import Optional
from typing import Tuple
Expand Down Expand Up @@ -102,6 +100,7 @@ def __init__(
mechanism_type="asgi", # type: str
span_origin="manual", # type: str
http_methods_to_capture=DEFAULT_HTTP_METHODS_TO_CAPTURE, # type: Tuple[str, ...]
asgi_version=None, # type: Optional[int]
):
# type: (...) -> None
"""
Expand Down Expand Up @@ -140,10 +139,16 @@ def __init__(
self.app = app
self.http_methods_to_capture = http_methods_to_capture

if _looks_like_asgi3(app):
self.__call__ = self._run_asgi3 # type: Callable[..., Any]
else:
self.__call__ = self._run_asgi2
if asgi_version is None:
if _looks_like_asgi3(app):
asgi_version = 3
else:
asgi_version = 2

if asgi_version == 3:
self.__call__ = self._run_asgi3
elif asgi_version == 2:
self.__call__ = self._run_asgi2 # type: ignore

def _capture_lifespan_exception(self, exc):
# type: (Exception) -> None
Expand Down Expand Up @@ -217,28 +222,16 @@ async def _run_app(self, scope, receive, send, asgi_version):
source=transaction_source,
origin=self.span_origin,
)
logger.debug(
"[ASGI] Created transaction (continuing trace): %s",
transaction,
)
else:
transaction = Transaction(
op=OP.HTTP_SERVER,
name=transaction_name,
source=transaction_source,
origin=self.span_origin,
)
logger.debug(
"[ASGI] Created transaction (new): %s", transaction
)

if transaction:
transaction.set_tag("asgi.type", ty)
logger.debug(
"[ASGI] Set transaction name and source on transaction: '%s' / '%s'",
transaction.name,
transaction.source,
)

with (
sentry_sdk.start_transaction(
Expand All @@ -248,7 +241,6 @@ async def _run_app(self, scope, receive, send, asgi_version):
if transaction is not None
else nullcontext()
):
logger.debug("[ASGI] Started transaction: %s", transaction)
try:

async def _sentry_wrapped_send(event):
Expand Down Expand Up @@ -303,12 +295,6 @@ def event_processor(self, event, hint, asgi_scope):
event["transaction"] = name
event["transaction_info"] = {"source": source}

logger.debug(
"[ASGI] Set transaction name and source in event_processor: '%s' / '%s'",
event["transaction"],
event["transaction_info"]["source"],
)

return event

# Helper functions.
Expand Down
2 changes: 1 addition & 1 deletion sentry_sdk/integrations/django/asgi.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ async def sentry_patched_asgi_handler(self, receive, send):
http_methods_to_capture=integration.http_methods_to_capture,
)

return await middleware(self.scope)(receive, send)
return await middleware(self.scope)(receive, send) # type: ignore

cls.__call__ = sentry_patched_asgi_handler

Expand Down
8 changes: 1 addition & 7 deletions sentry_sdk/integrations/fastapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
from sentry_sdk.integrations import DidNotEnable
from sentry_sdk.scope import should_send_default_pii
from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource
from sentry_sdk.utils import (
transaction_from_function,
logger,
)
from sentry_sdk.utils import transaction_from_function

from typing import TYPE_CHECKING

Expand Down Expand Up @@ -66,9 +63,6 @@ def _set_transaction_name_and_source(scope, transaction_style, request):
source = SOURCE_FOR_STYLE[transaction_style]

scope.set_transaction_name(name, source=source)
logger.debug(
"[FastAPI] Set transaction name and source on scope: %s / %s", name, source
)


def patch_get_request_handler():
Expand Down
2 changes: 1 addition & 1 deletion sentry_sdk/integrations/litestar.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def __init__(self, app, span_origin=LitestarIntegration.origin):
transaction_style="endpoint",
mechanism_type="asgi",
span_origin=span_origin,
asgi_version=3,
)

def _capture_request_exception(self, exc):
Expand Down Expand Up @@ -116,7 +117,6 @@ def injection_wrapper(self, *args, **kwargs):
*(kwargs.get("after_exception") or []),
]

SentryLitestarASGIMiddleware.__call__ = SentryLitestarASGIMiddleware._run_asgi3 # type: ignore
middleware = kwargs.get("middleware") or []
kwargs["middleware"] = [SentryLitestarASGIMiddleware, *middleware]
old__init__(self, *args, **kwargs)
Expand Down
2 changes: 1 addition & 1 deletion sentry_sdk/integrations/quart.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ async def sentry_patched_asgi_app(self, scope, receive, send):
middleware = SentryAsgiMiddleware(
lambda *a, **kw: old_app(self, *a, **kw),
span_origin=QuartIntegration.origin,
asgi_version=3,
)
middleware.__call__ = middleware._run_asgi3
return await middleware(scope, receive, send)

Quart.__call__ = sentry_patched_asgi_app
Expand Down
6 changes: 1 addition & 5 deletions sentry_sdk/integrations/starlette.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
capture_internal_exceptions,
ensure_integration_enabled,
event_from_exception,
logger,
parse_version,
transaction_from_function,
)
Expand Down Expand Up @@ -403,9 +402,9 @@ async def _sentry_patched_asgi_app(self, scope, receive, send):
if integration
else DEFAULT_HTTP_METHODS_TO_CAPTURE
),
asgi_version=3,
)

middleware.__call__ = middleware._run_asgi3
return await middleware(scope, receive, send)

Starlette.__call__ = _sentry_patched_asgi_app
Expand Down Expand Up @@ -723,9 +722,6 @@ def _set_transaction_name_and_source(scope, transaction_style, request):
source = TransactionSource.ROUTE

scope.set_transaction_name(name, source=source)
logger.debug(
"[Starlette] Set transaction name and source on scope: %s / %s", name, source
)


def _get_transaction_from_middleware(app, asgi_scope, integration):
Expand Down
2 changes: 1 addition & 1 deletion sentry_sdk/integrations/starlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def __init__(self, app, span_origin=StarliteIntegration.origin):
transaction_style="endpoint",
mechanism_type="asgi",
span_origin=span_origin,
asgi_version=3,
)


Expand Down Expand Up @@ -94,7 +95,6 @@ def injection_wrapper(self, *args, **kwargs):
]
)

SentryStarliteASGIMiddleware.__call__ = SentryStarliteASGIMiddleware._run_asgi3 # type: ignore
middleware = kwargs.get("middleware") or []
kwargs["middleware"] = [SentryStarliteASGIMiddleware, *middleware]
old__init__(self, *args, **kwargs)
Expand Down
22 changes: 11 additions & 11 deletions sentry_sdk/scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from collections.abc import Mapping, MutableMapping
from collections.abc import Mapping

from typing import Any
from typing import Callable
Expand Down Expand Up @@ -238,24 +238,24 @@ def __copy__(self):
rv._name = self._name
rv._fingerprint = self._fingerprint
rv._transaction = self._transaction
rv._transaction_info = dict(self._transaction_info)
rv._transaction_info = self._transaction_info.copy()
rv._user = self._user

rv._tags = dict(self._tags)
rv._contexts = dict(self._contexts)
rv._extras = dict(self._extras)
rv._tags = self._tags.copy()
rv._contexts = self._contexts.copy()
rv._extras = self._extras.copy()

rv._breadcrumbs = copy(self._breadcrumbs)
rv._n_breadcrumbs_truncated = copy(self._n_breadcrumbs_truncated)
rv._event_processors = list(self._event_processors)
rv._error_processors = list(self._error_processors)
rv._n_breadcrumbs_truncated = self._n_breadcrumbs_truncated
rv._event_processors = self._event_processors.copy()
rv._error_processors = self._error_processors.copy()
rv._propagation_context = self._propagation_context

rv._should_capture = self._should_capture
rv._span = self._span
rv._session = self._session
rv._force_auto_session_tracking = self._force_auto_session_tracking
rv._attachments = list(self._attachments)
rv._attachments = self._attachments.copy()

rv._profile = self._profile

Expand Down Expand Up @@ -683,12 +683,12 @@ def clear(self):
self._level = None # type: Optional[LogLevelStr]
self._fingerprint = None # type: Optional[List[str]]
self._transaction = None # type: Optional[str]
self._transaction_info = {} # type: MutableMapping[str, str]
self._transaction_info = {} # type: dict[str, str]
self._user = None # type: Optional[Dict[str, Any]]

self._tags = {} # type: Dict[str, Any]
self._contexts = {} # type: Dict[str, Dict[str, Any]]
self._extras = {} # type: MutableMapping[str, Any]
self._extras = {} # type: dict[str, Any]
self._attachments = [] # type: List[Attachment]

self.clear_breadcrumbs()
Expand Down
35 changes: 30 additions & 5 deletions sentry_sdk/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ class Span:
"""

__slots__ = (
"trace_id",
"span_id",
"_trace_id",
"_span_id",
"parent_span_id",
"same_process_as_parent",
"sampled",
Expand Down Expand Up @@ -301,8 +301,8 @@ def __init__(
name=None, # type: Optional[str]
):
# type: (...) -> None
self.trace_id = trace_id or uuid.uuid4().hex
self.span_id = span_id or uuid.uuid4().hex[16:]
self._trace_id = trace_id
self._span_id = span_id
self.parent_span_id = parent_span_id
self.same_process_as_parent = same_process_as_parent
self.sampled = sampled
Expand Down Expand Up @@ -356,6 +356,32 @@ def init_span_recorder(self, maxlen):
if self._span_recorder is None:
self._span_recorder = _SpanRecorder(maxlen)

@property
def trace_id(self):
# type: () -> str
if not self._trace_id:
self._trace_id = uuid.uuid4().hex

return self._trace_id

@trace_id.setter
def trace_id(self, value):
# type: (str) -> None
self._trace_id = value

@property
def span_id(self):
# type: () -> str
if not self._span_id:
self._span_id = uuid.uuid4().hex[16:]

return self._span_id

@span_id.setter
def span_id(self, value):
# type: (str) -> None
self._span_id = value

def _get_local_aggregator(self):
# type: (...) -> LocalAggregator
rv = self._local_aggregator
Expand Down Expand Up @@ -822,7 +848,6 @@ def __init__( # type: ignore[misc]
**kwargs, # type: Unpack[SpanKwargs]
):
# type: (...) -> None

super().__init__(**kwargs)

self.name = name
Expand Down