11
11
from sentry_sdk import Hub , _functools
12
12
from sentry_sdk ._types import TYPE_CHECKING
13
13
from sentry_sdk .consts import OP
14
+ from sentry_sdk .hub import _should_send_default_pii
14
15
15
16
from sentry_sdk .integrations .asgi import SentryAsgiMiddleware
17
+ from sentry_sdk .utils import capture_internal_exceptions
18
+
19
+ from django .core .handlers .wsgi import WSGIRequest
20
+
16
21
17
22
if TYPE_CHECKING :
18
23
from typing import Any
24
+ from typing import Dict
19
25
from typing import Union
20
26
from typing import Callable
21
27
28
+ from django .core .handlers .asgi import ASGIRequest
22
29
from django .http .response import HttpResponse
23
30
31
+ from sentry_sdk .integrations .django import DjangoIntegration
32
+ from sentry_sdk ._types import EventProcessor
33
+
34
+
35
+ def _make_asgi_request_event_processor (request , integration ):
36
+ # type: (ASGIRequest, DjangoIntegration) -> EventProcessor
37
+ def asgi_request_event_processor (event , hint ):
38
+ # type: (Dict[str, Any], Dict[str, Any]) -> Dict[str, Any]
39
+ # if the request is gone we are fine not logging the data from
40
+ # it. This might happen if the processor is pushed away to
41
+ # another thread.
42
+ from sentry_sdk .integrations .django import (
43
+ DjangoRequestExtractor ,
44
+ _set_user_info ,
45
+ )
46
+
47
+ if request is None :
48
+ return event
49
+
50
+ if type (request ) == WSGIRequest :
51
+ return event
52
+
53
+ with capture_internal_exceptions ():
54
+ DjangoRequestExtractor (request ).extract_into_event (event )
55
+
56
+ if _should_send_default_pii ():
57
+ with capture_internal_exceptions ():
58
+ _set_user_info (request , event )
59
+
60
+ return event
61
+
62
+ return asgi_request_event_processor
63
+
24
64
25
65
def patch_django_asgi_handler_impl (cls ):
26
66
# type: (Any) -> None
@@ -31,16 +71,46 @@ def patch_django_asgi_handler_impl(cls):
31
71
32
72
async def sentry_patched_asgi_handler (self , scope , receive , send ):
33
73
# type: (Any, Any, Any, Any) -> Any
34
- if Hub .current .get_integration (DjangoIntegration ) is None :
74
+ hub = Hub .current
75
+ integration = hub .get_integration (DjangoIntegration )
76
+ if integration is None :
35
77
return await old_app (self , scope , receive , send )
36
78
37
79
middleware = SentryAsgiMiddleware (
38
80
old_app .__get__ (self , cls ), unsafe_context_data = True
39
81
)._run_asgi3
82
+
40
83
return await middleware (scope , receive , send )
41
84
42
85
cls .__call__ = sentry_patched_asgi_handler
43
86
87
+ modern_django_asgi_support = hasattr (cls , "create_request" )
88
+ if modern_django_asgi_support :
89
+ old_create_request = cls .create_request
90
+
91
+ def sentry_patched_create_request (self , * args , ** kwargs ):
92
+ # type: (Any, *Any, **Any) -> Any
93
+ hub = Hub .current
94
+ integration = hub .get_integration (DjangoIntegration )
95
+ if integration is None :
96
+ return old_create_request (self , * args , ** kwargs )
97
+
98
+ with hub .configure_scope () as scope :
99
+ request , error_response = old_create_request (self , * args , ** kwargs )
100
+
101
+ # read the body once, to signal Django to cache the body stream
102
+ # so we can read the body in our event processor
103
+ # (otherwise Django closes the body stream and makes it impossible to read it again)
104
+ _ = request .body
105
+
106
+ scope .add_event_processor (
107
+ _make_asgi_request_event_processor (request , integration )
108
+ )
109
+
110
+ return request , error_response
111
+
112
+ cls .create_request = sentry_patched_create_request
113
+
44
114
45
115
def patch_get_response_async (cls , _before_get_response ):
46
116
# type: (Any, Any) -> None
0 commit comments