Skip to content

Commit 354d7bb

Browse files
authored
Move add_breadcrumb and session function from Hub to Scope (#2544)
Moved some functionality from Hub to Scope or Client: - moved add_breadcrumb from Hub to Scope - moved session functions from Hub to Scope - moved get_integration1 from Hub to Client. This is preparation work for refactoring how we deal with Hubs and Scopes in the future.
1 parent 67c963d commit 354d7bb

File tree

3 files changed

+124
-56
lines changed

3 files changed

+124
-56
lines changed

sentry_sdk/client.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@
4343
from typing import Dict
4444
from typing import Optional
4545
from typing import Sequence
46+
from typing import Type
47+
from typing import Union
4648

49+
from sentry_sdk.integrations import Integration
4750
from sentry_sdk.scope import Scope
4851
from sentry_sdk._types import Event, Hint
4952
from sentry_sdk.session import Session
@@ -653,6 +656,22 @@ def capture_session(
653656
else:
654657
self.session_flusher.add_session(session)
655658

659+
def get_integration(
660+
self, name_or_class # type: Union[str, Type[Integration]]
661+
):
662+
# type: (...) -> Any
663+
"""Returns the integration for this client by name or class.
664+
If the client does not have that integration then `None` is returned.
665+
"""
666+
if isinstance(name_or_class, str):
667+
integration_name = name_or_class
668+
elif name_or_class.identifier is not None:
669+
integration_name = name_or_class.identifier
670+
else:
671+
raise ValueError("Integration has no name")
672+
673+
return self.integrations.get(integration_name)
674+
656675
def close(
657676
self,
658677
timeout=None, # type: Optional[float]

sentry_sdk/hub.py

Lines changed: 10 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from contextlib import contextmanager
55

6-
from sentry_sdk._compat import datetime_utcnow, with_metaclass
6+
from sentry_sdk._compat import with_metaclass
77
from sentry_sdk.consts import INSTRUMENTER
88
from sentry_sdk.scope import Scope
99
from sentry_sdk.client import Client
@@ -15,7 +15,6 @@
1515
BAGGAGE_HEADER_NAME,
1616
SENTRY_TRACE_HEADER_NAME,
1717
)
18-
from sentry_sdk.session import Session
1918
from sentry_sdk.tracing_utils import (
2019
has_tracing_enabled,
2120
normalize_incoming_data,
@@ -294,18 +293,9 @@ def get_integration(
294293
If the return value is not `None` the hub is guaranteed to have a
295294
client attached.
296295
"""
297-
if isinstance(name_or_class, str):
298-
integration_name = name_or_class
299-
elif name_or_class.identifier is not None:
300-
integration_name = name_or_class.identifier
301-
else:
302-
raise ValueError("Integration has no name")
303-
304296
client = self.client
305297
if client is not None:
306-
rv = client.integrations.get(integration_name)
307-
if rv is not None:
308-
return rv
298+
return client.get_integration(name_or_class)
309299

310300
@property
311301
def client(self):
@@ -430,31 +420,9 @@ def add_breadcrumb(self, crumb=None, hint=None, **kwargs):
430420
logger.info("Dropped breadcrumb because no client bound")
431421
return
432422

433-
crumb = dict(crumb or ()) # type: Breadcrumb
434-
crumb.update(kwargs)
435-
if not crumb:
436-
return
437-
438-
hint = dict(hint or ()) # type: Hint
439-
440-
if crumb.get("timestamp") is None:
441-
crumb["timestamp"] = datetime_utcnow()
442-
if crumb.get("type") is None:
443-
crumb["type"] = "default"
444-
445-
if client.options["before_breadcrumb"] is not None:
446-
new_crumb = client.options["before_breadcrumb"](crumb, hint)
447-
else:
448-
new_crumb = crumb
449-
450-
if new_crumb is not None:
451-
scope._breadcrumbs.append(new_crumb)
452-
else:
453-
logger.info("before breadcrumb dropped breadcrumb (%s)", crumb)
423+
kwargs["client"] = client
454424

455-
max_breadcrumbs = client.options["max_breadcrumbs"] # type: int
456-
while len(scope._breadcrumbs) > max_breadcrumbs:
457-
scope._breadcrumbs.popleft()
425+
scope.add_breadcrumb(crumb, hint, **kwargs)
458426

459427
def start_span(self, span=None, instrumenter=INSTRUMENTER.SENTRY, **kwargs):
460428
# type: (Optional[Span], str, Any) -> Span
@@ -712,26 +680,17 @@ def start_session(
712680
):
713681
# type: (...) -> None
714682
"""Starts a new session."""
715-
self.end_session()
716683
client, scope = self._stack[-1]
717-
scope._session = Session(
718-
release=client.options["release"] if client else None,
719-
environment=client.options["environment"] if client else None,
720-
user=scope._user,
684+
scope.start_session(
685+
client=client,
721686
session_mode=session_mode,
722687
)
723688

724689
def end_session(self):
725690
# type: (...) -> None
726691
"""Ends the current session if there is one."""
727692
client, scope = self._stack[-1]
728-
session = scope._session
729-
self.scope._session = None
730-
731-
if session is not None:
732-
session.close()
733-
if client is not None:
734-
client.capture_session(session)
693+
scope.end_session(client=client)
735694

736695
def stop_auto_session_tracking(self):
737696
# type: (...) -> None
@@ -740,18 +699,17 @@ def stop_auto_session_tracking(self):
740699
This temporarily session tracking for the current scope when called.
741700
To resume session tracking call `resume_auto_session_tracking`.
742701
"""
743-
self.end_session()
744702
client, scope = self._stack[-1]
745-
scope._force_auto_session_tracking = False
703+
scope.stop_auto_session_tracking(client=client)
746704

747705
def resume_auto_session_tracking(self):
748706
# type: (...) -> None
749707
"""Resumes automatic session tracking for the current scope if
750708
disabled earlier. This requires that generally automatic session
751709
tracking is enabled.
752710
"""
753-
client, scope = self._stack[-1]
754-
scope._force_auto_session_tracking = None
711+
scope = self._stack[-1][1]
712+
scope.resume_auto_session_tracking()
755713

756714
def flush(
757715
self,

sentry_sdk/scope.py

Lines changed: 95 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
import uuid
66

77
from sentry_sdk.attachments import Attachment
8+
from sentry_sdk._compat import datetime_utcnow
9+
from sentry_sdk.consts import FALSE_VALUES
810
from sentry_sdk._functools import wraps
11+
from sentry_sdk.session import Session
912
from sentry_sdk.tracing_utils import (
1013
Baggage,
1114
extract_sentrytrace_data,
@@ -20,9 +23,6 @@
2023
from sentry_sdk._types import TYPE_CHECKING
2124
from sentry_sdk.utils import logger, capture_internal_exceptions
2225

23-
from sentry_sdk.consts import FALSE_VALUES
24-
25-
2626
if TYPE_CHECKING:
2727
from typing import Any
2828
from typing import Dict
@@ -36,6 +36,7 @@
3636

3737
from sentry_sdk._types import (
3838
Breadcrumb,
39+
BreadcrumbHint,
3940
Event,
4041
EventProcessor,
4142
ErrorProcessor,
@@ -46,7 +47,6 @@
4647

4748
from sentry_sdk.profiler import Profile
4849
from sentry_sdk.tracing import Span
49-
from sentry_sdk.session import Session
5050

5151
F = TypeVar("F", bound=Callable[..., Any])
5252
T = TypeVar("T")
@@ -517,6 +517,97 @@ def add_attachment(
517517
)
518518
)
519519

520+
def add_breadcrumb(self, crumb=None, hint=None, **kwargs):
521+
# type: (Optional[Breadcrumb], Optional[BreadcrumbHint], Any) -> None
522+
"""
523+
Adds a breadcrumb.
524+
525+
:param crumb: Dictionary with the data as the sentry v7/v8 protocol expects.
526+
527+
:param hint: An optional value that can be used by `before_breadcrumb`
528+
to customize the breadcrumbs that are emitted.
529+
"""
530+
client = kwargs.pop("client", None)
531+
if client is None:
532+
return
533+
534+
before_breadcrumb = client.options.get("before_breadcrumb")
535+
max_breadcrumbs = client.options.get("max_breadcrumbs")
536+
537+
crumb = dict(crumb or ()) # type: Breadcrumb
538+
crumb.update(kwargs)
539+
if not crumb:
540+
return
541+
542+
hint = dict(hint or ()) # type: Hint
543+
544+
if crumb.get("timestamp") is None:
545+
crumb["timestamp"] = datetime_utcnow()
546+
if crumb.get("type") is None:
547+
crumb["type"] = "default"
548+
549+
if before_breadcrumb is not None:
550+
new_crumb = before_breadcrumb(crumb, hint)
551+
else:
552+
new_crumb = crumb
553+
554+
if new_crumb is not None:
555+
self._breadcrumbs.append(new_crumb)
556+
else:
557+
logger.info("before breadcrumb dropped breadcrumb (%s)", crumb)
558+
559+
while len(self._breadcrumbs) > max_breadcrumbs:
560+
self._breadcrumbs.popleft()
561+
562+
def start_session(self, *args, **kwargs):
563+
# type: (*Any, **Any) -> None
564+
"""Starts a new session."""
565+
client = kwargs.pop("client", None)
566+
session_mode = kwargs.pop("session_mode", "application")
567+
568+
self.end_session(client=client)
569+
570+
self._session = Session(
571+
release=client.options["release"] if client else None,
572+
environment=client.options["environment"] if client else None,
573+
user=self._user,
574+
session_mode=session_mode,
575+
)
576+
577+
def end_session(self, *args, **kwargs):
578+
# type: (*Any, **Any) -> None
579+
"""Ends the current session if there is one."""
580+
client = kwargs.pop("client", None)
581+
582+
session = self._session
583+
self._session = None
584+
585+
if session is not None:
586+
session.close()
587+
if client is not None:
588+
client.capture_session(session)
589+
590+
def stop_auto_session_tracking(self, *args, **kwargs):
591+
# type: (*Any, **Any) -> None
592+
"""Stops automatic session tracking.
593+
594+
This temporarily session tracking for the current scope when called.
595+
To resume session tracking call `resume_auto_session_tracking`.
596+
"""
597+
client = kwargs.pop("client", None)
598+
599+
self.end_session(client=client)
600+
601+
self._force_auto_session_tracking = False
602+
603+
def resume_auto_session_tracking(self):
604+
# type: (...) -> None
605+
"""Resumes automatic session tracking for the current scope if
606+
disabled earlier. This requires that generally automatic session
607+
tracking is enabled.
608+
"""
609+
self._force_auto_session_tracking = None
610+
520611
def add_event_processor(
521612
self, func # type: EventProcessor
522613
):

0 commit comments

Comments
 (0)