diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py index 3282918490..7c1da02afe 100644 --- a/sentry_sdk/integrations/aiohttp.py +++ b/sentry_sdk/integrations/aiohttp.py @@ -42,6 +42,7 @@ HAS_REAL_CONTEXTVARS, SENSITIVE_DATA_SUBSTITUTE, AnnotatedValue, + _register_control_flow_exception, capture_internal_exceptions, ensure_integration_enabled, event_from_exception, @@ -111,6 +112,12 @@ def setup_once() -> None: " or aiocontextvars package." + CONTEXTVARS_ERROR_MESSAGE ) + # In the aiohttp integration, all of their HTTP responses are Exceptions. + # Because they have to be raised and handled by the framework, we need to + # register the exceptions as control flow exceptions so that we don't + # accidentally overwrite a status of "ok" with "error". + _register_control_flow_exception(HTTPException) + ignore_logger("aiohttp.server") old_handle = Application._handle diff --git a/sentry_sdk/utils.py b/sentry_sdk/utils.py index aa13a98e94..e63bbd2568 100644 --- a/sentry_sdk/utils.py +++ b/sentry_sdk/utils.py @@ -27,11 +27,6 @@ # Python 3.10 and below BaseExceptionGroup = None # type: ignore -try: - from aiohttp.web_exceptions import HTTPException as AIOHttpHttpException -except ImportError: - AIOHttpHttpException = None - from typing import TYPE_CHECKING import sentry_sdk @@ -93,6 +88,10 @@ "is_sentry_internal_task", default=False ) +# These exceptions won't set the span status to error if they occur. Use +# register_control_flow_exception to add to this list +_control_flow_exception_classes: "list[type]" = [] + def is_internal_task() -> bool: return _is_sentry_internal_task.get() @@ -1983,15 +1982,16 @@ def get_current_thread_meta( return None, None +def _register_control_flow_exception(exc_type: type) -> None: + _control_flow_exception_classes.append(exc_type) + + def should_be_treated_as_error(ty: "Any", value: "Any") -> bool: if ty == SystemExit and hasattr(value, "code") and value.code in (0, None): # https://docs.python.org/3/library/exceptions.html#SystemExit return False - # In the aiohttp integration, all of their HTTP responses are Exceptions. - # Because they have to be raised and handled by the framework, we need this check so - # that we don't accidentally overwrite a status of "ok" with "error" here. - if AIOHttpHttpException and isinstance(value, AIOHttpHttpException): + if issubclass(ty, tuple(_control_flow_exception_classes)): return False return True