Skip to content

Commit 79e15f5

Browse files
authored
(2) Move capture_* from Hub to Client (#2555)
Moved some functionality from Hub to Client: - Capture Event: - moved `capture_event` from Hub to Client - created new `capture_event` in Scope that calls `capture_event` in Client - made `capture_event` in Hub call the new `capture_event` in Scope - Capture Exception: - created new `capture_exception` in Scope - made `capture_exception` in Hub call the new one in Scope - Capture Message: - created new `capture_message` in Scope - made `capture_message` in Hub call the new one in Scope - renamed `**scope_args` to `**scope_kwargs` because it contains keyword arguments. - moved `_update_scope` from Hub to Scope and renamed it to `_merge_scopes` This is preparation work for refactoring how we deal with Hubs and Scopes in the future. Its properly easier to reason about this change when checking out the branch than looking at the diff.
1 parent eff8f78 commit 79e15f5

File tree

6 files changed

+238
-82
lines changed

6 files changed

+238
-82
lines changed

docs/apidocs.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ API Docs
1111
.. autoclass:: sentry_sdk.Client
1212
:members:
1313

14+
.. autoclass:: sentry_sdk.client._Client
15+
:members:
16+
1417
.. autoclass:: sentry_sdk.Transport
1518
:members:
1619

sentry_sdk/api.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,31 +82,31 @@ def capture_event(
8282
event, # type: Event
8383
hint=None, # type: Optional[Hint]
8484
scope=None, # type: Optional[Any]
85-
**scope_args # type: Any
85+
**scope_kwargs # type: Any
8686
):
8787
# type: (...) -> Optional[str]
88-
return Hub.current.capture_event(event, hint, scope=scope, **scope_args)
88+
return Hub.current.capture_event(event, hint, scope=scope, **scope_kwargs)
8989

9090

9191
@hubmethod
9292
def capture_message(
9393
message, # type: str
9494
level=None, # type: Optional[str]
9595
scope=None, # type: Optional[Any]
96-
**scope_args # type: Any
96+
**scope_kwargs # type: Any
9797
):
9898
# type: (...) -> Optional[str]
99-
return Hub.current.capture_message(message, level, scope=scope, **scope_args)
99+
return Hub.current.capture_message(message, level, scope=scope, **scope_kwargs)
100100

101101

102102
@hubmethod
103103
def capture_exception(
104104
error=None, # type: Optional[Union[BaseException, ExcInfo]]
105105
scope=None, # type: Optional[Any]
106-
**scope_args # type: Any
106+
**scope_kwargs # type: Any
107107
):
108108
# type: (...) -> Optional[str]
109-
return Hub.current.capture_exception(error, scope=scope, **scope_args)
109+
return Hub.current.capture_exception(error, scope=scope, **scope_kwargs)
110110

111111

112112
@hubmethod

sentry_sdk/client.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ class _Client(object):
156156
forwarding them to sentry through the configured transport. It takes
157157
the client options as keyword arguments and optionally the DSN as first
158158
argument.
159+
160+
Alias of :py:class:`Client`. (Was created for better intelisense support)
159161
"""
160162

161163
def __init__(self, *args, **kwargs):
@@ -560,8 +562,8 @@ def capture_event(
560562
561563
:param hint: Contains metadata about the event that can be read from `before_send`, such as the original exception object or a HTTP request object.
562564
563-
:param scope: An optional scope to use for determining whether this event
564-
should be captured.
565+
:param scope: An optional :py:class:`sentry_sdk.Scope` to apply to events.
566+
The `scope` and `scope_kwargs` parameters are mutually exclusive.
565567
566568
:returns: An event ID. May be `None` if there is no DSN set or of if the SDK decided to discard the event for other reasons. In such situations setting `debug=True` on `init()` may help.
567569
"""

sentry_sdk/hub.py

Lines changed: 63 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
)
2222

2323
from sentry_sdk.utils import (
24-
exc_info_from_error,
25-
event_from_exception,
2624
logger,
2725
ContextVar,
2826
)
@@ -65,24 +63,6 @@ def overload(x):
6563
_local = ContextVar("sentry_current_hub")
6664

6765

68-
def _update_scope(base, scope_change, scope_kwargs):
69-
# type: (Scope, Optional[Any], Dict[str, Any]) -> Scope
70-
if scope_change and scope_kwargs:
71-
raise TypeError("cannot provide scope and kwargs")
72-
if scope_change is not None:
73-
final_scope = copy.copy(base)
74-
if callable(scope_change):
75-
scope_change(final_scope)
76-
else:
77-
final_scope.update_from_scope(scope_change)
78-
elif scope_kwargs:
79-
final_scope = copy.copy(base)
80-
final_scope.update_from_kwargs(**scope_kwargs)
81-
else:
82-
final_scope = base
83-
return final_scope
84-
85-
8666
def _should_send_default_pii():
8767
# type: () -> bool
8868
client = Hub.current.client
@@ -322,76 +302,100 @@ def bind_client(
322302
top = self._stack[-1]
323303
self._stack[-1] = (new, top[1])
324304

325-
def capture_event(self, event, hint=None, scope=None, **scope_args):
305+
def capture_event(self, event, hint=None, scope=None, **scope_kwargs):
326306
# type: (Event, Optional[Hint], Optional[Scope], Any) -> Optional[str]
327307
"""
328308
Captures an event.
329309
330-
Alias of :py:meth:`sentry_sdk.Client.capture_event`.
310+
Alias of :py:meth:`sentry_sdk.Scope.capture_event`.
311+
312+
:param event: A ready-made event that can be directly sent to Sentry.
331313
332-
:param scope_args: For supported `**scope_args` see
333-
:py:meth:`sentry_sdk.Scope.update_from_kwargs`.
314+
:param hint: Contains metadata about the event that can be read from `before_send`, such as the original exception object or a HTTP request object.
315+
316+
:param scope: An optional :py:class:`sentry_sdk.Scope` to apply to events.
317+
The `scope` and `scope_kwargs` parameters are mutually exclusive.
318+
319+
:param scope_kwargs: Optional data to apply to event.
320+
For supported `**scope_kwargs` see :py:meth:`sentry_sdk.Scope.update_from_kwargs`.
321+
The `scope` and `scope_kwargs` parameters are mutually exclusive.
334322
"""
335323
client, top_scope = self._stack[-1]
336-
scope = _update_scope(top_scope, scope, scope_args)
337-
if client is not None:
338-
is_transaction = event.get("type") == "transaction"
339-
rv = client.capture_event(event, hint, scope)
340-
if rv is not None and not is_transaction:
341-
self._last_event_id = rv
342-
return rv
343-
return None
324+
if client is None:
325+
return None
326+
327+
last_event_id = top_scope.capture_event(
328+
event, hint, client=client, scope=scope, **scope_kwargs
329+
)
344330

345-
def capture_message(self, message, level=None, scope=None, **scope_args):
331+
is_transaction = event.get("type") == "transaction"
332+
if last_event_id is not None and not is_transaction:
333+
self._last_event_id = last_event_id
334+
335+
return last_event_id
336+
337+
def capture_message(self, message, level=None, scope=None, **scope_kwargs):
346338
# type: (str, Optional[str], Optional[Scope], Any) -> Optional[str]
347339
"""
348340
Captures a message.
349341
350-
:param message: The string to send as the message.
342+
Alias of :py:meth:`sentry_sdk.Scope.capture_message`.
343+
344+
:param message: The string to send as the message to Sentry.
351345
352346
:param level: If no level is provided, the default level is `info`.
353347
354-
:param scope: An optional :py:class:`sentry_sdk.Scope` to use.
348+
:param scope: An optional :py:class:`sentry_sdk.Scope` to apply to events.
349+
The `scope` and `scope_kwargs` parameters are mutually exclusive.
355350
356-
:param scope_args: For supported `**scope_args` see
357-
:py:meth:`sentry_sdk.Scope.update_from_kwargs`.
351+
:param scope_kwargs: Optional data to apply to event.
352+
For supported `**scope_kwargs` see :py:meth:`sentry_sdk.Scope.update_from_kwargs`.
353+
The `scope` and `scope_kwargs` parameters are mutually exclusive.
358354
359355
:returns: An `event_id` if the SDK decided to send the event (see :py:meth:`sentry_sdk.Client.capture_event`).
360356
"""
361-
if self.client is None:
357+
client, top_scope = self._stack[-1]
358+
if client is None:
362359
return None
363-
if level is None:
364-
level = "info"
365-
return self.capture_event(
366-
{"message": message, "level": level}, scope=scope, **scope_args
360+
361+
last_event_id = top_scope.capture_message(
362+
message, level=level, client=client, scope=scope, **scope_kwargs
367363
)
368364

369-
def capture_exception(self, error=None, scope=None, **scope_args):
365+
if last_event_id is not None:
366+
self._last_event_id = last_event_id
367+
368+
return last_event_id
369+
370+
def capture_exception(self, error=None, scope=None, **scope_kwargs):
370371
# type: (Optional[Union[BaseException, ExcInfo]], Optional[Scope], Any) -> Optional[str]
371372
"""Captures an exception.
372373
373-
:param error: An exception to catch. If `None`, `sys.exc_info()` will be used.
374+
Alias of :py:meth:`sentry_sdk.Scope.capture_exception`.
375+
376+
:param error: An exception to capture. If `None`, `sys.exc_info()` will be used.
377+
378+
:param scope: An optional :py:class:`sentry_sdk.Scope` to apply to events.
379+
The `scope` and `scope_kwargs` parameters are mutually exclusive.
374380
375-
:param scope_args: For supported `**scope_args` see
376-
:py:meth:`sentry_sdk.Scope.update_from_kwargs`.
381+
:param scope_kwargs: Optional data to apply to event.
382+
For supported `**scope_kwargs` see :py:meth:`sentry_sdk.Scope.update_from_kwargs`.
383+
The `scope` and `scope_kwargs` parameters are mutually exclusive.
377384
378385
:returns: An `event_id` if the SDK decided to send the event (see :py:meth:`sentry_sdk.Client.capture_event`).
379386
"""
380-
client = self.client
387+
client, top_scope = self._stack[-1]
381388
if client is None:
382389
return None
383-
if error is not None:
384-
exc_info = exc_info_from_error(error)
385-
else:
386-
exc_info = sys.exc_info()
387390

388-
event, hint = event_from_exception(exc_info, client_options=client.options)
389-
try:
390-
return self.capture_event(event, hint=hint, scope=scope, **scope_args)
391-
except Exception:
392-
self._capture_internal_exception(sys.exc_info())
391+
last_event_id = top_scope.capture_exception(
392+
error, client=client, scope=scope, **scope_kwargs
393+
)
393394

394-
return None
395+
if last_event_id is not None:
396+
self._last_event_id = last_event_id
397+
398+
return last_event_id
395399

396400
def _capture_internal_exception(
397401
self, exc_info # type: Any
@@ -401,6 +405,8 @@ def _capture_internal_exception(
401405
Capture an exception that is likely caused by a bug in the SDK
402406
itself.
403407
408+
Duplicated in :py:meth:`sentry_sdk.Client._capture_internal_exception`.
409+
404410
These exceptions do not end up in Sentry and are just logged instead.
405411
"""
406412
logger.error("Internal error in sentry_sdk", exc_info=exc_info)

0 commit comments

Comments
 (0)