sentry-sdk 3.0.0a1__py2.py3-none-any.whl → 3.0.0a3__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of sentry-sdk might be problematic. Click here for more details.
- sentry_sdk/__init__.py +2 -0
- sentry_sdk/_compat.py +5 -12
- sentry_sdk/_init_implementation.py +7 -7
- sentry_sdk/_log_batcher.py +17 -29
- sentry_sdk/_lru_cache.py +7 -9
- sentry_sdk/_queue.py +2 -4
- sentry_sdk/_types.py +11 -18
- sentry_sdk/_werkzeug.py +5 -7
- sentry_sdk/ai/monitoring.py +44 -31
- sentry_sdk/ai/utils.py +3 -4
- sentry_sdk/api.py +75 -87
- sentry_sdk/attachments.py +10 -12
- sentry_sdk/client.py +137 -155
- sentry_sdk/consts.py +430 -174
- sentry_sdk/crons/api.py +16 -17
- sentry_sdk/crons/decorator.py +25 -27
- sentry_sdk/debug.py +4 -6
- sentry_sdk/envelope.py +46 -112
- sentry_sdk/feature_flags.py +9 -15
- sentry_sdk/integrations/__init__.py +24 -19
- sentry_sdk/integrations/_asgi_common.py +15 -18
- sentry_sdk/integrations/_wsgi_common.py +22 -33
- sentry_sdk/integrations/aiohttp.py +32 -30
- sentry_sdk/integrations/anthropic.py +42 -37
- sentry_sdk/integrations/argv.py +3 -4
- sentry_sdk/integrations/ariadne.py +16 -18
- sentry_sdk/integrations/arq.py +21 -29
- sentry_sdk/integrations/asgi.py +63 -37
- sentry_sdk/integrations/asyncio.py +14 -16
- sentry_sdk/integrations/atexit.py +6 -10
- sentry_sdk/integrations/aws_lambda.py +26 -36
- sentry_sdk/integrations/beam.py +10 -18
- sentry_sdk/integrations/boto3.py +18 -16
- sentry_sdk/integrations/bottle.py +25 -34
- sentry_sdk/integrations/celery/__init__.py +41 -61
- sentry_sdk/integrations/celery/beat.py +23 -27
- sentry_sdk/integrations/celery/utils.py +15 -17
- sentry_sdk/integrations/chalice.py +8 -10
- sentry_sdk/integrations/clickhouse_driver.py +21 -31
- sentry_sdk/integrations/cloud_resource_context.py +9 -16
- sentry_sdk/integrations/cohere.py +27 -33
- sentry_sdk/integrations/dedupe.py +5 -8
- sentry_sdk/integrations/django/__init__.py +57 -72
- sentry_sdk/integrations/django/asgi.py +26 -34
- sentry_sdk/integrations/django/caching.py +23 -19
- sentry_sdk/integrations/django/middleware.py +17 -20
- sentry_sdk/integrations/django/signals_handlers.py +11 -10
- sentry_sdk/integrations/django/templates.py +19 -16
- sentry_sdk/integrations/django/transactions.py +16 -11
- sentry_sdk/integrations/django/views.py +6 -10
- sentry_sdk/integrations/dramatiq.py +21 -21
- sentry_sdk/integrations/excepthook.py +10 -10
- sentry_sdk/integrations/executing.py +3 -4
- sentry_sdk/integrations/falcon.py +27 -42
- sentry_sdk/integrations/fastapi.py +13 -16
- sentry_sdk/integrations/flask.py +31 -38
- sentry_sdk/integrations/gcp.py +13 -16
- sentry_sdk/integrations/gnu_backtrace.py +4 -6
- sentry_sdk/integrations/gql.py +16 -17
- sentry_sdk/integrations/graphene.py +13 -12
- sentry_sdk/integrations/grpc/__init__.py +19 -1
- sentry_sdk/integrations/grpc/aio/server.py +15 -14
- sentry_sdk/integrations/grpc/client.py +19 -9
- sentry_sdk/integrations/grpc/consts.py +2 -0
- sentry_sdk/integrations/grpc/server.py +12 -8
- sentry_sdk/integrations/httpx.py +9 -12
- sentry_sdk/integrations/huey.py +13 -20
- sentry_sdk/integrations/huggingface_hub.py +18 -18
- sentry_sdk/integrations/langchain.py +203 -113
- sentry_sdk/integrations/launchdarkly.py +13 -10
- sentry_sdk/integrations/litestar.py +37 -35
- sentry_sdk/integrations/logging.py +52 -65
- sentry_sdk/integrations/loguru.py +127 -57
- sentry_sdk/integrations/modules.py +3 -4
- sentry_sdk/integrations/openai.py +100 -88
- sentry_sdk/integrations/openai_agents/__init__.py +49 -0
- sentry_sdk/integrations/openai_agents/consts.py +1 -0
- sentry_sdk/integrations/openai_agents/patches/__init__.py +4 -0
- sentry_sdk/integrations/openai_agents/patches/agent_run.py +152 -0
- sentry_sdk/integrations/openai_agents/patches/models.py +52 -0
- sentry_sdk/integrations/openai_agents/patches/runner.py +42 -0
- sentry_sdk/integrations/openai_agents/patches/tools.py +84 -0
- sentry_sdk/integrations/openai_agents/spans/__init__.py +5 -0
- sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +20 -0
- sentry_sdk/integrations/openai_agents/spans/ai_client.py +46 -0
- sentry_sdk/integrations/openai_agents/spans/execute_tool.py +47 -0
- sentry_sdk/integrations/openai_agents/spans/handoff.py +24 -0
- sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +41 -0
- sentry_sdk/integrations/openai_agents/utils.py +201 -0
- sentry_sdk/integrations/openfeature.py +11 -6
- sentry_sdk/integrations/pure_eval.py +6 -10
- sentry_sdk/integrations/pymongo.py +13 -17
- sentry_sdk/integrations/pyramid.py +31 -36
- sentry_sdk/integrations/quart.py +23 -28
- sentry_sdk/integrations/ray.py +73 -64
- sentry_sdk/integrations/redis/__init__.py +7 -4
- sentry_sdk/integrations/redis/_async_common.py +25 -12
- sentry_sdk/integrations/redis/_sync_common.py +19 -13
- sentry_sdk/integrations/redis/modules/caches.py +17 -8
- sentry_sdk/integrations/redis/modules/queries.py +9 -8
- sentry_sdk/integrations/redis/rb.py +3 -2
- sentry_sdk/integrations/redis/redis.py +4 -4
- sentry_sdk/integrations/redis/redis_cluster.py +21 -13
- sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +3 -2
- sentry_sdk/integrations/redis/utils.py +23 -24
- sentry_sdk/integrations/rq.py +13 -16
- sentry_sdk/integrations/rust_tracing.py +9 -6
- sentry_sdk/integrations/sanic.py +34 -46
- sentry_sdk/integrations/serverless.py +22 -27
- sentry_sdk/integrations/socket.py +27 -15
- sentry_sdk/integrations/spark/__init__.py +1 -0
- sentry_sdk/integrations/spark/spark_driver.py +45 -83
- sentry_sdk/integrations/spark/spark_worker.py +7 -11
- sentry_sdk/integrations/sqlalchemy.py +22 -19
- sentry_sdk/integrations/starlette.py +86 -90
- sentry_sdk/integrations/starlite.py +28 -34
- sentry_sdk/integrations/statsig.py +5 -4
- sentry_sdk/integrations/stdlib.py +28 -24
- sentry_sdk/integrations/strawberry.py +62 -49
- sentry_sdk/integrations/sys_exit.py +7 -11
- sentry_sdk/integrations/threading.py +12 -14
- sentry_sdk/integrations/tornado.py +28 -32
- sentry_sdk/integrations/trytond.py +4 -3
- sentry_sdk/integrations/typer.py +8 -6
- sentry_sdk/integrations/unleash.py +5 -4
- sentry_sdk/integrations/wsgi.py +47 -46
- sentry_sdk/logger.py +41 -10
- sentry_sdk/monitor.py +16 -28
- sentry_sdk/opentelemetry/consts.py +11 -4
- sentry_sdk/opentelemetry/contextvars_context.py +26 -16
- sentry_sdk/opentelemetry/propagator.py +38 -21
- sentry_sdk/opentelemetry/sampler.py +51 -34
- sentry_sdk/opentelemetry/scope.py +36 -37
- sentry_sdk/opentelemetry/span_processor.py +48 -58
- sentry_sdk/opentelemetry/tracing.py +58 -14
- sentry_sdk/opentelemetry/utils.py +186 -194
- sentry_sdk/profiler/continuous_profiler.py +108 -97
- sentry_sdk/profiler/transaction_profiler.py +70 -97
- sentry_sdk/profiler/utils.py +11 -15
- sentry_sdk/scope.py +251 -273
- sentry_sdk/scrubber.py +22 -26
- sentry_sdk/serializer.py +40 -54
- sentry_sdk/session.py +44 -61
- sentry_sdk/sessions.py +35 -49
- sentry_sdk/spotlight.py +15 -21
- sentry_sdk/tracing.py +121 -187
- sentry_sdk/tracing_utils.py +104 -122
- sentry_sdk/transport.py +131 -157
- sentry_sdk/utils.py +232 -309
- sentry_sdk/worker.py +16 -28
- {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/METADATA +3 -3
- sentry_sdk-3.0.0a3.dist-info/RECORD +168 -0
- {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/WHEEL +1 -1
- sentry_sdk-3.0.0a1.dist-info/RECORD +0 -154
- {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/entry_points.txt +0 -0
- {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/licenses/LICENSE +0 -0
- {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/top_level.txt +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
from functools import wraps
|
|
2
3
|
|
|
3
4
|
from django.dispatch import Signal
|
|
@@ -13,8 +14,7 @@ if TYPE_CHECKING:
|
|
|
13
14
|
from typing import Any, Union
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
def _get_receiver_name(receiver):
|
|
17
|
-
# type: (Callable[..., Any]) -> str
|
|
17
|
+
def _get_receiver_name(receiver: Callable[..., Any]) -> str:
|
|
18
18
|
name = ""
|
|
19
19
|
|
|
20
20
|
if hasattr(receiver, "__qualname__"):
|
|
@@ -38,8 +38,7 @@ def _get_receiver_name(receiver):
|
|
|
38
38
|
return name
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
def patch_signals():
|
|
42
|
-
# type: () -> None
|
|
41
|
+
def patch_signals() -> None:
|
|
43
42
|
"""
|
|
44
43
|
Patch django signal receivers to create a span.
|
|
45
44
|
|
|
@@ -51,19 +50,21 @@ def patch_signals():
|
|
|
51
50
|
old_live_receivers = Signal._live_receivers
|
|
52
51
|
|
|
53
52
|
@wraps(old_live_receivers)
|
|
54
|
-
def _sentry_live_receivers(self, sender)
|
|
55
|
-
|
|
53
|
+
def _sentry_live_receivers(self: Signal, sender: Any) -> Union[
|
|
54
|
+
tuple[list[Callable[..., Any]], list[Callable[..., Any]]],
|
|
55
|
+
list[Callable[..., Any]],
|
|
56
|
+
]:
|
|
56
57
|
if DJANGO_VERSION >= (5, 0):
|
|
57
58
|
sync_receivers, async_receivers = old_live_receivers(self, sender)
|
|
58
59
|
else:
|
|
59
60
|
sync_receivers = old_live_receivers(self, sender)
|
|
60
61
|
async_receivers = []
|
|
61
62
|
|
|
62
|
-
def sentry_sync_receiver_wrapper(
|
|
63
|
-
|
|
63
|
+
def sentry_sync_receiver_wrapper(
|
|
64
|
+
receiver: Callable[..., Any],
|
|
65
|
+
) -> Callable[..., Any]:
|
|
64
66
|
@wraps(receiver)
|
|
65
|
-
def wrapper(*args, **kwargs):
|
|
66
|
-
# type: (Any, Any) -> Any
|
|
67
|
+
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
67
68
|
signal_name = _get_receiver_name(receiver)
|
|
68
69
|
with sentry_sdk.start_span(
|
|
69
70
|
op=OP.EVENT_DJANGO,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import functools
|
|
2
3
|
|
|
3
4
|
from django.template import TemplateSyntaxError
|
|
@@ -18,8 +19,9 @@ if TYPE_CHECKING:
|
|
|
18
19
|
from typing import Tuple
|
|
19
20
|
|
|
20
21
|
|
|
21
|
-
def get_template_frame_from_exception(
|
|
22
|
-
|
|
22
|
+
def get_template_frame_from_exception(
|
|
23
|
+
exc_value: Optional[BaseException],
|
|
24
|
+
) -> Optional[Dict[str, Any]]:
|
|
23
25
|
|
|
24
26
|
# As of Django 1.9 or so the new template debug thing showed up.
|
|
25
27
|
if hasattr(exc_value, "template_debug"):
|
|
@@ -41,8 +43,7 @@ def get_template_frame_from_exception(exc_value):
|
|
|
41
43
|
return None
|
|
42
44
|
|
|
43
45
|
|
|
44
|
-
def _get_template_name_description(template_name):
|
|
45
|
-
# type: (str) -> str
|
|
46
|
+
def _get_template_name_description(template_name: str) -> str:
|
|
46
47
|
if isinstance(template_name, (list, tuple)):
|
|
47
48
|
if template_name:
|
|
48
49
|
return "[{}, ...]".format(template_name[0])
|
|
@@ -50,8 +51,7 @@ def _get_template_name_description(template_name):
|
|
|
50
51
|
return template_name
|
|
51
52
|
|
|
52
53
|
|
|
53
|
-
def patch_templates():
|
|
54
|
-
# type: () -> None
|
|
54
|
+
def patch_templates() -> None:
|
|
55
55
|
from django.template.response import SimpleTemplateResponse
|
|
56
56
|
from sentry_sdk.integrations.django import DjangoIntegration
|
|
57
57
|
|
|
@@ -59,8 +59,7 @@ def patch_templates():
|
|
|
59
59
|
|
|
60
60
|
@property # type: ignore
|
|
61
61
|
@ensure_integration_enabled(DjangoIntegration, real_rendered_content.fget)
|
|
62
|
-
def rendered_content(self):
|
|
63
|
-
# type: (SimpleTemplateResponse) -> str
|
|
62
|
+
def rendered_content(self: SimpleTemplateResponse) -> str:
|
|
64
63
|
with sentry_sdk.start_span(
|
|
65
64
|
op=OP.TEMPLATE_RENDER,
|
|
66
65
|
name=_get_template_name_description(self.template_name),
|
|
@@ -80,8 +79,13 @@ def patch_templates():
|
|
|
80
79
|
|
|
81
80
|
@functools.wraps(real_render)
|
|
82
81
|
@ensure_integration_enabled(DjangoIntegration, real_render)
|
|
83
|
-
def render(
|
|
84
|
-
|
|
82
|
+
def render(
|
|
83
|
+
request: django.http.HttpRequest,
|
|
84
|
+
template_name: str,
|
|
85
|
+
context: Optional[Dict[str, Any]] = None,
|
|
86
|
+
*args: Any,
|
|
87
|
+
**kwargs: Any,
|
|
88
|
+
) -> django.http.HttpResponse:
|
|
85
89
|
|
|
86
90
|
# Inject trace meta tags into template context
|
|
87
91
|
context = context or {}
|
|
@@ -103,8 +107,7 @@ def patch_templates():
|
|
|
103
107
|
django.shortcuts.render = render
|
|
104
108
|
|
|
105
109
|
|
|
106
|
-
def _get_template_frame_from_debug(debug):
|
|
107
|
-
# type: (Dict[str, Any]) -> Dict[str, Any]
|
|
110
|
+
def _get_template_frame_from_debug(debug: Dict[str, Any]) -> Dict[str, Any]:
|
|
108
111
|
if debug is None:
|
|
109
112
|
return None
|
|
110
113
|
|
|
@@ -135,8 +138,7 @@ def _get_template_frame_from_debug(debug):
|
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
|
|
138
|
-
def _linebreak_iter(template_source):
|
|
139
|
-
# type: (str) -> Iterator[int]
|
|
141
|
+
def _linebreak_iter(template_source: str) -> Iterator[int]:
|
|
140
142
|
yield 0
|
|
141
143
|
p = template_source.find("\n")
|
|
142
144
|
while p >= 0:
|
|
@@ -144,8 +146,9 @@ def _linebreak_iter(template_source):
|
|
|
144
146
|
p = template_source.find("\n", p + 1)
|
|
145
147
|
|
|
146
148
|
|
|
147
|
-
def _get_template_frame_from_source(
|
|
148
|
-
|
|
149
|
+
def _get_template_frame_from_source(
|
|
150
|
+
source: Tuple[Origin, Tuple[int, int]],
|
|
151
|
+
) -> Optional[Dict[str, Any]]:
|
|
149
152
|
if not source:
|
|
150
153
|
return None
|
|
151
154
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
"""
|
|
2
4
|
Copied from raven-python.
|
|
3
5
|
|
|
@@ -27,8 +29,7 @@ except ImportError:
|
|
|
27
29
|
from django.core.urlresolvers import get_resolver
|
|
28
30
|
|
|
29
31
|
|
|
30
|
-
def get_regex(resolver_or_pattern):
|
|
31
|
-
# type: (Union[URLPattern, URLResolver]) -> Pattern[str]
|
|
32
|
+
def get_regex(resolver_or_pattern: Union[URLPattern, URLResolver]) -> Pattern[str]:
|
|
32
33
|
"""Utility method for django's deprecated resolver.regex"""
|
|
33
34
|
try:
|
|
34
35
|
regex = resolver_or_pattern.regex
|
|
@@ -48,10 +49,9 @@ class RavenResolver:
|
|
|
48
49
|
_either_option_matcher = re.compile(r"\[([^\]]+)\|([^\]]+)\]")
|
|
49
50
|
_camel_re = re.compile(r"([A-Z]+)([a-z])")
|
|
50
51
|
|
|
51
|
-
_cache
|
|
52
|
+
_cache: Dict[URLPattern, str] = {}
|
|
52
53
|
|
|
53
|
-
def _simplify(self, pattern):
|
|
54
|
-
# type: (Union[URLPattern, URLResolver]) -> str
|
|
54
|
+
def _simplify(self, pattern: Union[URLPattern, URLResolver]) -> str:
|
|
55
55
|
r"""
|
|
56
56
|
Clean up urlpattern regexes into something readable by humans:
|
|
57
57
|
|
|
@@ -102,8 +102,12 @@ class RavenResolver:
|
|
|
102
102
|
|
|
103
103
|
return result
|
|
104
104
|
|
|
105
|
-
def _resolve(
|
|
106
|
-
|
|
105
|
+
def _resolve(
|
|
106
|
+
self,
|
|
107
|
+
resolver: URLResolver,
|
|
108
|
+
path: str,
|
|
109
|
+
parents: Optional[List[URLResolver]] = None,
|
|
110
|
+
) -> Optional[str]:
|
|
107
111
|
|
|
108
112
|
match = get_regex(resolver).search(path) # Django < 2.0
|
|
109
113
|
|
|
@@ -142,10 +146,11 @@ class RavenResolver:
|
|
|
142
146
|
|
|
143
147
|
def resolve(
|
|
144
148
|
self,
|
|
145
|
-
path
|
|
146
|
-
urlconf
|
|
147
|
-
|
|
148
|
-
|
|
149
|
+
path: str,
|
|
150
|
+
urlconf: Union[
|
|
151
|
+
None, Tuple[URLPattern, URLPattern, URLResolver], Tuple[URLPattern]
|
|
152
|
+
] = None,
|
|
153
|
+
) -> Optional[str]:
|
|
149
154
|
resolver = get_resolver(urlconf)
|
|
150
155
|
match = self._resolve(resolver, path)
|
|
151
156
|
return match
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import functools
|
|
2
3
|
|
|
3
4
|
import sentry_sdk
|
|
@@ -21,8 +22,7 @@ except (ImportError, SyntaxError):
|
|
|
21
22
|
wrap_async_view = None # type: ignore
|
|
22
23
|
|
|
23
24
|
|
|
24
|
-
def patch_views():
|
|
25
|
-
# type: () -> None
|
|
25
|
+
def patch_views() -> None:
|
|
26
26
|
|
|
27
27
|
from django.core.handlers.base import BaseHandler
|
|
28
28
|
from django.template.response import SimpleTemplateResponse
|
|
@@ -32,8 +32,7 @@ def patch_views():
|
|
|
32
32
|
old_render = SimpleTemplateResponse.render
|
|
33
33
|
|
|
34
34
|
@functools.wraps(old_render)
|
|
35
|
-
def sentry_patched_render(self):
|
|
36
|
-
# type: (SimpleTemplateResponse) -> Any
|
|
35
|
+
def sentry_patched_render(self: SimpleTemplateResponse) -> Any:
|
|
37
36
|
with sentry_sdk.start_span(
|
|
38
37
|
op=OP.VIEW_RESPONSE_RENDER,
|
|
39
38
|
name="serialize response",
|
|
@@ -43,8 +42,7 @@ def patch_views():
|
|
|
43
42
|
return old_render(self)
|
|
44
43
|
|
|
45
44
|
@functools.wraps(old_make_view_atomic)
|
|
46
|
-
def sentry_patched_make_view_atomic(self, *args, **kwargs):
|
|
47
|
-
# type: (Any, *Any, **Any) -> Any
|
|
45
|
+
def sentry_patched_make_view_atomic(self: Any, *args: Any, **kwargs: Any) -> Any:
|
|
48
46
|
callback = old_make_view_atomic(self, *args, **kwargs)
|
|
49
47
|
|
|
50
48
|
# XXX: The wrapper function is created for every request. Find more
|
|
@@ -71,13 +69,11 @@ def patch_views():
|
|
|
71
69
|
BaseHandler.make_view_atomic = sentry_patched_make_view_atomic
|
|
72
70
|
|
|
73
71
|
|
|
74
|
-
def _wrap_sync_view(callback):
|
|
75
|
-
# type: (Any) -> Any
|
|
72
|
+
def _wrap_sync_view(callback: Any) -> Any:
|
|
76
73
|
from sentry_sdk.integrations.django import DjangoIntegration
|
|
77
74
|
|
|
78
75
|
@functools.wraps(callback)
|
|
79
|
-
def sentry_wrapped_callback(request, *args, **kwargs):
|
|
80
|
-
# type: (Any, *Any, **Any) -> Any
|
|
76
|
+
def sentry_wrapped_callback(request: Any, *args: Any, **kwargs: Any) -> Any:
|
|
81
77
|
current_scope = sentry_sdk.get_current_scope()
|
|
82
78
|
if current_scope.root_span is not None:
|
|
83
79
|
current_scope.root_span.update_active_thread()
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import json
|
|
2
3
|
|
|
3
4
|
import sentry_sdk
|
|
@@ -36,17 +37,14 @@ class DramatiqIntegration(Integration):
|
|
|
36
37
|
identifier = "dramatiq"
|
|
37
38
|
|
|
38
39
|
@staticmethod
|
|
39
|
-
def setup_once():
|
|
40
|
-
# type: () -> None
|
|
40
|
+
def setup_once() -> None:
|
|
41
41
|
_patch_dramatiq_broker()
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
def _patch_dramatiq_broker():
|
|
45
|
-
# type: () -> None
|
|
44
|
+
def _patch_dramatiq_broker() -> None:
|
|
46
45
|
original_broker__init__ = Broker.__init__
|
|
47
46
|
|
|
48
|
-
def sentry_patched_broker__init__(self, *args, **kw):
|
|
49
|
-
# type: (Broker, *Any, **Any) -> None
|
|
47
|
+
def sentry_patched_broker__init__(self: Broker, *args: Any, **kw: Any) -> None:
|
|
50
48
|
integration = sentry_sdk.get_client().get_integration(DramatiqIntegration)
|
|
51
49
|
|
|
52
50
|
try:
|
|
@@ -85,8 +83,7 @@ class SentryMiddleware(Middleware): # type: ignore[misc]
|
|
|
85
83
|
DramatiqIntegration.
|
|
86
84
|
"""
|
|
87
85
|
|
|
88
|
-
def before_process_message(self, broker, message):
|
|
89
|
-
# type: (Broker, Message) -> None
|
|
86
|
+
def before_process_message(self, broker: Broker, message: Message) -> None:
|
|
90
87
|
integration = sentry_sdk.get_client().get_integration(DramatiqIntegration)
|
|
91
88
|
if integration is None:
|
|
92
89
|
return
|
|
@@ -99,8 +96,14 @@ class SentryMiddleware(Middleware): # type: ignore[misc]
|
|
|
99
96
|
scope.set_extra("dramatiq_message_id", message.message_id)
|
|
100
97
|
scope.add_event_processor(_make_message_event_processor(message, integration))
|
|
101
98
|
|
|
102
|
-
def after_process_message(
|
|
103
|
-
|
|
99
|
+
def after_process_message(
|
|
100
|
+
self: Broker,
|
|
101
|
+
broker: Message,
|
|
102
|
+
message: Any,
|
|
103
|
+
*,
|
|
104
|
+
result: Optional[Any] = None,
|
|
105
|
+
exception: Optional[Exception] = None,
|
|
106
|
+
) -> None:
|
|
104
107
|
integration = sentry_sdk.get_client().get_integration(DramatiqIntegration)
|
|
105
108
|
if integration is None:
|
|
106
109
|
return
|
|
@@ -127,11 +130,11 @@ class SentryMiddleware(Middleware): # type: ignore[misc]
|
|
|
127
130
|
message._scope_manager.__exit__(None, None, None)
|
|
128
131
|
|
|
129
132
|
|
|
130
|
-
def _make_message_event_processor(
|
|
131
|
-
|
|
133
|
+
def _make_message_event_processor(
|
|
134
|
+
message: Message, integration: DramatiqIntegration
|
|
135
|
+
) -> Callable[[Event, Hint], Optional[Event]]:
|
|
132
136
|
|
|
133
|
-
def inner(event, hint):
|
|
134
|
-
# type: (Event, Hint) -> Optional[Event]
|
|
137
|
+
def inner(event: Event, hint: Hint) -> Optional[Event]:
|
|
135
138
|
with capture_internal_exceptions():
|
|
136
139
|
DramatiqMessageExtractor(message).extract_into_event(event)
|
|
137
140
|
|
|
@@ -141,16 +144,13 @@ def _make_message_event_processor(message, integration):
|
|
|
141
144
|
|
|
142
145
|
|
|
143
146
|
class DramatiqMessageExtractor:
|
|
144
|
-
def __init__(self, message):
|
|
145
|
-
# type: (Message) -> None
|
|
147
|
+
def __init__(self, message: Message) -> None:
|
|
146
148
|
self.message_data = dict(message.asdict())
|
|
147
149
|
|
|
148
|
-
def content_length(self):
|
|
149
|
-
# type: () -> int
|
|
150
|
+
def content_length(self) -> int:
|
|
150
151
|
return len(json.dumps(self.message_data))
|
|
151
152
|
|
|
152
|
-
def extract_into_event(self, event):
|
|
153
|
-
# type: (Event) -> None
|
|
153
|
+
def extract_into_event(self, event: Event) -> None:
|
|
154
154
|
client = sentry_sdk.get_client()
|
|
155
155
|
if not client.is_active():
|
|
156
156
|
return
|
|
@@ -159,7 +159,7 @@ class DramatiqMessageExtractor:
|
|
|
159
159
|
request_info = contexts.setdefault("dramatiq", {})
|
|
160
160
|
request_info["type"] = "dramatiq"
|
|
161
161
|
|
|
162
|
-
data
|
|
162
|
+
data: Optional[Union[AnnotatedValue, Dict[str, Any]]] = None
|
|
163
163
|
if not request_body_within_bounds(client, self.content_length()):
|
|
164
164
|
data = AnnotatedValue.removed_because_over_size_limit()
|
|
165
165
|
else:
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import sys
|
|
2
3
|
|
|
3
4
|
import sentry_sdk
|
|
@@ -28,8 +29,7 @@ class ExcepthookIntegration(Integration):
|
|
|
28
29
|
|
|
29
30
|
always_run = False
|
|
30
31
|
|
|
31
|
-
def __init__(self, always_run=False):
|
|
32
|
-
# type: (bool) -> None
|
|
32
|
+
def __init__(self, always_run: bool = False) -> None:
|
|
33
33
|
|
|
34
34
|
if not isinstance(always_run, bool):
|
|
35
35
|
raise ValueError(
|
|
@@ -39,15 +39,16 @@ class ExcepthookIntegration(Integration):
|
|
|
39
39
|
self.always_run = always_run
|
|
40
40
|
|
|
41
41
|
@staticmethod
|
|
42
|
-
def setup_once():
|
|
43
|
-
# type: () -> None
|
|
42
|
+
def setup_once() -> None:
|
|
44
43
|
sys.excepthook = _make_excepthook(sys.excepthook)
|
|
45
44
|
|
|
46
45
|
|
|
47
|
-
def _make_excepthook(old_excepthook):
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
def _make_excepthook(old_excepthook: Excepthook) -> Excepthook:
|
|
47
|
+
def sentry_sdk_excepthook(
|
|
48
|
+
type_: Type[BaseException],
|
|
49
|
+
value: BaseException,
|
|
50
|
+
traceback: Optional[TracebackType],
|
|
51
|
+
) -> None:
|
|
51
52
|
integration = sentry_sdk.get_client().get_integration(ExcepthookIntegration)
|
|
52
53
|
|
|
53
54
|
# Note: If we replace this with ensure_integration_enabled then
|
|
@@ -70,8 +71,7 @@ def _make_excepthook(old_excepthook):
|
|
|
70
71
|
return sentry_sdk_excepthook
|
|
71
72
|
|
|
72
73
|
|
|
73
|
-
def _should_send(always_run=False):
|
|
74
|
-
# type: (bool) -> bool
|
|
74
|
+
def _should_send(always_run: bool = False) -> bool:
|
|
75
75
|
if always_run:
|
|
76
76
|
return True
|
|
77
77
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import sentry_sdk
|
|
2
3
|
from sentry_sdk.integrations import Integration, DidNotEnable
|
|
3
4
|
from sentry_sdk.scope import add_global_event_processor
|
|
@@ -20,12 +21,10 @@ class ExecutingIntegration(Integration):
|
|
|
20
21
|
identifier = "executing"
|
|
21
22
|
|
|
22
23
|
@staticmethod
|
|
23
|
-
def setup_once():
|
|
24
|
-
# type: () -> None
|
|
24
|
+
def setup_once() -> None:
|
|
25
25
|
|
|
26
26
|
@add_global_event_processor
|
|
27
|
-
def add_executing_info(event, hint):
|
|
28
|
-
# type: (Event, Optional[Hint]) -> Optional[Event]
|
|
27
|
+
def add_executing_info(event: Event, hint: Optional[Hint]) -> Optional[Event]:
|
|
29
28
|
if sentry_sdk.get_client().get_integration(ExecutingIntegration) is None:
|
|
30
29
|
return event
|
|
31
30
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import sentry_sdk
|
|
2
3
|
from sentry_sdk.consts import SOURCE_FOR_STYLE
|
|
3
4
|
from sentry_sdk.integrations import _check_minimum_version, Integration, DidNotEnable
|
|
@@ -33,30 +34,25 @@ falcon_helpers = falcon.app_helpers
|
|
|
33
34
|
falcon_app_class = falcon.App
|
|
34
35
|
|
|
35
36
|
|
|
36
|
-
_FALCON_UNSET
|
|
37
|
+
_FALCON_UNSET: Optional[object] = None
|
|
37
38
|
with capture_internal_exceptions():
|
|
38
39
|
from falcon.request import _UNSET as _FALCON_UNSET # type: ignore[import-not-found, no-redef]
|
|
39
40
|
|
|
40
41
|
|
|
41
42
|
class FalconRequestExtractor(RequestExtractor):
|
|
42
|
-
def env(self):
|
|
43
|
-
# type: () -> Dict[str, Any]
|
|
43
|
+
def env(self) -> Dict[str, Any]:
|
|
44
44
|
return self.request.env
|
|
45
45
|
|
|
46
|
-
def cookies(self):
|
|
47
|
-
# type: () -> Dict[str, Any]
|
|
46
|
+
def cookies(self) -> Dict[str, Any]:
|
|
48
47
|
return self.request.cookies
|
|
49
48
|
|
|
50
|
-
def form(self):
|
|
51
|
-
# type: () -> None
|
|
49
|
+
def form(self) -> None:
|
|
52
50
|
return None # No such concept in Falcon
|
|
53
51
|
|
|
54
|
-
def files(self):
|
|
55
|
-
# type: () -> None
|
|
52
|
+
def files(self) -> None:
|
|
56
53
|
return None # No such concept in Falcon
|
|
57
54
|
|
|
58
|
-
def raw_data(self):
|
|
59
|
-
# type: () -> Optional[str]
|
|
55
|
+
def raw_data(self) -> Optional[str]:
|
|
60
56
|
|
|
61
57
|
# As request data can only be read once we won't make this available
|
|
62
58
|
# to Sentry. Just send back a dummy string in case there was a
|
|
@@ -68,8 +64,7 @@ class FalconRequestExtractor(RequestExtractor):
|
|
|
68
64
|
else:
|
|
69
65
|
return None
|
|
70
66
|
|
|
71
|
-
def json(self):
|
|
72
|
-
# type: () -> Optional[Dict[str, Any]]
|
|
67
|
+
def json(self) -> Optional[Dict[str, Any]]:
|
|
73
68
|
# fallback to cached_media = None if self.request._media is not available
|
|
74
69
|
cached_media = None
|
|
75
70
|
with capture_internal_exceptions():
|
|
@@ -90,8 +85,7 @@ class FalconRequestExtractor(RequestExtractor):
|
|
|
90
85
|
class SentryFalconMiddleware:
|
|
91
86
|
"""Captures exceptions in Falcon requests and send to Sentry"""
|
|
92
87
|
|
|
93
|
-
def process_request(self, req, resp, *args, **kwargs):
|
|
94
|
-
# type: (Any, Any, *Any, **Any) -> None
|
|
88
|
+
def process_request(self, req: Any, resp: Any, *args: Any, **kwargs: Any) -> None:
|
|
95
89
|
integration = sentry_sdk.get_client().get_integration(FalconIntegration)
|
|
96
90
|
if integration is None:
|
|
97
91
|
return
|
|
@@ -110,8 +104,7 @@ class FalconIntegration(Integration):
|
|
|
110
104
|
|
|
111
105
|
transaction_style = ""
|
|
112
106
|
|
|
113
|
-
def __init__(self, transaction_style="uri_template"):
|
|
114
|
-
# type: (str) -> None
|
|
107
|
+
def __init__(self, transaction_style: str = "uri_template") -> None:
|
|
115
108
|
if transaction_style not in TRANSACTION_STYLE_VALUES:
|
|
116
109
|
raise ValueError(
|
|
117
110
|
"Invalid value for transaction_style: %s (must be in %s)"
|
|
@@ -120,8 +113,7 @@ class FalconIntegration(Integration):
|
|
|
120
113
|
self.transaction_style = transaction_style
|
|
121
114
|
|
|
122
115
|
@staticmethod
|
|
123
|
-
def setup_once():
|
|
124
|
-
# type: () -> None
|
|
116
|
+
def setup_once() -> None:
|
|
125
117
|
|
|
126
118
|
version = parse_version(FALCON_VERSION)
|
|
127
119
|
_check_minimum_version(FalconIntegration, version)
|
|
@@ -131,12 +123,10 @@ class FalconIntegration(Integration):
|
|
|
131
123
|
_patch_prepare_middleware()
|
|
132
124
|
|
|
133
125
|
|
|
134
|
-
def _patch_wsgi_app():
|
|
135
|
-
# type: () -> None
|
|
126
|
+
def _patch_wsgi_app() -> None:
|
|
136
127
|
original_wsgi_app = falcon_app_class.__call__
|
|
137
128
|
|
|
138
|
-
def sentry_patched_wsgi_app(self, env, start_response):
|
|
139
|
-
# type: (falcon.API, Any, Any) -> Any
|
|
129
|
+
def sentry_patched_wsgi_app(self: falcon.API, env: Any, start_response: Any) -> Any:
|
|
140
130
|
integration = sentry_sdk.get_client().get_integration(FalconIntegration)
|
|
141
131
|
if integration is None:
|
|
142
132
|
return original_wsgi_app(self, env, start_response)
|
|
@@ -151,13 +141,11 @@ def _patch_wsgi_app():
|
|
|
151
141
|
falcon_app_class.__call__ = sentry_patched_wsgi_app
|
|
152
142
|
|
|
153
143
|
|
|
154
|
-
def _patch_handle_exception():
|
|
155
|
-
# type: () -> None
|
|
144
|
+
def _patch_handle_exception() -> None:
|
|
156
145
|
original_handle_exception = falcon_app_class._handle_exception
|
|
157
146
|
|
|
158
147
|
@ensure_integration_enabled(FalconIntegration, original_handle_exception)
|
|
159
|
-
def sentry_patched_handle_exception(self, *args):
|
|
160
|
-
# type: (falcon.API, *Any) -> Any
|
|
148
|
+
def sentry_patched_handle_exception(self: falcon.API, *args: Any) -> Any:
|
|
161
149
|
# NOTE(jmagnusson): falcon 2.0 changed falcon.API._handle_exception
|
|
162
150
|
# method signature from `(ex, req, resp, params)` to
|
|
163
151
|
# `(req, resp, ex, params)`
|
|
@@ -189,14 +177,12 @@ def _patch_handle_exception():
|
|
|
189
177
|
falcon_app_class._handle_exception = sentry_patched_handle_exception
|
|
190
178
|
|
|
191
179
|
|
|
192
|
-
def _patch_prepare_middleware():
|
|
193
|
-
# type: () -> None
|
|
180
|
+
def _patch_prepare_middleware() -> None:
|
|
194
181
|
original_prepare_middleware = falcon_helpers.prepare_middleware
|
|
195
182
|
|
|
196
183
|
def sentry_patched_prepare_middleware(
|
|
197
|
-
middleware=None, independent_middleware=False, asgi=False
|
|
198
|
-
):
|
|
199
|
-
# type: (Any, Any, bool) -> Any
|
|
184
|
+
middleware: Any = None, independent_middleware: Any = False, asgi: bool = False
|
|
185
|
+
) -> Any:
|
|
200
186
|
if asgi:
|
|
201
187
|
# We don't support ASGI Falcon apps, so we don't patch anything here
|
|
202
188
|
return original_prepare_middleware(middleware, independent_middleware, asgi)
|
|
@@ -212,8 +198,7 @@ def _patch_prepare_middleware():
|
|
|
212
198
|
falcon_helpers.prepare_middleware = sentry_patched_prepare_middleware
|
|
213
199
|
|
|
214
200
|
|
|
215
|
-
def _exception_leads_to_http_5xx(ex, response):
|
|
216
|
-
# type: (Exception, falcon.Response) -> bool
|
|
201
|
+
def _exception_leads_to_http_5xx(ex: Exception, response: falcon.Response) -> bool:
|
|
217
202
|
is_server_error = isinstance(ex, falcon.HTTPError) and (ex.status or "").startswith(
|
|
218
203
|
"5"
|
|
219
204
|
)
|
|
@@ -224,13 +209,13 @@ def _exception_leads_to_http_5xx(ex, response):
|
|
|
224
209
|
return (is_server_error or is_unhandled_error) and _has_http_5xx_status(response)
|
|
225
210
|
|
|
226
211
|
|
|
227
|
-
def _has_http_5xx_status(response):
|
|
228
|
-
# type: (falcon.Response) -> bool
|
|
212
|
+
def _has_http_5xx_status(response: falcon.Response) -> bool:
|
|
229
213
|
return response.status.startswith("5")
|
|
230
214
|
|
|
231
215
|
|
|
232
|
-
def _set_transaction_name_and_source(
|
|
233
|
-
|
|
216
|
+
def _set_transaction_name_and_source(
|
|
217
|
+
event: Event, transaction_style: str, request: falcon.Request
|
|
218
|
+
) -> None:
|
|
234
219
|
name_for_style = {
|
|
235
220
|
"uri_template": request.uri_template,
|
|
236
221
|
"path": request.path,
|
|
@@ -239,11 +224,11 @@ def _set_transaction_name_and_source(event, transaction_style, request):
|
|
|
239
224
|
event["transaction_info"] = {"source": SOURCE_FOR_STYLE[transaction_style]}
|
|
240
225
|
|
|
241
226
|
|
|
242
|
-
def _make_request_event_processor(
|
|
243
|
-
|
|
227
|
+
def _make_request_event_processor(
|
|
228
|
+
req: falcon.Request, integration: FalconIntegration
|
|
229
|
+
) -> EventProcessor:
|
|
244
230
|
|
|
245
|
-
def event_processor(event, hint):
|
|
246
|
-
# type: (Event, dict[str, Any]) -> Event
|
|
231
|
+
def event_processor(event: Event, hint: dict[str, Any]) -> Event:
|
|
247
232
|
_set_transaction_name_and_source(event, integration.transaction_style, req)
|
|
248
233
|
|
|
249
234
|
with capture_internal_exceptions():
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
1
2
|
import asyncio
|
|
2
3
|
from copy import deepcopy
|
|
3
4
|
from functools import wraps
|
|
@@ -38,13 +39,13 @@ class FastApiIntegration(StarletteIntegration):
|
|
|
38
39
|
identifier = "fastapi"
|
|
39
40
|
|
|
40
41
|
@staticmethod
|
|
41
|
-
def setup_once():
|
|
42
|
-
# type: () -> None
|
|
42
|
+
def setup_once() -> None:
|
|
43
43
|
patch_get_request_handler()
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
def _set_transaction_name_and_source(
|
|
47
|
-
|
|
46
|
+
def _set_transaction_name_and_source(
|
|
47
|
+
scope: sentry_sdk.Scope, transaction_style: str, request: Any
|
|
48
|
+
) -> None:
|
|
48
49
|
name = ""
|
|
49
50
|
|
|
50
51
|
if transaction_style == "endpoint":
|
|
@@ -71,12 +72,10 @@ def _set_transaction_name_and_source(scope, transaction_style, request):
|
|
|
71
72
|
)
|
|
72
73
|
|
|
73
74
|
|
|
74
|
-
def patch_get_request_handler():
|
|
75
|
-
# type: () -> None
|
|
75
|
+
def patch_get_request_handler() -> None:
|
|
76
76
|
old_get_request_handler = fastapi.routing.get_request_handler
|
|
77
77
|
|
|
78
|
-
def _sentry_get_request_handler(*args, **kwargs):
|
|
79
|
-
# type: (*Any, **Any) -> Any
|
|
78
|
+
def _sentry_get_request_handler(*args: Any, **kwargs: Any) -> Any:
|
|
80
79
|
dependant = kwargs.get("dependant")
|
|
81
80
|
if (
|
|
82
81
|
dependant
|
|
@@ -86,8 +85,7 @@ def patch_get_request_handler():
|
|
|
86
85
|
old_call = dependant.call
|
|
87
86
|
|
|
88
87
|
@wraps(old_call)
|
|
89
|
-
def _sentry_call(*args, **kwargs):
|
|
90
|
-
# type: (*Any, **Any) -> Any
|
|
88
|
+
def _sentry_call(*args: Any, **kwargs: Any) -> Any:
|
|
91
89
|
current_scope = sentry_sdk.get_current_scope()
|
|
92
90
|
if current_scope.root_span is not None:
|
|
93
91
|
current_scope.root_span.update_active_thread()
|
|
@@ -102,8 +100,7 @@ def patch_get_request_handler():
|
|
|
102
100
|
|
|
103
101
|
old_app = old_get_request_handler(*args, **kwargs)
|
|
104
102
|
|
|
105
|
-
async def _sentry_app(*args, **kwargs):
|
|
106
|
-
# type: (*Any, **Any) -> Any
|
|
103
|
+
async def _sentry_app(*args: Any, **kwargs: Any) -> Any:
|
|
107
104
|
integration = sentry_sdk.get_client().get_integration(FastApiIntegration)
|
|
108
105
|
if integration is None:
|
|
109
106
|
return await old_app(*args, **kwargs)
|
|
@@ -117,10 +114,10 @@ def patch_get_request_handler():
|
|
|
117
114
|
extractor = StarletteRequestExtractor(request)
|
|
118
115
|
info = await extractor.extract_request_info()
|
|
119
116
|
|
|
120
|
-
def _make_request_event_processor(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
117
|
+
def _make_request_event_processor(
|
|
118
|
+
req: Any, integration: Any
|
|
119
|
+
) -> Callable[[Event, Dict[str, Any]], Event]:
|
|
120
|
+
def event_processor(event: Event, hint: Dict[str, Any]) -> Event:
|
|
124
121
|
|
|
125
122
|
# Extract information from request
|
|
126
123
|
request_info = event.get("request", {})
|