about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/middleware.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/middleware.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-4a52a71956a8d46fcb7294ac71734504bb09bcc2.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/middleware.py')
-rw-r--r--.venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/middleware.py187
1 files changed, 187 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/middleware.py b/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/middleware.py
new file mode 100644
index 00000000..24527656
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/middleware.py
@@ -0,0 +1,187 @@
+"""
+Create spans from Django middleware invocations
+"""
+
+from functools import wraps
+
+from django import VERSION as DJANGO_VERSION
+
+import sentry_sdk
+from sentry_sdk.consts import OP
+from sentry_sdk.utils import (
+    ContextVar,
+    transaction_from_function,
+    capture_internal_exceptions,
+)
+
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+    from typing import Any
+    from typing import Callable
+    from typing import Optional
+    from typing import TypeVar
+
+    from sentry_sdk.tracing import Span
+
+    F = TypeVar("F", bound=Callable[..., Any])
+
+_import_string_should_wrap_middleware = ContextVar(
+    "import_string_should_wrap_middleware"
+)
+
+DJANGO_SUPPORTS_ASYNC_MIDDLEWARE = DJANGO_VERSION >= (3, 1)
+
+if not DJANGO_SUPPORTS_ASYNC_MIDDLEWARE:
+    _asgi_middleware_mixin_factory = lambda _: object
+else:
+    from .asgi import _asgi_middleware_mixin_factory
+
+
+def patch_django_middlewares():
+    # type: () -> None
+    from django.core.handlers import base
+
+    old_import_string = base.import_string
+
+    def sentry_patched_import_string(dotted_path):
+        # type: (str) -> Any
+        rv = old_import_string(dotted_path)
+
+        if _import_string_should_wrap_middleware.get(None):
+            rv = _wrap_middleware(rv, dotted_path)
+
+        return rv
+
+    base.import_string = sentry_patched_import_string
+
+    old_load_middleware = base.BaseHandler.load_middleware
+
+    def sentry_patched_load_middleware(*args, **kwargs):
+        # type: (Any, Any) -> Any
+        _import_string_should_wrap_middleware.set(True)
+        try:
+            return old_load_middleware(*args, **kwargs)
+        finally:
+            _import_string_should_wrap_middleware.set(False)
+
+    base.BaseHandler.load_middleware = sentry_patched_load_middleware
+
+
+def _wrap_middleware(middleware, middleware_name):
+    # type: (Any, str) -> Any
+    from sentry_sdk.integrations.django import DjangoIntegration
+
+    def _check_middleware_span(old_method):
+        # type: (Callable[..., Any]) -> Optional[Span]
+        integration = sentry_sdk.get_client().get_integration(DjangoIntegration)
+        if integration is None or not integration.middleware_spans:
+            return None
+
+        function_name = transaction_from_function(old_method)
+
+        description = middleware_name
+        function_basename = getattr(old_method, "__name__", None)
+        if function_basename:
+            description = "{}.{}".format(description, function_basename)
+
+        middleware_span = sentry_sdk.start_span(
+            op=OP.MIDDLEWARE_DJANGO,
+            name=description,
+            origin=DjangoIntegration.origin,
+        )
+        middleware_span.set_tag("django.function_name", function_name)
+        middleware_span.set_tag("django.middleware_name", middleware_name)
+
+        return middleware_span
+
+    def _get_wrapped_method(old_method):
+        # type: (F) -> F
+        with capture_internal_exceptions():
+
+            def sentry_wrapped_method(*args, **kwargs):
+                # type: (*Any, **Any) -> Any
+                middleware_span = _check_middleware_span(old_method)
+
+                if middleware_span is None:
+                    return old_method(*args, **kwargs)
+
+                with middleware_span:
+                    return old_method(*args, **kwargs)
+
+            try:
+                # fails for __call__ of function on Python 2 (see py2.7-django-1.11)
+                sentry_wrapped_method = wraps(old_method)(sentry_wrapped_method)
+
+                # Necessary for Django 3.1
+                sentry_wrapped_method.__self__ = old_method.__self__  # type: ignore
+            except Exception:
+                pass
+
+            return sentry_wrapped_method  # type: ignore
+
+        return old_method
+
+    class SentryWrappingMiddleware(
+        _asgi_middleware_mixin_factory(_check_middleware_span)  # type: ignore
+    ):
+        sync_capable = getattr(middleware, "sync_capable", True)
+        async_capable = DJANGO_SUPPORTS_ASYNC_MIDDLEWARE and getattr(
+            middleware, "async_capable", False
+        )
+
+        def __init__(self, get_response=None, *args, **kwargs):
+            # type: (Optional[Callable[..., Any]], *Any, **Any) -> None
+            if get_response:
+                self._inner = middleware(get_response, *args, **kwargs)
+            else:
+                self._inner = middleware(*args, **kwargs)
+            self.get_response = get_response
+            self._call_method = None
+            if self.async_capable:
+                super().__init__(get_response)
+
+        # We need correct behavior for `hasattr()`, which we can only determine
+        # when we have an instance of the middleware we're wrapping.
+        def __getattr__(self, method_name):
+            # type: (str) -> Any
+            if method_name not in (
+                "process_request",
+                "process_view",
+                "process_template_response",
+                "process_response",
+                "process_exception",
+            ):
+                raise AttributeError()
+
+            old_method = getattr(self._inner, method_name)
+            rv = _get_wrapped_method(old_method)
+            self.__dict__[method_name] = rv
+            return rv
+
+        def __call__(self, *args, **kwargs):
+            # type: (*Any, **Any) -> Any
+            if hasattr(self, "async_route_check") and self.async_route_check():
+                return self.__acall__(*args, **kwargs)
+
+            f = self._call_method
+            if f is None:
+                self._call_method = f = self._inner.__call__
+
+            middleware_span = _check_middleware_span(old_method=f)
+
+            if middleware_span is None:
+                return f(*args, **kwargs)
+
+            with middleware_span:
+                return f(*args, **kwargs)
+
+    for attr in (
+        "__name__",
+        "__module__",
+        "__qualname__",
+    ):
+        if hasattr(middleware, attr):
+            setattr(SentryWrappingMiddleware, attr, getattr(middleware, attr))
+
+    return SentryWrappingMiddleware