diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index 846fc0a7b6..8aad751470 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -43,10 +43,7 @@ from typing import Dict from typing import Optional from typing import Sequence - from typing import Type - from typing import Union - from sentry_sdk.integrations import Integration from sentry_sdk.scope import Scope from sentry_sdk._types import Event, Hint from sentry_sdk.session import Session @@ -656,22 +653,6 @@ def capture_session( else: self.session_flusher.add_session(session) - def get_integration( - self, name_or_class # type: Union[str, Type[Integration]] - ): - # type: (...) -> Any - """Returns the integration for this client by name or class. - If the client does not have that integration then `None` is returned. - """ - if isinstance(name_or_class, str): - integration_name = name_or_class - elif name_or_class.identifier is not None: - integration_name = name_or_class.identifier - else: - raise ValueError("Integration has no name") - - return self.integrations.get(integration_name) - def close( self, timeout=None, # type: Optional[float] diff --git a/sentry_sdk/hub.py b/sentry_sdk/hub.py index 032ccd09e7..2525dc56f1 100644 --- a/sentry_sdk/hub.py +++ b/sentry_sdk/hub.py @@ -3,7 +3,7 @@ from contextlib import contextmanager -from sentry_sdk._compat import with_metaclass +from sentry_sdk._compat import datetime_utcnow, with_metaclass from sentry_sdk.consts import INSTRUMENTER from sentry_sdk.scope import Scope from sentry_sdk.client import Client @@ -15,6 +15,7 @@ BAGGAGE_HEADER_NAME, SENTRY_TRACE_HEADER_NAME, ) +from sentry_sdk.session import Session from sentry_sdk.tracing_utils import ( has_tracing_enabled, normalize_incoming_data, @@ -293,9 +294,18 @@ def get_integration( If the return value is not `None` the hub is guaranteed to have a client attached. """ + if isinstance(name_or_class, str): + integration_name = name_or_class + elif name_or_class.identifier is not None: + integration_name = name_or_class.identifier + else: + raise ValueError("Integration has no name") + client = self.client if client is not None: - return client.get_integration(name_or_class) + rv = client.integrations.get(integration_name) + if rv is not None: + return rv @property def client(self): @@ -420,9 +430,31 @@ def add_breadcrumb(self, crumb=None, hint=None, **kwargs): logger.info("Dropped breadcrumb because no client bound") return - kwargs["client"] = client + crumb = dict(crumb or ()) # type: Breadcrumb + crumb.update(kwargs) + if not crumb: + return + + hint = dict(hint or ()) # type: Hint + + if crumb.get("timestamp") is None: + crumb["timestamp"] = datetime_utcnow() + if crumb.get("type") is None: + crumb["type"] = "default" + + if client.options["before_breadcrumb"] is not None: + new_crumb = client.options["before_breadcrumb"](crumb, hint) + else: + new_crumb = crumb + + if new_crumb is not None: + scope._breadcrumbs.append(new_crumb) + else: + logger.info("before breadcrumb dropped breadcrumb (%s)", crumb) - scope.add_breadcrumb(crumb, hint, **kwargs) + max_breadcrumbs = client.options["max_breadcrumbs"] # type: int + while len(scope._breadcrumbs) > max_breadcrumbs: + scope._breadcrumbs.popleft() def start_span(self, span=None, instrumenter=INSTRUMENTER.SENTRY, **kwargs): # type: (Optional[Span], str, Any) -> Span @@ -680,9 +712,12 @@ def start_session( ): # type: (...) -> None """Starts a new session.""" + self.end_session() client, scope = self._stack[-1] - scope.start_session( - client=client, + scope._session = Session( + release=client.options["release"] if client else None, + environment=client.options["environment"] if client else None, + user=scope._user, session_mode=session_mode, ) @@ -690,7 +725,13 @@ def end_session(self): # type: (...) -> None """Ends the current session if there is one.""" client, scope = self._stack[-1] - scope.end_session(client=client) + session = scope._session + self.scope._session = None + + if session is not None: + session.close() + if client is not None: + client.capture_session(session) def stop_auto_session_tracking(self): # type: (...) -> None @@ -699,8 +740,9 @@ def stop_auto_session_tracking(self): This temporarily session tracking for the current scope when called. To resume session tracking call `resume_auto_session_tracking`. """ + self.end_session() client, scope = self._stack[-1] - scope.stop_auto_session_tracking(client=client) + scope._force_auto_session_tracking = False def resume_auto_session_tracking(self): # type: (...) -> None @@ -708,8 +750,8 @@ def resume_auto_session_tracking(self): disabled earlier. This requires that generally automatic session tracking is enabled. """ - scope = self._stack[-1][1] - scope.resume_auto_session_tracking() + client, scope = self._stack[-1] + scope._force_auto_session_tracking = None def flush( self, diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index 8e9724b4c5..5096eccce0 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -5,10 +5,7 @@ import uuid from sentry_sdk.attachments import Attachment -from sentry_sdk._compat import datetime_utcnow -from sentry_sdk.consts import FALSE_VALUES from sentry_sdk._functools import wraps -from sentry_sdk.session import Session from sentry_sdk.tracing_utils import ( Baggage, extract_sentrytrace_data, @@ -23,6 +20,9 @@ from sentry_sdk._types import TYPE_CHECKING from sentry_sdk.utils import logger, capture_internal_exceptions +from sentry_sdk.consts import FALSE_VALUES + + if TYPE_CHECKING: from typing import Any from typing import Dict @@ -36,7 +36,6 @@ from sentry_sdk._types import ( Breadcrumb, - BreadcrumbHint, Event, EventProcessor, ErrorProcessor, @@ -47,6 +46,7 @@ from sentry_sdk.profiler import Profile from sentry_sdk.tracing import Span + from sentry_sdk.session import Session F = TypeVar("F", bound=Callable[..., Any]) T = TypeVar("T") @@ -517,97 +517,6 @@ def add_attachment( ) ) - def add_breadcrumb(self, crumb=None, hint=None, **kwargs): - # type: (Optional[Breadcrumb], Optional[BreadcrumbHint], Any) -> None - """ - Adds a breadcrumb. - - :param crumb: Dictionary with the data as the sentry v7/v8 protocol expects. - - :param hint: An optional value that can be used by `before_breadcrumb` - to customize the breadcrumbs that are emitted. - """ - client = kwargs.pop("client", None) - if client is None: - return - - before_breadcrumb = client.options.get("before_breadcrumb") - max_breadcrumbs = client.options.get("max_breadcrumbs") - - crumb = dict(crumb or ()) # type: Breadcrumb - crumb.update(kwargs) - if not crumb: - return - - hint = dict(hint or ()) # type: Hint - - if crumb.get("timestamp") is None: - crumb["timestamp"] = datetime_utcnow() - if crumb.get("type") is None: - crumb["type"] = "default" - - if before_breadcrumb is not None: - new_crumb = before_breadcrumb(crumb, hint) - else: - new_crumb = crumb - - if new_crumb is not None: - self._breadcrumbs.append(new_crumb) - else: - logger.info("before breadcrumb dropped breadcrumb (%s)", crumb) - - while len(self._breadcrumbs) > max_breadcrumbs: - self._breadcrumbs.popleft() - - def start_session(self, *args, **kwargs): - # type: (*Any, **Any) -> None - """Starts a new session.""" - client = kwargs.pop("client", None) - session_mode = kwargs.pop("session_mode", "application") - - self.end_session(client=client) - - self._session = Session( - release=client.options["release"] if client else None, - environment=client.options["environment"] if client else None, - user=self._user, - session_mode=session_mode, - ) - - def end_session(self, *args, **kwargs): - # type: (*Any, **Any) -> None - """Ends the current session if there is one.""" - client = kwargs.pop("client", None) - - session = self._session - self._session = None - - if session is not None: - session.close() - if client is not None: - client.capture_session(session) - - def stop_auto_session_tracking(self, *args, **kwargs): - # type: (*Any, **Any) -> None - """Stops automatic session tracking. - - This temporarily session tracking for the current scope when called. - To resume session tracking call `resume_auto_session_tracking`. - """ - client = kwargs.pop("client", None) - - self.end_session(client=client) - - self._force_auto_session_tracking = False - - def resume_auto_session_tracking(self): - # type: (...) -> None - """Resumes automatic session tracking for the current scope if - disabled earlier. This requires that generally automatic session - tracking is enabled. - """ - self._force_auto_session_tracking = None - def add_event_processor( self, func # type: EventProcessor ):