aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/views.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/views.py')
-rw-r--r--.venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/views.py96
1 files changed, 96 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/views.py b/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/views.py
new file mode 100644
index 00000000..0a9861a6
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/views.py
@@ -0,0 +1,96 @@
+import functools
+
+import sentry_sdk
+from sentry_sdk.consts import OP
+
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+ from typing import Any
+
+
+try:
+ from asyncio import iscoroutinefunction
+except ImportError:
+ iscoroutinefunction = None # type: ignore
+
+
+try:
+ from sentry_sdk.integrations.django.asgi import wrap_async_view
+except (ImportError, SyntaxError):
+ wrap_async_view = None # type: ignore
+
+
+def patch_views():
+ # type: () -> None
+
+ from django.core.handlers.base import BaseHandler
+ from django.template.response import SimpleTemplateResponse
+ from sentry_sdk.integrations.django import DjangoIntegration
+
+ old_make_view_atomic = BaseHandler.make_view_atomic
+ old_render = SimpleTemplateResponse.render
+
+ def sentry_patched_render(self):
+ # type: (SimpleTemplateResponse) -> Any
+ with sentry_sdk.start_span(
+ op=OP.VIEW_RESPONSE_RENDER,
+ name="serialize response",
+ origin=DjangoIntegration.origin,
+ ):
+ return old_render(self)
+
+ @functools.wraps(old_make_view_atomic)
+ def sentry_patched_make_view_atomic(self, *args, **kwargs):
+ # type: (Any, *Any, **Any) -> Any
+ callback = old_make_view_atomic(self, *args, **kwargs)
+
+ # XXX: The wrapper function is created for every request. Find more
+ # efficient way to wrap views (or build a cache?)
+
+ integration = sentry_sdk.get_client().get_integration(DjangoIntegration)
+ if integration is not None and integration.middleware_spans:
+ is_async_view = (
+ iscoroutinefunction is not None
+ and wrap_async_view is not None
+ and iscoroutinefunction(callback)
+ )
+ if is_async_view:
+ sentry_wrapped_callback = wrap_async_view(callback)
+ else:
+ sentry_wrapped_callback = _wrap_sync_view(callback)
+
+ else:
+ sentry_wrapped_callback = callback
+
+ return sentry_wrapped_callback
+
+ SimpleTemplateResponse.render = sentry_patched_render
+ BaseHandler.make_view_atomic = sentry_patched_make_view_atomic
+
+
+def _wrap_sync_view(callback):
+ # type: (Any) -> Any
+ from sentry_sdk.integrations.django import DjangoIntegration
+
+ @functools.wraps(callback)
+ def sentry_wrapped_callback(request, *args, **kwargs):
+ # type: (Any, *Any, **Any) -> Any
+ current_scope = sentry_sdk.get_current_scope()
+ if current_scope.transaction is not None:
+ current_scope.transaction.update_active_thread()
+
+ sentry_scope = sentry_sdk.get_isolation_scope()
+ # set the active thread id to the handler thread for sync views
+ # this isn't necessary for async views since that runs on main
+ if sentry_scope.profile is not None:
+ sentry_scope.profile.update_active_thread_id()
+
+ with sentry_sdk.start_span(
+ op=OP.VIEW_RENDER,
+ name=request.resolver_match.view_name,
+ origin=DjangoIntegration.origin,
+ ):
+ return callback(request, *args, **kwargs)
+
+ return sentry_wrapped_callback