sentry-sdk 0.18.0__py2.py3-none-any.whl → 2.46.0__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.
- sentry_sdk/__init__.py +48 -6
- sentry_sdk/_compat.py +64 -56
- sentry_sdk/_init_implementation.py +84 -0
- sentry_sdk/_log_batcher.py +172 -0
- sentry_sdk/_lru_cache.py +47 -0
- sentry_sdk/_metrics_batcher.py +167 -0
- sentry_sdk/_queue.py +81 -19
- sentry_sdk/_types.py +311 -11
- sentry_sdk/_werkzeug.py +98 -0
- sentry_sdk/ai/__init__.py +7 -0
- sentry_sdk/ai/monitoring.py +137 -0
- sentry_sdk/ai/utils.py +144 -0
- sentry_sdk/api.py +409 -67
- sentry_sdk/attachments.py +75 -0
- sentry_sdk/client.py +849 -103
- sentry_sdk/consts.py +1389 -34
- sentry_sdk/crons/__init__.py +10 -0
- sentry_sdk/crons/api.py +62 -0
- sentry_sdk/crons/consts.py +4 -0
- sentry_sdk/crons/decorator.py +135 -0
- sentry_sdk/debug.py +12 -15
- sentry_sdk/envelope.py +112 -61
- sentry_sdk/feature_flags.py +71 -0
- sentry_sdk/hub.py +442 -386
- sentry_sdk/integrations/__init__.py +228 -58
- sentry_sdk/integrations/_asgi_common.py +108 -0
- sentry_sdk/integrations/_wsgi_common.py +131 -40
- sentry_sdk/integrations/aiohttp.py +221 -72
- sentry_sdk/integrations/anthropic.py +439 -0
- sentry_sdk/integrations/argv.py +4 -6
- sentry_sdk/integrations/ariadne.py +161 -0
- sentry_sdk/integrations/arq.py +247 -0
- sentry_sdk/integrations/asgi.py +237 -135
- sentry_sdk/integrations/asyncio.py +144 -0
- sentry_sdk/integrations/asyncpg.py +208 -0
- sentry_sdk/integrations/atexit.py +13 -18
- sentry_sdk/integrations/aws_lambda.py +233 -80
- sentry_sdk/integrations/beam.py +27 -35
- sentry_sdk/integrations/boto3.py +137 -0
- sentry_sdk/integrations/bottle.py +91 -69
- sentry_sdk/integrations/celery/__init__.py +529 -0
- sentry_sdk/integrations/celery/beat.py +293 -0
- sentry_sdk/integrations/celery/utils.py +43 -0
- sentry_sdk/integrations/chalice.py +35 -28
- sentry_sdk/integrations/clickhouse_driver.py +177 -0
- sentry_sdk/integrations/cloud_resource_context.py +280 -0
- sentry_sdk/integrations/cohere.py +274 -0
- sentry_sdk/integrations/dedupe.py +32 -8
- sentry_sdk/integrations/django/__init__.py +343 -89
- sentry_sdk/integrations/django/asgi.py +201 -22
- sentry_sdk/integrations/django/caching.py +204 -0
- sentry_sdk/integrations/django/middleware.py +80 -32
- sentry_sdk/integrations/django/signals_handlers.py +91 -0
- sentry_sdk/integrations/django/templates.py +69 -2
- sentry_sdk/integrations/django/transactions.py +39 -14
- sentry_sdk/integrations/django/views.py +69 -16
- sentry_sdk/integrations/dramatiq.py +226 -0
- sentry_sdk/integrations/excepthook.py +19 -13
- sentry_sdk/integrations/executing.py +5 -6
- sentry_sdk/integrations/falcon.py +128 -65
- sentry_sdk/integrations/fastapi.py +141 -0
- sentry_sdk/integrations/flask.py +114 -75
- sentry_sdk/integrations/gcp.py +67 -36
- sentry_sdk/integrations/gnu_backtrace.py +14 -22
- sentry_sdk/integrations/google_genai/__init__.py +301 -0
- sentry_sdk/integrations/google_genai/consts.py +16 -0
- sentry_sdk/integrations/google_genai/streaming.py +155 -0
- sentry_sdk/integrations/google_genai/utils.py +576 -0
- sentry_sdk/integrations/gql.py +162 -0
- sentry_sdk/integrations/graphene.py +151 -0
- sentry_sdk/integrations/grpc/__init__.py +168 -0
- sentry_sdk/integrations/grpc/aio/__init__.py +7 -0
- sentry_sdk/integrations/grpc/aio/client.py +95 -0
- sentry_sdk/integrations/grpc/aio/server.py +100 -0
- sentry_sdk/integrations/grpc/client.py +91 -0
- sentry_sdk/integrations/grpc/consts.py +1 -0
- sentry_sdk/integrations/grpc/server.py +66 -0
- sentry_sdk/integrations/httpx.py +178 -0
- sentry_sdk/integrations/huey.py +174 -0
- sentry_sdk/integrations/huggingface_hub.py +378 -0
- sentry_sdk/integrations/langchain.py +1132 -0
- sentry_sdk/integrations/langgraph.py +337 -0
- sentry_sdk/integrations/launchdarkly.py +61 -0
- sentry_sdk/integrations/litellm.py +287 -0
- sentry_sdk/integrations/litestar.py +315 -0
- sentry_sdk/integrations/logging.py +261 -85
- sentry_sdk/integrations/loguru.py +213 -0
- sentry_sdk/integrations/mcp.py +566 -0
- sentry_sdk/integrations/modules.py +6 -33
- sentry_sdk/integrations/openai.py +725 -0
- sentry_sdk/integrations/openai_agents/__init__.py +61 -0
- sentry_sdk/integrations/openai_agents/consts.py +1 -0
- sentry_sdk/integrations/openai_agents/patches/__init__.py +5 -0
- sentry_sdk/integrations/openai_agents/patches/agent_run.py +140 -0
- sentry_sdk/integrations/openai_agents/patches/error_tracing.py +77 -0
- sentry_sdk/integrations/openai_agents/patches/models.py +50 -0
- sentry_sdk/integrations/openai_agents/patches/runner.py +45 -0
- sentry_sdk/integrations/openai_agents/patches/tools.py +77 -0
- sentry_sdk/integrations/openai_agents/spans/__init__.py +5 -0
- sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +21 -0
- sentry_sdk/integrations/openai_agents/spans/ai_client.py +42 -0
- sentry_sdk/integrations/openai_agents/spans/execute_tool.py +48 -0
- sentry_sdk/integrations/openai_agents/spans/handoff.py +19 -0
- sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +86 -0
- sentry_sdk/integrations/openai_agents/utils.py +199 -0
- sentry_sdk/integrations/openfeature.py +35 -0
- sentry_sdk/integrations/opentelemetry/__init__.py +7 -0
- sentry_sdk/integrations/opentelemetry/consts.py +5 -0
- sentry_sdk/integrations/opentelemetry/integration.py +58 -0
- sentry_sdk/integrations/opentelemetry/propagator.py +117 -0
- sentry_sdk/integrations/opentelemetry/span_processor.py +391 -0
- sentry_sdk/integrations/otlp.py +82 -0
- sentry_sdk/integrations/pure_eval.py +20 -11
- sentry_sdk/integrations/pydantic_ai/__init__.py +47 -0
- sentry_sdk/integrations/pydantic_ai/consts.py +1 -0
- sentry_sdk/integrations/pydantic_ai/patches/__init__.py +4 -0
- sentry_sdk/integrations/pydantic_ai/patches/agent_run.py +215 -0
- sentry_sdk/integrations/pydantic_ai/patches/graph_nodes.py +110 -0
- sentry_sdk/integrations/pydantic_ai/patches/model_request.py +40 -0
- sentry_sdk/integrations/pydantic_ai/patches/tools.py +98 -0
- sentry_sdk/integrations/pydantic_ai/spans/__init__.py +3 -0
- sentry_sdk/integrations/pydantic_ai/spans/ai_client.py +246 -0
- sentry_sdk/integrations/pydantic_ai/spans/execute_tool.py +49 -0
- sentry_sdk/integrations/pydantic_ai/spans/invoke_agent.py +112 -0
- sentry_sdk/integrations/pydantic_ai/utils.py +223 -0
- sentry_sdk/integrations/pymongo.py +214 -0
- sentry_sdk/integrations/pyramid.py +71 -60
- sentry_sdk/integrations/quart.py +237 -0
- sentry_sdk/integrations/ray.py +165 -0
- sentry_sdk/integrations/redis/__init__.py +48 -0
- sentry_sdk/integrations/redis/_async_common.py +116 -0
- sentry_sdk/integrations/redis/_sync_common.py +119 -0
- sentry_sdk/integrations/redis/consts.py +19 -0
- sentry_sdk/integrations/redis/modules/__init__.py +0 -0
- sentry_sdk/integrations/redis/modules/caches.py +118 -0
- sentry_sdk/integrations/redis/modules/queries.py +65 -0
- sentry_sdk/integrations/redis/rb.py +32 -0
- sentry_sdk/integrations/redis/redis.py +69 -0
- sentry_sdk/integrations/redis/redis_cluster.py +107 -0
- sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +50 -0
- sentry_sdk/integrations/redis/utils.py +148 -0
- sentry_sdk/integrations/rq.py +62 -52
- sentry_sdk/integrations/rust_tracing.py +284 -0
- sentry_sdk/integrations/sanic.py +248 -114
- sentry_sdk/integrations/serverless.py +13 -22
- sentry_sdk/integrations/socket.py +96 -0
- sentry_sdk/integrations/spark/spark_driver.py +115 -62
- sentry_sdk/integrations/spark/spark_worker.py +42 -50
- sentry_sdk/integrations/sqlalchemy.py +82 -37
- sentry_sdk/integrations/starlette.py +737 -0
- sentry_sdk/integrations/starlite.py +292 -0
- sentry_sdk/integrations/statsig.py +37 -0
- sentry_sdk/integrations/stdlib.py +100 -58
- sentry_sdk/integrations/strawberry.py +394 -0
- sentry_sdk/integrations/sys_exit.py +70 -0
- sentry_sdk/integrations/threading.py +142 -38
- sentry_sdk/integrations/tornado.py +68 -53
- sentry_sdk/integrations/trytond.py +15 -20
- sentry_sdk/integrations/typer.py +60 -0
- sentry_sdk/integrations/unleash.py +33 -0
- sentry_sdk/integrations/unraisablehook.py +53 -0
- sentry_sdk/integrations/wsgi.py +126 -125
- sentry_sdk/logger.py +96 -0
- sentry_sdk/metrics.py +81 -0
- sentry_sdk/monitor.py +120 -0
- sentry_sdk/profiler/__init__.py +49 -0
- sentry_sdk/profiler/continuous_profiler.py +730 -0
- sentry_sdk/profiler/transaction_profiler.py +839 -0
- sentry_sdk/profiler/utils.py +195 -0
- sentry_sdk/scope.py +1542 -112
- sentry_sdk/scrubber.py +177 -0
- sentry_sdk/serializer.py +152 -210
- sentry_sdk/session.py +177 -0
- sentry_sdk/sessions.py +202 -179
- sentry_sdk/spotlight.py +242 -0
- sentry_sdk/tracing.py +1202 -294
- sentry_sdk/tracing_utils.py +1236 -0
- sentry_sdk/transport.py +693 -189
- sentry_sdk/types.py +52 -0
- sentry_sdk/utils.py +1395 -228
- sentry_sdk/worker.py +30 -17
- sentry_sdk-2.46.0.dist-info/METADATA +268 -0
- sentry_sdk-2.46.0.dist-info/RECORD +189 -0
- {sentry_sdk-0.18.0.dist-info → sentry_sdk-2.46.0.dist-info}/WHEEL +1 -1
- sentry_sdk-2.46.0.dist-info/entry_points.txt +2 -0
- sentry_sdk-2.46.0.dist-info/licenses/LICENSE +21 -0
- sentry_sdk/_functools.py +0 -66
- sentry_sdk/integrations/celery.py +0 -275
- sentry_sdk/integrations/redis.py +0 -103
- sentry_sdk-0.18.0.dist-info/LICENSE +0 -9
- sentry_sdk-0.18.0.dist-info/METADATA +0 -66
- sentry_sdk-0.18.0.dist-info/RECORD +0 -65
- {sentry_sdk-0.18.0.dist-info → sentry_sdk-2.46.0.dist-info}/top_level.txt +0 -0
|
@@ -1,49 +1,55 @@
|
|
|
1
1
|
import weakref
|
|
2
|
+
import contextlib
|
|
2
3
|
from inspect import iscoroutinefunction
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
import sentry_sdk
|
|
6
|
+
from sentry_sdk.api import continue_trace
|
|
7
|
+
from sentry_sdk.consts import OP
|
|
8
|
+
from sentry_sdk.scope import should_send_default_pii
|
|
9
|
+
from sentry_sdk.tracing import TransactionSource
|
|
5
10
|
from sentry_sdk.utils import (
|
|
6
11
|
HAS_REAL_CONTEXTVARS,
|
|
7
12
|
CONTEXTVARS_ERROR_MESSAGE,
|
|
13
|
+
ensure_integration_enabled,
|
|
8
14
|
event_from_exception,
|
|
9
15
|
capture_internal_exceptions,
|
|
10
16
|
transaction_from_function,
|
|
11
17
|
)
|
|
12
|
-
from sentry_sdk.integrations import Integration, DidNotEnable
|
|
18
|
+
from sentry_sdk.integrations import _check_minimum_version, Integration, DidNotEnable
|
|
13
19
|
from sentry_sdk.integrations._wsgi_common import (
|
|
14
20
|
RequestExtractor,
|
|
15
21
|
_filter_headers,
|
|
16
22
|
_is_json_content_type,
|
|
17
23
|
)
|
|
18
24
|
from sentry_sdk.integrations.logging import ignore_logger
|
|
19
|
-
from sentry_sdk._compat import iteritems
|
|
20
25
|
|
|
21
26
|
try:
|
|
22
|
-
from tornado import version_info as TORNADO_VERSION
|
|
27
|
+
from tornado import version_info as TORNADO_VERSION
|
|
23
28
|
from tornado.web import RequestHandler, HTTPError
|
|
24
29
|
from tornado.gen import coroutine
|
|
25
30
|
except ImportError:
|
|
26
31
|
raise DidNotEnable("Tornado not installed")
|
|
27
32
|
|
|
28
|
-
from
|
|
33
|
+
from typing import TYPE_CHECKING
|
|
29
34
|
|
|
30
|
-
if
|
|
35
|
+
if TYPE_CHECKING:
|
|
31
36
|
from typing import Any
|
|
32
37
|
from typing import Optional
|
|
33
38
|
from typing import Dict
|
|
34
39
|
from typing import Callable
|
|
40
|
+
from typing import Generator
|
|
35
41
|
|
|
36
|
-
from sentry_sdk._types import EventProcessor
|
|
42
|
+
from sentry_sdk._types import Event, EventProcessor
|
|
37
43
|
|
|
38
44
|
|
|
39
45
|
class TornadoIntegration(Integration):
|
|
40
46
|
identifier = "tornado"
|
|
47
|
+
origin = f"auto.http.{identifier}"
|
|
41
48
|
|
|
42
49
|
@staticmethod
|
|
43
50
|
def setup_once():
|
|
44
51
|
# type: () -> None
|
|
45
|
-
|
|
46
|
-
raise DidNotEnable("Tornado 5+ required")
|
|
52
|
+
_check_minimum_version(TornadoIntegration, TORNADO_VERSION)
|
|
47
53
|
|
|
48
54
|
if not HAS_REAL_CONTEXTVARS:
|
|
49
55
|
# Tornado is async. We better have contextvars or we're going to leak
|
|
@@ -55,7 +61,7 @@ class TornadoIntegration(Integration):
|
|
|
55
61
|
|
|
56
62
|
ignore_logger("tornado.access")
|
|
57
63
|
|
|
58
|
-
old_execute = RequestHandler._execute
|
|
64
|
+
old_execute = RequestHandler._execute
|
|
59
65
|
|
|
60
66
|
awaitable = iscoroutinefunction(old_execute)
|
|
61
67
|
|
|
@@ -63,19 +69,8 @@ class TornadoIntegration(Integration):
|
|
|
63
69
|
# Starting Tornado 6 RequestHandler._execute method is a standard Python coroutine (async/await)
|
|
64
70
|
# In that case our method should be a coroutine function too
|
|
65
71
|
async def sentry_execute_request_handler(self, *args, **kwargs):
|
|
66
|
-
# type: (
|
|
67
|
-
|
|
68
|
-
integration = hub.get_integration(TornadoIntegration)
|
|
69
|
-
if integration is None:
|
|
70
|
-
return await old_execute(self, *args, **kwargs)
|
|
71
|
-
|
|
72
|
-
weak_handler = weakref.ref(self)
|
|
73
|
-
|
|
74
|
-
with Hub(hub) as hub:
|
|
75
|
-
with hub.configure_scope() as scope:
|
|
76
|
-
scope.clear_breadcrumbs()
|
|
77
|
-
processor = _make_event_processor(weak_handler) # type: ignore
|
|
78
|
-
scope.add_event_processor(processor)
|
|
72
|
+
# type: (RequestHandler, *Any, **Any) -> Any
|
|
73
|
+
with _handle_request_impl(self):
|
|
79
74
|
return await old_execute(self, *args, **kwargs)
|
|
80
75
|
|
|
81
76
|
else:
|
|
@@ -83,57 +78,76 @@ class TornadoIntegration(Integration):
|
|
|
83
78
|
@coroutine # type: ignore
|
|
84
79
|
def sentry_execute_request_handler(self, *args, **kwargs):
|
|
85
80
|
# type: (RequestHandler, *Any, **Any) -> Any
|
|
86
|
-
|
|
87
|
-
integration = hub.get_integration(TornadoIntegration)
|
|
88
|
-
if integration is None:
|
|
89
|
-
return old_execute(self, *args, **kwargs)
|
|
90
|
-
|
|
91
|
-
weak_handler = weakref.ref(self)
|
|
92
|
-
|
|
93
|
-
with Hub(hub) as hub:
|
|
94
|
-
with hub.configure_scope() as scope:
|
|
95
|
-
scope.clear_breadcrumbs()
|
|
96
|
-
processor = _make_event_processor(weak_handler) # type: ignore
|
|
97
|
-
scope.add_event_processor(processor)
|
|
81
|
+
with _handle_request_impl(self):
|
|
98
82
|
result = yield from old_execute(self, *args, **kwargs)
|
|
99
83
|
return result
|
|
100
84
|
|
|
101
|
-
RequestHandler._execute = sentry_execute_request_handler
|
|
85
|
+
RequestHandler._execute = sentry_execute_request_handler
|
|
102
86
|
|
|
103
87
|
old_log_exception = RequestHandler.log_exception
|
|
104
88
|
|
|
105
89
|
def sentry_log_exception(self, ty, value, tb, *args, **kwargs):
|
|
106
90
|
# type: (Any, type, BaseException, Any, *Any, **Any) -> Optional[Any]
|
|
107
91
|
_capture_exception(ty, value, tb)
|
|
108
|
-
return old_log_exception(self, ty, value, tb, *args, **kwargs)
|
|
92
|
+
return old_log_exception(self, ty, value, tb, *args, **kwargs)
|
|
93
|
+
|
|
94
|
+
RequestHandler.log_exception = sentry_log_exception
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@contextlib.contextmanager
|
|
98
|
+
def _handle_request_impl(self):
|
|
99
|
+
# type: (RequestHandler) -> Generator[None, None, None]
|
|
100
|
+
integration = sentry_sdk.get_client().get_integration(TornadoIntegration)
|
|
109
101
|
|
|
110
|
-
|
|
102
|
+
if integration is None:
|
|
103
|
+
yield
|
|
111
104
|
|
|
105
|
+
weak_handler = weakref.ref(self)
|
|
112
106
|
|
|
107
|
+
with sentry_sdk.isolation_scope() as scope:
|
|
108
|
+
headers = self.request.headers
|
|
109
|
+
|
|
110
|
+
scope.clear_breadcrumbs()
|
|
111
|
+
processor = _make_event_processor(weak_handler)
|
|
112
|
+
scope.add_event_processor(processor)
|
|
113
|
+
|
|
114
|
+
transaction = continue_trace(
|
|
115
|
+
headers,
|
|
116
|
+
op=OP.HTTP_SERVER,
|
|
117
|
+
# Like with all other integrations, this is our
|
|
118
|
+
# fallback transaction in case there is no route.
|
|
119
|
+
# sentry_urldispatcher_resolve is responsible for
|
|
120
|
+
# setting a transaction name later.
|
|
121
|
+
name="generic Tornado request",
|
|
122
|
+
source=TransactionSource.ROUTE,
|
|
123
|
+
origin=TornadoIntegration.origin,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
with sentry_sdk.start_transaction(
|
|
127
|
+
transaction, custom_sampling_context={"tornado_request": self.request}
|
|
128
|
+
):
|
|
129
|
+
yield
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@ensure_integration_enabled(TornadoIntegration)
|
|
113
133
|
def _capture_exception(ty, value, tb):
|
|
114
134
|
# type: (type, BaseException, Any) -> None
|
|
115
|
-
hub = Hub.current
|
|
116
|
-
if hub.get_integration(TornadoIntegration) is None:
|
|
117
|
-
return
|
|
118
135
|
if isinstance(value, HTTPError):
|
|
119
136
|
return
|
|
120
137
|
|
|
121
|
-
# If an integration is there, a client has to be there.
|
|
122
|
-
client = hub.client # type: Any
|
|
123
|
-
|
|
124
138
|
event, hint = event_from_exception(
|
|
125
139
|
(ty, value, tb),
|
|
126
|
-
client_options=
|
|
140
|
+
client_options=sentry_sdk.get_client().options,
|
|
127
141
|
mechanism={"type": "tornado", "handled": False},
|
|
128
142
|
)
|
|
129
143
|
|
|
130
|
-
|
|
144
|
+
sentry_sdk.capture_event(event, hint=hint)
|
|
131
145
|
|
|
132
146
|
|
|
133
147
|
def _make_event_processor(weak_handler):
|
|
134
148
|
# type: (Callable[[], RequestHandler]) -> EventProcessor
|
|
135
149
|
def tornado_processor(event, hint):
|
|
136
|
-
# type: (
|
|
150
|
+
# type: (Event, dict[str, Any]) -> Event
|
|
137
151
|
handler = weak_handler()
|
|
138
152
|
if handler is None:
|
|
139
153
|
return event
|
|
@@ -141,8 +155,9 @@ def _make_event_processor(weak_handler):
|
|
|
141
155
|
request = handler.request
|
|
142
156
|
|
|
143
157
|
with capture_internal_exceptions():
|
|
144
|
-
method = getattr(handler, handler.request.method.lower())
|
|
145
|
-
event["transaction"] = transaction_from_function(method)
|
|
158
|
+
method = getattr(handler, handler.request.method.lower())
|
|
159
|
+
event["transaction"] = transaction_from_function(method) or ""
|
|
160
|
+
event["transaction_info"] = {"source": TransactionSource.COMPONENT}
|
|
146
161
|
|
|
147
162
|
with capture_internal_exceptions():
|
|
148
163
|
extractor = TornadoRequestExtractor(request)
|
|
@@ -162,7 +177,7 @@ def _make_event_processor(weak_handler):
|
|
|
162
177
|
request_info["headers"] = _filter_headers(dict(request.headers))
|
|
163
178
|
|
|
164
179
|
with capture_internal_exceptions():
|
|
165
|
-
if handler.current_user and
|
|
180
|
+
if handler.current_user and should_send_default_pii():
|
|
166
181
|
event.setdefault("user", {}).setdefault("is_authenticated", True)
|
|
167
182
|
|
|
168
183
|
return event
|
|
@@ -179,7 +194,7 @@ class TornadoRequestExtractor(RequestExtractor):
|
|
|
179
194
|
|
|
180
195
|
def cookies(self):
|
|
181
196
|
# type: () -> Dict[str, str]
|
|
182
|
-
return {k: v.value for k, v in
|
|
197
|
+
return {k: v.value for k, v in self.request.cookies.items()}
|
|
183
198
|
|
|
184
199
|
def raw_data(self):
|
|
185
200
|
# type: () -> bytes
|
|
@@ -189,7 +204,7 @@ class TornadoRequestExtractor(RequestExtractor):
|
|
|
189
204
|
# type: () -> Dict[str, Any]
|
|
190
205
|
return {
|
|
191
206
|
k: [v.decode("latin1", "replace") for v in vs]
|
|
192
|
-
for k, vs in
|
|
207
|
+
for k, vs in self.request.body_arguments.items()
|
|
193
208
|
}
|
|
194
209
|
|
|
195
210
|
def is_json(self):
|
|
@@ -198,7 +213,7 @@ class TornadoRequestExtractor(RequestExtractor):
|
|
|
198
213
|
|
|
199
214
|
def files(self):
|
|
200
215
|
# type: () -> Dict[str, Any]
|
|
201
|
-
return {k: v[0] for k, v in
|
|
216
|
+
return {k: v[0] for k, v in self.request.files.items() if v}
|
|
202
217
|
|
|
203
218
|
def size_of_file(self, file):
|
|
204
219
|
# type: (Any) -> int
|
|
@@ -1,46 +1,41 @@
|
|
|
1
|
-
import sentry_sdk
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
from sentry_sdk._types import MYPY
|
|
1
|
+
import sentry_sdk
|
|
2
|
+
from sentry_sdk.integrations import Integration
|
|
3
|
+
from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware
|
|
4
|
+
from sentry_sdk.utils import ensure_integration_enabled, event_from_exception
|
|
6
5
|
|
|
7
6
|
from trytond.exceptions import TrytonException # type: ignore
|
|
8
7
|
from trytond.wsgi import app # type: ignore
|
|
9
8
|
|
|
10
|
-
if MYPY:
|
|
11
|
-
from typing import Any
|
|
12
|
-
|
|
13
9
|
|
|
14
10
|
# TODO: trytond-worker, trytond-cron and trytond-admin intergations
|
|
15
11
|
|
|
16
12
|
|
|
17
|
-
class TrytondWSGIIntegration(
|
|
13
|
+
class TrytondWSGIIntegration(Integration):
|
|
18
14
|
identifier = "trytond_wsgi"
|
|
15
|
+
origin = f"auto.http.{identifier}"
|
|
19
16
|
|
|
20
17
|
def __init__(self): # type: () -> None
|
|
21
18
|
pass
|
|
22
19
|
|
|
23
20
|
@staticmethod
|
|
24
21
|
def setup_once(): # type: () -> None
|
|
22
|
+
app.wsgi_app = SentryWsgiMiddleware(
|
|
23
|
+
app.wsgi_app,
|
|
24
|
+
span_origin=TrytondWSGIIntegration.origin,
|
|
25
|
+
)
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
@ensure_integration_enabled(TrytondWSGIIntegration)
|
|
28
28
|
def error_handler(e): # type: (Exception) -> None
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if hub.get_integration(TrytondWSGIIntegration) is None:
|
|
32
|
-
return
|
|
33
|
-
elif isinstance(e, TrytonException):
|
|
29
|
+
if isinstance(e, TrytonException):
|
|
34
30
|
return
|
|
35
31
|
else:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
event, hint = sentry_sdk.utils.event_from_exception(
|
|
32
|
+
client = sentry_sdk.get_client()
|
|
33
|
+
event, hint = event_from_exception(
|
|
39
34
|
e,
|
|
40
35
|
client_options=client.options,
|
|
41
36
|
mechanism={"type": "trytond", "handled": False},
|
|
42
37
|
)
|
|
43
|
-
|
|
38
|
+
sentry_sdk.capture_event(event, hint=hint)
|
|
44
39
|
|
|
45
40
|
# Expected error handlers signature was changed
|
|
46
41
|
# when the error_handler decorator was introduced
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import sentry_sdk
|
|
2
|
+
from sentry_sdk.utils import (
|
|
3
|
+
capture_internal_exceptions,
|
|
4
|
+
event_from_exception,
|
|
5
|
+
)
|
|
6
|
+
from sentry_sdk.integrations import Integration, DidNotEnable
|
|
7
|
+
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from typing import Callable
|
|
12
|
+
from typing import Any
|
|
13
|
+
from typing import Type
|
|
14
|
+
from typing import Optional
|
|
15
|
+
|
|
16
|
+
from types import TracebackType
|
|
17
|
+
|
|
18
|
+
Excepthook = Callable[
|
|
19
|
+
[Type[BaseException], BaseException, Optional[TracebackType]],
|
|
20
|
+
Any,
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
import typer
|
|
25
|
+
except ImportError:
|
|
26
|
+
raise DidNotEnable("Typer not installed")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class TyperIntegration(Integration):
|
|
30
|
+
identifier = "typer"
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def setup_once():
|
|
34
|
+
# type: () -> None
|
|
35
|
+
typer.main.except_hook = _make_excepthook(typer.main.except_hook) # type: ignore
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _make_excepthook(old_excepthook):
|
|
39
|
+
# type: (Excepthook) -> Excepthook
|
|
40
|
+
def sentry_sdk_excepthook(type_, value, traceback):
|
|
41
|
+
# type: (Type[BaseException], BaseException, Optional[TracebackType]) -> None
|
|
42
|
+
integration = sentry_sdk.get_client().get_integration(TyperIntegration)
|
|
43
|
+
|
|
44
|
+
# Note: If we replace this with ensure_integration_enabled then
|
|
45
|
+
# we break the exceptiongroup backport;
|
|
46
|
+
# See: https://github.com/getsentry/sentry-python/issues/3097
|
|
47
|
+
if integration is None:
|
|
48
|
+
return old_excepthook(type_, value, traceback)
|
|
49
|
+
|
|
50
|
+
with capture_internal_exceptions():
|
|
51
|
+
event, hint = event_from_exception(
|
|
52
|
+
(type_, value, traceback),
|
|
53
|
+
client_options=sentry_sdk.get_client().options,
|
|
54
|
+
mechanism={"type": "typer", "handled": False},
|
|
55
|
+
)
|
|
56
|
+
sentry_sdk.capture_event(event, hint=hint)
|
|
57
|
+
|
|
58
|
+
return old_excepthook(type_, value, traceback)
|
|
59
|
+
|
|
60
|
+
return sentry_sdk_excepthook
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from sentry_sdk.feature_flags import add_feature_flag
|
|
5
|
+
from sentry_sdk.integrations import Integration, DidNotEnable
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
from UnleashClient import UnleashClient
|
|
9
|
+
except ImportError:
|
|
10
|
+
raise DidNotEnable("UnleashClient is not installed")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class UnleashIntegration(Integration):
|
|
14
|
+
identifier = "unleash"
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def setup_once():
|
|
18
|
+
# type: () -> None
|
|
19
|
+
# Wrap and patch evaluation methods (class methods)
|
|
20
|
+
old_is_enabled = UnleashClient.is_enabled
|
|
21
|
+
|
|
22
|
+
@wraps(old_is_enabled)
|
|
23
|
+
def sentry_is_enabled(self, feature, *args, **kwargs):
|
|
24
|
+
# type: (UnleashClient, str, *Any, **Any) -> Any
|
|
25
|
+
enabled = old_is_enabled(self, feature, *args, **kwargs)
|
|
26
|
+
|
|
27
|
+
# We have no way of knowing what type of unleash feature this is, so we have to treat
|
|
28
|
+
# it as a boolean / toggle feature.
|
|
29
|
+
add_feature_flag(feature, enabled)
|
|
30
|
+
|
|
31
|
+
return enabled
|
|
32
|
+
|
|
33
|
+
UnleashClient.is_enabled = sentry_is_enabled # type: ignore
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
import sentry_sdk
|
|
4
|
+
from sentry_sdk.utils import (
|
|
5
|
+
capture_internal_exceptions,
|
|
6
|
+
event_from_exception,
|
|
7
|
+
)
|
|
8
|
+
from sentry_sdk.integrations import Integration
|
|
9
|
+
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from typing import Callable
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class UnraisablehookIntegration(Integration):
|
|
18
|
+
identifier = "unraisablehook"
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def setup_once():
|
|
22
|
+
# type: () -> None
|
|
23
|
+
sys.unraisablehook = _make_unraisable(sys.unraisablehook)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _make_unraisable(old_unraisablehook):
|
|
27
|
+
# type: (Callable[[sys.UnraisableHookArgs], Any]) -> Callable[[sys.UnraisableHookArgs], Any]
|
|
28
|
+
def sentry_sdk_unraisablehook(unraisable):
|
|
29
|
+
# type: (sys.UnraisableHookArgs) -> None
|
|
30
|
+
integration = sentry_sdk.get_client().get_integration(UnraisablehookIntegration)
|
|
31
|
+
|
|
32
|
+
# Note: If we replace this with ensure_integration_enabled then
|
|
33
|
+
# we break the exceptiongroup backport;
|
|
34
|
+
# See: https://github.com/getsentry/sentry-python/issues/3097
|
|
35
|
+
if integration is None:
|
|
36
|
+
return old_unraisablehook(unraisable)
|
|
37
|
+
|
|
38
|
+
if unraisable.exc_value and unraisable.exc_traceback:
|
|
39
|
+
with capture_internal_exceptions():
|
|
40
|
+
event, hint = event_from_exception(
|
|
41
|
+
(
|
|
42
|
+
unraisable.exc_type,
|
|
43
|
+
unraisable.exc_value,
|
|
44
|
+
unraisable.exc_traceback,
|
|
45
|
+
),
|
|
46
|
+
client_options=sentry_sdk.get_client().options,
|
|
47
|
+
mechanism={"type": "unraisablehook", "handled": False},
|
|
48
|
+
)
|
|
49
|
+
sentry_sdk.capture_event(event, hint=hint)
|
|
50
|
+
|
|
51
|
+
return old_unraisablehook(unraisable)
|
|
52
|
+
|
|
53
|
+
return sentry_sdk_unraisablehook
|