|
1 | 1 | from __future__ import absolute_import
|
2 | 2 |
|
| 3 | +import inspect |
| 4 | +import threading |
| 5 | + |
3 | 6 | from sentry_sdk.hub import _should_send_default_pii, Hub
|
4 | 7 | from sentry_sdk.integrations import DidNotEnable, Integration
|
5 | 8 | from sentry_sdk.integrations._wsgi_common import _filter_headers
|
|
11 | 14 | event_from_exception,
|
12 | 15 | )
|
13 | 16 |
|
| 17 | +from sentry_sdk._functools import wraps |
14 | 18 | from sentry_sdk._types import TYPE_CHECKING
|
15 | 19 |
|
16 | 20 | if TYPE_CHECKING:
|
|
34 | 38 | request,
|
35 | 39 | websocket,
|
36 | 40 | )
|
| 41 | + from quart.scaffold import Scaffold # type: ignore |
37 | 42 | from quart.signals import ( # type: ignore
|
38 | 43 | got_background_exception,
|
39 | 44 | got_request_exception,
|
40 | 45 | got_websocket_exception,
|
41 | 46 | request_started,
|
42 | 47 | websocket_started,
|
43 | 48 | )
|
| 49 | + from quart.utils import is_coroutine_function # type: ignore |
44 | 50 | except ImportError:
|
45 | 51 | raise DidNotEnable("Quart is not installed")
|
46 | 52 |
|
@@ -71,18 +77,62 @@ def setup_once():
|
71 | 77 | got_request_exception.connect(_capture_exception)
|
72 | 78 | got_websocket_exception.connect(_capture_exception)
|
73 | 79 |
|
74 |
| - old_app = Quart.__call__ |
| 80 | + patch_asgi_app() |
| 81 | + patch_scaffold_route() |
| 82 | + |
| 83 | + |
| 84 | +def patch_asgi_app(): |
| 85 | + # type: () -> None |
| 86 | + old_app = Quart.__call__ |
| 87 | + |
| 88 | + async def sentry_patched_asgi_app(self, scope, receive, send): |
| 89 | + # type: (Any, Any, Any, Any) -> Any |
| 90 | + if Hub.current.get_integration(QuartIntegration) is None: |
| 91 | + return await old_app(self, scope, receive, send) |
| 92 | + |
| 93 | + middleware = SentryAsgiMiddleware(lambda *a, **kw: old_app(self, *a, **kw)) |
| 94 | + middleware.__call__ = middleware._run_asgi3 |
| 95 | + return await middleware(scope, receive, send) |
| 96 | + |
| 97 | + Quart.__call__ = sentry_patched_asgi_app |
| 98 | + |
| 99 | + |
| 100 | +def patch_scaffold_route(): |
| 101 | + # type: () -> None |
| 102 | + old_route = Scaffold.route |
| 103 | + |
| 104 | + def _sentry_route(*args, **kwargs): |
| 105 | + # type: (*Any, **Any) -> Any |
| 106 | + old_decorator = old_route(*args, **kwargs) |
| 107 | + |
| 108 | + def decorator(old_func): |
| 109 | + # type: (Any) -> Any |
| 110 | + |
| 111 | + if inspect.isfunction(old_func) and not is_coroutine_function(old_func): |
| 112 | + |
| 113 | + @wraps(old_func) |
| 114 | + def _sentry_func(*args, **kwargs): |
| 115 | + # type: (*Any, **Any) -> Any |
| 116 | + hub = Hub.current |
| 117 | + integration = hub.get_integration(QuartIntegration) |
| 118 | + if integration is None: |
| 119 | + return old_func(*args, **kwargs) |
| 120 | + |
| 121 | + with hub.configure_scope() as sentry_scope: |
| 122 | + if sentry_scope.profile is not None: |
| 123 | + sentry_scope.profile.active_thread_id = ( |
| 124 | + threading.current_thread().ident |
| 125 | + ) |
| 126 | + |
| 127 | + return old_func(*args, **kwargs) |
| 128 | + |
| 129 | + return old_decorator(_sentry_func) |
75 | 130 |
|
76 |
| - async def sentry_patched_asgi_app(self, scope, receive, send): |
77 |
| - # type: (Any, Any, Any, Any) -> Any |
78 |
| - if Hub.current.get_integration(QuartIntegration) is None: |
79 |
| - return await old_app(self, scope, receive, send) |
| 131 | + return old_decorator(old_func) |
80 | 132 |
|
81 |
| - middleware = SentryAsgiMiddleware(lambda *a, **kw: old_app(self, *a, **kw)) |
82 |
| - middleware.__call__ = middleware._run_asgi3 |
83 |
| - return await middleware(scope, receive, send) |
| 133 | + return decorator |
84 | 134 |
|
85 |
| - Quart.__call__ = sentry_patched_asgi_app |
| 135 | + Scaffold.route = _sentry_route |
86 | 136 |
|
87 | 137 |
|
88 | 138 | def _set_transaction_name_and_source(scope, transaction_style, request):
|
|
0 commit comments