diff options
Diffstat (limited to '.venv/lib/python3.12/site-packages/sentry_sdk/hub.py')
-rw-r--r-- | .venv/lib/python3.12/site-packages/sentry_sdk/hub.py | 739 |
1 files changed, 739 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/sentry_sdk/hub.py b/.venv/lib/python3.12/site-packages/sentry_sdk/hub.py new file mode 100644 index 00000000..7fda9202 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/sentry_sdk/hub.py @@ -0,0 +1,739 @@ +import warnings +from contextlib import contextmanager + +from sentry_sdk import ( + get_client, + get_global_scope, + get_isolation_scope, + get_current_scope, +) +from sentry_sdk._compat import with_metaclass +from sentry_sdk.consts import INSTRUMENTER +from sentry_sdk.scope import _ScopeManager +from sentry_sdk.client import Client +from sentry_sdk.tracing import ( + NoOpSpan, + Span, + Transaction, +) + +from sentry_sdk.utils import ( + logger, + ContextVar, +) + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from typing import Any + from typing import Callable + from typing import ContextManager + from typing import Dict + from typing import Generator + from typing import List + from typing import Optional + from typing import overload + from typing import Tuple + from typing import Type + from typing import TypeVar + from typing import Union + + from typing_extensions import Unpack + + from sentry_sdk.scope import Scope + from sentry_sdk.client import BaseClient + from sentry_sdk.integrations import Integration + from sentry_sdk._types import ( + Event, + Hint, + Breadcrumb, + BreadcrumbHint, + ExcInfo, + LogLevelStr, + SamplingContext, + ) + from sentry_sdk.tracing import TransactionKwargs + + T = TypeVar("T") + +else: + + def overload(x): + # type: (T) -> T + return x + + +class SentryHubDeprecationWarning(DeprecationWarning): + """ + A custom deprecation warning to inform users that the Hub is deprecated. + """ + + _MESSAGE = ( + "`sentry_sdk.Hub` is deprecated and will be removed in a future major release. " + "Please consult our 1.x to 2.x migration guide for details on how to migrate " + "`Hub` usage to the new API: " + "https://docs.sentry.io/platforms/python/migration/1.x-to-2.x" + ) + + def __init__(self, *_): + # type: (*object) -> None + super().__init__(self._MESSAGE) + + +@contextmanager +def _suppress_hub_deprecation_warning(): + # type: () -> Generator[None, None, None] + """Utility function to suppress deprecation warnings for the Hub.""" + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=SentryHubDeprecationWarning) + yield + + +_local = ContextVar("sentry_current_hub") + + +class HubMeta(type): + @property + def current(cls): + # type: () -> Hub + """Returns the current instance of the hub.""" + warnings.warn(SentryHubDeprecationWarning(), stacklevel=2) + rv = _local.get(None) + if rv is None: + with _suppress_hub_deprecation_warning(): + # This will raise a deprecation warning; suppress it since we already warned above. + rv = Hub(GLOBAL_HUB) + _local.set(rv) + return rv + + @property + def main(cls): + # type: () -> Hub + """Returns the main instance of the hub.""" + warnings.warn(SentryHubDeprecationWarning(), stacklevel=2) + return GLOBAL_HUB + + +class Hub(with_metaclass(HubMeta)): # type: ignore + """ + .. deprecated:: 2.0.0 + The Hub is deprecated. Its functionality will be merged into :py:class:`sentry_sdk.scope.Scope`. + + The hub wraps the concurrency management of the SDK. Each thread has + its own hub but the hub might transfer with the flow of execution if + context vars are available. + + If the hub is used with a with statement it's temporarily activated. + """ + + _stack = None # type: List[Tuple[Optional[Client], Scope]] + _scope = None # type: Optional[Scope] + + # Mypy doesn't pick up on the metaclass. + + if TYPE_CHECKING: + current = None # type: Hub + main = None # type: Hub + + def __init__( + self, + client_or_hub=None, # type: Optional[Union[Hub, Client]] + scope=None, # type: Optional[Any] + ): + # type: (...) -> None + warnings.warn(SentryHubDeprecationWarning(), stacklevel=2) + + current_scope = None + + if isinstance(client_or_hub, Hub): + client = get_client() + if scope is None: + # hub cloning is going on, we use a fork of the current/isolation scope for context manager + scope = get_isolation_scope().fork() + current_scope = get_current_scope().fork() + else: + client = client_or_hub # type: ignore + get_global_scope().set_client(client) + + if scope is None: # so there is no Hub cloning going on + # just the current isolation scope is used for context manager + scope = get_isolation_scope() + current_scope = get_current_scope() + + if current_scope is None: + # just the current current scope is used for context manager + current_scope = get_current_scope() + + self._stack = [(client, scope)] # type: ignore + self._last_event_id = None # type: Optional[str] + self._old_hubs = [] # type: List[Hub] + + self._old_current_scopes = [] # type: List[Scope] + self._old_isolation_scopes = [] # type: List[Scope] + self._current_scope = current_scope # type: Scope + self._scope = scope # type: Scope + + def __enter__(self): + # type: () -> Hub + self._old_hubs.append(Hub.current) + _local.set(self) + + current_scope = get_current_scope() + self._old_current_scopes.append(current_scope) + scope._current_scope.set(self._current_scope) + + isolation_scope = get_isolation_scope() + self._old_isolation_scopes.append(isolation_scope) + scope._isolation_scope.set(self._scope) + + return self + + def __exit__( + self, + exc_type, # type: Optional[type] + exc_value, # type: Optional[BaseException] + tb, # type: Optional[Any] + ): + # type: (...) -> None + old = self._old_hubs.pop() + _local.set(old) + + old_current_scope = self._old_current_scopes.pop() + scope._current_scope.set(old_current_scope) + + old_isolation_scope = self._old_isolation_scopes.pop() + scope._isolation_scope.set(old_isolation_scope) + + def run( + self, callback # type: Callable[[], T] + ): + # type: (...) -> T + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + + Runs a callback in the context of the hub. Alternatively the + with statement can be used on the hub directly. + """ + with self: + return callback() + + def get_integration( + self, name_or_class # type: Union[str, Type[Integration]] + ): + # type: (...) -> Any + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.client._Client.get_integration` instead. + + Returns the integration for this hub by name or class. If there + is no client bound or the client does not have that integration + then `None` is returned. + + If the return value is not `None` the hub is guaranteed to have a + client attached. + """ + return get_client().get_integration(name_or_class) + + @property + def client(self): + # type: () -> Optional[BaseClient] + """ + .. deprecated:: 2.0.0 + This property is deprecated and will be removed in a future release. + Please use :py:func:`sentry_sdk.api.get_client` instead. + + Returns the current client on the hub. + """ + client = get_client() + + if not client.is_active(): + return None + + return client + + @property + def scope(self): + # type: () -> Scope + """ + .. deprecated:: 2.0.0 + This property is deprecated and will be removed in a future release. + Returns the current scope on the hub. + """ + return get_isolation_scope() + + def last_event_id(self): + # type: () -> Optional[str] + """ + Returns the last event ID. + + .. deprecated:: 1.40.5 + This function is deprecated and will be removed in a future release. The functions `capture_event`, `capture_message`, and `capture_exception` return the event ID directly. + """ + logger.warning( + "Deprecated: last_event_id is deprecated. This will be removed in the future. The functions `capture_event`, `capture_message`, and `capture_exception` return the event ID directly." + ) + return self._last_event_id + + def bind_client( + self, new # type: Optional[BaseClient] + ): + # type: (...) -> None + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.set_client` instead. + + Binds a new client to the hub. + """ + get_global_scope().set_client(new) + + def capture_event(self, event, hint=None, scope=None, **scope_kwargs): + # type: (Event, Optional[Hint], Optional[Scope], Any) -> Optional[str] + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.capture_event` instead. + + Captures an event. + + Alias of :py:meth:`sentry_sdk.Scope.capture_event`. + + :param event: A ready-made event that can be directly sent to Sentry. + + :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. + + :param scope: An optional :py:class:`sentry_sdk.Scope` to apply to events. + The `scope` and `scope_kwargs` parameters are mutually exclusive. + + :param scope_kwargs: Optional data to apply to event. + For supported `**scope_kwargs` see :py:meth:`sentry_sdk.Scope.update_from_kwargs`. + The `scope` and `scope_kwargs` parameters are mutually exclusive. + """ + last_event_id = get_current_scope().capture_event( + event, hint, scope=scope, **scope_kwargs + ) + + is_transaction = event.get("type") == "transaction" + if last_event_id is not None and not is_transaction: + self._last_event_id = last_event_id + + return last_event_id + + def capture_message(self, message, level=None, scope=None, **scope_kwargs): + # type: (str, Optional[LogLevelStr], Optional[Scope], Any) -> Optional[str] + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.capture_message` instead. + + Captures a message. + + Alias of :py:meth:`sentry_sdk.Scope.capture_message`. + + :param message: The string to send as the message to Sentry. + + :param level: If no level is provided, the default level is `info`. + + :param scope: An optional :py:class:`sentry_sdk.Scope` to apply to events. + The `scope` and `scope_kwargs` parameters are mutually exclusive. + + :param scope_kwargs: Optional data to apply to event. + For supported `**scope_kwargs` see :py:meth:`sentry_sdk.Scope.update_from_kwargs`. + The `scope` and `scope_kwargs` parameters are mutually exclusive. + + :returns: An `event_id` if the SDK decided to send the event (see :py:meth:`sentry_sdk.client._Client.capture_event`). + """ + last_event_id = get_current_scope().capture_message( + message, level=level, scope=scope, **scope_kwargs + ) + + if last_event_id is not None: + self._last_event_id = last_event_id + + return last_event_id + + def capture_exception(self, error=None, scope=None, **scope_kwargs): + # type: (Optional[Union[BaseException, ExcInfo]], Optional[Scope], Any) -> Optional[str] + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.capture_exception` instead. + + Captures an exception. + + Alias of :py:meth:`sentry_sdk.Scope.capture_exception`. + + :param error: An exception to capture. If `None`, `sys.exc_info()` will be used. + + :param scope: An optional :py:class:`sentry_sdk.Scope` to apply to events. + The `scope` and `scope_kwargs` parameters are mutually exclusive. + + :param scope_kwargs: Optional data to apply to event. + For supported `**scope_kwargs` see :py:meth:`sentry_sdk.Scope.update_from_kwargs`. + The `scope` and `scope_kwargs` parameters are mutually exclusive. + + :returns: An `event_id` if the SDK decided to send the event (see :py:meth:`sentry_sdk.client._Client.capture_event`). + """ + last_event_id = get_current_scope().capture_exception( + error, scope=scope, **scope_kwargs + ) + + if last_event_id is not None: + self._last_event_id = last_event_id + + return last_event_id + + def add_breadcrumb(self, crumb=None, hint=None, **kwargs): + # type: (Optional[Breadcrumb], Optional[BreadcrumbHint], Any) -> None + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.add_breadcrumb` instead. + + 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. + """ + get_isolation_scope().add_breadcrumb(crumb, hint, **kwargs) + + def start_span(self, instrumenter=INSTRUMENTER.SENTRY, **kwargs): + # type: (str, Any) -> Span + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.start_span` instead. + + Start a span whose parent is the currently active span or transaction, if any. + + The return value is a :py:class:`sentry_sdk.tracing.Span` instance, + typically used as a context manager to start and stop timing in a `with` + block. + + Only spans contained in a transaction are sent to Sentry. Most + integrations start a transaction at the appropriate time, for example + for every incoming HTTP request. Use + :py:meth:`sentry_sdk.start_transaction` to start a new transaction when + one is not already in progress. + + For supported `**kwargs` see :py:class:`sentry_sdk.tracing.Span`. + """ + scope = get_current_scope() + return scope.start_span(instrumenter=instrumenter, **kwargs) + + def start_transaction( + self, + transaction=None, + instrumenter=INSTRUMENTER.SENTRY, + custom_sampling_context=None, + **kwargs + ): + # type: (Optional[Transaction], str, Optional[SamplingContext], Unpack[TransactionKwargs]) -> Union[Transaction, NoOpSpan] + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.start_transaction` instead. + + Start and return a transaction. + + Start an existing transaction if given, otherwise create and start a new + transaction with kwargs. + + This is the entry point to manual tracing instrumentation. + + A tree structure can be built by adding child spans to the transaction, + and child spans to other spans. To start a new child span within the + transaction or any span, call the respective `.start_child()` method. + + Every child span must be finished before the transaction is finished, + otherwise the unfinished spans are discarded. + + When used as context managers, spans and transactions are automatically + finished at the end of the `with` block. If not using context managers, + call the `.finish()` method. + + When the transaction is finished, it will be sent to Sentry with all its + finished child spans. + + For supported `**kwargs` see :py:class:`sentry_sdk.tracing.Transaction`. + """ + scope = get_current_scope() + + # For backwards compatibility, we allow passing the scope as the hub. + # We need a major release to make this nice. (if someone searches the code: deprecated) + # Type checking disabled for this line because deprecated keys are not allowed in the type signature. + kwargs["hub"] = scope # type: ignore + + return scope.start_transaction( + transaction, instrumenter, custom_sampling_context, **kwargs + ) + + def continue_trace(self, environ_or_headers, op=None, name=None, source=None): + # type: (Dict[str, Any], Optional[str], Optional[str], Optional[str]) -> Transaction + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.continue_trace` instead. + + Sets the propagation context from environment or headers and returns a transaction. + """ + return get_isolation_scope().continue_trace( + environ_or_headers=environ_or_headers, op=op, name=name, source=source + ) + + @overload + def push_scope( + self, callback=None # type: Optional[None] + ): + # type: (...) -> ContextManager[Scope] + pass + + @overload + def push_scope( # noqa: F811 + self, callback # type: Callable[[Scope], None] + ): + # type: (...) -> None + pass + + def push_scope( # noqa + self, + callback=None, # type: Optional[Callable[[Scope], None]] + continue_trace=True, # type: bool + ): + # type: (...) -> Optional[ContextManager[Scope]] + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + + Pushes a new layer on the scope stack. + + :param callback: If provided, this method pushes a scope, calls + `callback`, and pops the scope again. + + :returns: If no `callback` is provided, a context manager that should + be used to pop the scope again. + """ + if callback is not None: + with self.push_scope() as scope: + callback(scope) + return None + + return _ScopeManager(self) + + def pop_scope_unsafe(self): + # type: () -> Tuple[Optional[Client], Scope] + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + + Pops a scope layer from the stack. + + Try to use the context manager :py:meth:`push_scope` instead. + """ + rv = self._stack.pop() + assert self._stack, "stack must have at least one layer" + return rv + + @overload + def configure_scope( + self, callback=None # type: Optional[None] + ): + # type: (...) -> ContextManager[Scope] + pass + + @overload + def configure_scope( # noqa: F811 + self, callback # type: Callable[[Scope], None] + ): + # type: (...) -> None + pass + + def configure_scope( # noqa + self, + callback=None, # type: Optional[Callable[[Scope], None]] + continue_trace=True, # type: bool + ): + # type: (...) -> Optional[ContextManager[Scope]] + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + + Reconfigures the scope. + + :param callback: If provided, call the callback with the current scope. + + :returns: If no callback is provided, returns a context manager that returns the scope. + """ + scope = get_isolation_scope() + + if continue_trace: + scope.generate_propagation_context() + + if callback is not None: + # TODO: used to return None when client is None. Check if this changes behavior. + callback(scope) + + return None + + @contextmanager + def inner(): + # type: () -> Generator[Scope, None, None] + yield scope + + return inner() + + def start_session( + self, session_mode="application" # type: str + ): + # type: (...) -> None + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.start_session` instead. + + Starts a new session. + """ + get_isolation_scope().start_session( + session_mode=session_mode, + ) + + def end_session(self): + # type: (...) -> None + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.end_session` instead. + + Ends the current session if there is one. + """ + get_isolation_scope().end_session() + + def stop_auto_session_tracking(self): + # type: (...) -> None + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.stop_auto_session_tracking` instead. + + Stops automatic session tracking. + + This temporarily session tracking for the current scope when called. + To resume session tracking call `resume_auto_session_tracking`. + """ + get_isolation_scope().stop_auto_session_tracking() + + def resume_auto_session_tracking(self): + # type: (...) -> None + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.resume_auto_session_tracking` instead. + + Resumes automatic session tracking for the current scope if + disabled earlier. This requires that generally automatic session + tracking is enabled. + """ + get_isolation_scope().resume_auto_session_tracking() + + def flush( + self, + timeout=None, # type: Optional[float] + callback=None, # type: Optional[Callable[[int, float], None]] + ): + # type: (...) -> None + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.client._Client.flush` instead. + + Alias for :py:meth:`sentry_sdk.client._Client.flush` + """ + return get_client().flush(timeout=timeout, callback=callback) + + def get_traceparent(self): + # type: () -> Optional[str] + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.get_traceparent` instead. + + Returns the traceparent either from the active span or from the scope. + """ + current_scope = get_current_scope() + traceparent = current_scope.get_traceparent() + + if traceparent is None: + isolation_scope = get_isolation_scope() + traceparent = isolation_scope.get_traceparent() + + return traceparent + + def get_baggage(self): + # type: () -> Optional[str] + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.get_baggage` instead. + + Returns Baggage either from the active span or from the scope. + """ + current_scope = get_current_scope() + baggage = current_scope.get_baggage() + + if baggage is None: + isolation_scope = get_isolation_scope() + baggage = isolation_scope.get_baggage() + + if baggage is not None: + return baggage.serialize() + + return None + + def iter_trace_propagation_headers(self, span=None): + # type: (Optional[Span]) -> Generator[Tuple[str, str], None, None] + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.iter_trace_propagation_headers` instead. + + Return HTTP headers which allow propagation of trace data. Data taken + from the span representing the request, if available, or the current + span on the scope if not. + """ + return get_current_scope().iter_trace_propagation_headers( + span=span, + ) + + def trace_propagation_meta(self, span=None): + # type: (Optional[Span]) -> str + """ + .. deprecated:: 2.0.0 + This function is deprecated and will be removed in a future release. + Please use :py:meth:`sentry_sdk.Scope.trace_propagation_meta` instead. + + Return meta tags which should be injected into HTML templates + to allow propagation of trace information. + """ + if span is not None: + logger.warning( + "The parameter `span` in trace_propagation_meta() is deprecated and will be removed in the future." + ) + + return get_current_scope().trace_propagation_meta( + span=span, + ) + + +with _suppress_hub_deprecation_warning(): + # Suppress deprecation warning for the Hub here, since we still always + # import this module. + GLOBAL_HUB = Hub() +_local.set(GLOBAL_HUB) + + +# Circular imports +from sentry_sdk import scope |