sentry-sdk 2.27.0__py2.py3-none-any.whl → 3.0.0a1__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 +4 -8
- sentry_sdk/_compat.py +0 -1
- sentry_sdk/_init_implementation.py +6 -44
- sentry_sdk/_log_batcher.py +47 -28
- sentry_sdk/_types.py +2 -64
- sentry_sdk/ai/monitoring.py +14 -10
- sentry_sdk/ai/utils.py +1 -1
- sentry_sdk/api.py +69 -163
- sentry_sdk/client.py +25 -72
- sentry_sdk/consts.py +42 -23
- sentry_sdk/debug.py +0 -10
- sentry_sdk/envelope.py +2 -10
- sentry_sdk/feature_flags.py +2 -2
- sentry_sdk/integrations/__init__.py +4 -2
- sentry_sdk/integrations/_asgi_common.py +3 -3
- sentry_sdk/integrations/_wsgi_common.py +11 -40
- sentry_sdk/integrations/aiohttp.py +104 -57
- sentry_sdk/integrations/anthropic.py +10 -7
- sentry_sdk/integrations/arq.py +24 -13
- sentry_sdk/integrations/asgi.py +102 -83
- sentry_sdk/integrations/asyncio.py +1 -0
- sentry_sdk/integrations/asyncpg.py +45 -30
- sentry_sdk/integrations/aws_lambda.py +109 -92
- sentry_sdk/integrations/boto3.py +38 -9
- sentry_sdk/integrations/bottle.py +1 -1
- sentry_sdk/integrations/celery/__init__.py +48 -38
- sentry_sdk/integrations/clickhouse_driver.py +59 -28
- sentry_sdk/integrations/cohere.py +2 -0
- sentry_sdk/integrations/django/__init__.py +25 -46
- sentry_sdk/integrations/django/asgi.py +6 -2
- sentry_sdk/integrations/django/caching.py +13 -22
- sentry_sdk/integrations/django/middleware.py +1 -0
- sentry_sdk/integrations/django/signals_handlers.py +3 -1
- sentry_sdk/integrations/django/templates.py +8 -12
- sentry_sdk/integrations/django/transactions.py +1 -6
- sentry_sdk/integrations/django/views.py +5 -2
- sentry_sdk/integrations/falcon.py +7 -25
- sentry_sdk/integrations/fastapi.py +3 -3
- sentry_sdk/integrations/flask.py +1 -1
- sentry_sdk/integrations/gcp.py +63 -38
- sentry_sdk/integrations/graphene.py +6 -13
- sentry_sdk/integrations/grpc/aio/client.py +14 -8
- sentry_sdk/integrations/grpc/aio/server.py +19 -21
- sentry_sdk/integrations/grpc/client.py +8 -6
- sentry_sdk/integrations/grpc/server.py +12 -14
- sentry_sdk/integrations/httpx.py +47 -12
- sentry_sdk/integrations/huey.py +26 -22
- sentry_sdk/integrations/huggingface_hub.py +1 -0
- sentry_sdk/integrations/langchain.py +22 -15
- sentry_sdk/integrations/litestar.py +4 -2
- sentry_sdk/integrations/logging.py +12 -3
- sentry_sdk/integrations/openai.py +2 -0
- sentry_sdk/integrations/pymongo.py +18 -25
- sentry_sdk/integrations/pyramid.py +1 -1
- sentry_sdk/integrations/quart.py +3 -3
- sentry_sdk/integrations/ray.py +23 -17
- sentry_sdk/integrations/redis/_async_common.py +30 -18
- sentry_sdk/integrations/redis/_sync_common.py +28 -18
- sentry_sdk/integrations/redis/modules/caches.py +13 -10
- sentry_sdk/integrations/redis/modules/queries.py +14 -11
- sentry_sdk/integrations/redis/rb.py +4 -4
- sentry_sdk/integrations/redis/redis.py +6 -6
- sentry_sdk/integrations/redis/redis_cluster.py +18 -16
- sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +4 -4
- sentry_sdk/integrations/redis/utils.py +63 -19
- sentry_sdk/integrations/rq.py +68 -23
- sentry_sdk/integrations/rust_tracing.py +28 -43
- sentry_sdk/integrations/sanic.py +23 -13
- sentry_sdk/integrations/socket.py +9 -5
- sentry_sdk/integrations/sqlalchemy.py +8 -8
- sentry_sdk/integrations/starlette.py +11 -31
- sentry_sdk/integrations/starlite.py +4 -2
- sentry_sdk/integrations/stdlib.py +56 -9
- sentry_sdk/integrations/strawberry.py +40 -59
- sentry_sdk/integrations/threading.py +10 -26
- sentry_sdk/integrations/tornado.py +57 -18
- sentry_sdk/integrations/trytond.py +4 -1
- sentry_sdk/integrations/wsgi.py +84 -38
- sentry_sdk/opentelemetry/__init__.py +9 -0
- sentry_sdk/opentelemetry/consts.py +33 -0
- sentry_sdk/opentelemetry/contextvars_context.py +73 -0
- sentry_sdk/{integrations/opentelemetry → opentelemetry}/propagator.py +19 -28
- sentry_sdk/opentelemetry/sampler.py +326 -0
- sentry_sdk/opentelemetry/scope.py +218 -0
- sentry_sdk/opentelemetry/span_processor.py +329 -0
- sentry_sdk/opentelemetry/tracing.py +35 -0
- sentry_sdk/opentelemetry/utils.py +476 -0
- sentry_sdk/profiler/__init__.py +0 -40
- sentry_sdk/profiler/continuous_profiler.py +1 -30
- sentry_sdk/profiler/transaction_profiler.py +5 -56
- sentry_sdk/scope.py +107 -351
- sentry_sdk/sessions.py +0 -87
- sentry_sdk/tracing.py +418 -1144
- sentry_sdk/tracing_utils.py +126 -164
- sentry_sdk/transport.py +4 -104
- sentry_sdk/utils.py +169 -152
- {sentry_sdk-2.27.0.dist-info → sentry_sdk-3.0.0a1.dist-info}/METADATA +3 -5
- sentry_sdk-3.0.0a1.dist-info/RECORD +154 -0
- {sentry_sdk-2.27.0.dist-info → sentry_sdk-3.0.0a1.dist-info}/WHEEL +1 -1
- sentry_sdk-3.0.0a1.dist-info/entry_points.txt +2 -0
- sentry_sdk/hub.py +0 -739
- sentry_sdk/integrations/opentelemetry/__init__.py +0 -7
- sentry_sdk/integrations/opentelemetry/consts.py +0 -5
- sentry_sdk/integrations/opentelemetry/integration.py +0 -58
- sentry_sdk/integrations/opentelemetry/span_processor.py +0 -391
- sentry_sdk/metrics.py +0 -965
- sentry_sdk-2.27.0.dist-info/RECORD +0 -152
- sentry_sdk-2.27.0.dist-info/entry_points.txt +0 -2
- {sentry_sdk-2.27.0.dist-info → sentry_sdk-3.0.0a1.dist-info}/licenses/LICENSE +0 -0
- {sentry_sdk-2.27.0.dist-info → sentry_sdk-3.0.0a1.dist-info}/top_level.txt +0 -0
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import functools
|
|
3
|
-
import warnings
|
|
4
3
|
from collections.abc import Set
|
|
5
4
|
from copy import deepcopy
|
|
6
5
|
from json import JSONDecodeError
|
|
7
6
|
|
|
8
7
|
import sentry_sdk
|
|
9
|
-
from sentry_sdk.consts import OP
|
|
8
|
+
from sentry_sdk.consts import OP, SOURCE_FOR_STYLE, TransactionSource
|
|
10
9
|
from sentry_sdk.integrations import (
|
|
11
10
|
DidNotEnable,
|
|
12
11
|
Integration,
|
|
@@ -14,16 +13,11 @@ from sentry_sdk.integrations import (
|
|
|
14
13
|
)
|
|
15
14
|
from sentry_sdk.integrations._wsgi_common import (
|
|
16
15
|
DEFAULT_HTTP_METHODS_TO_CAPTURE,
|
|
17
|
-
HttpCodeRangeContainer,
|
|
18
16
|
_is_json_content_type,
|
|
19
17
|
request_body_within_bounds,
|
|
20
18
|
)
|
|
21
19
|
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
|
|
22
20
|
from sentry_sdk.scope import should_send_default_pii
|
|
23
|
-
from sentry_sdk.tracing import (
|
|
24
|
-
SOURCE_FOR_STYLE,
|
|
25
|
-
TransactionSource,
|
|
26
|
-
)
|
|
27
21
|
from sentry_sdk.utils import (
|
|
28
22
|
AnnotatedValue,
|
|
29
23
|
capture_internal_exceptions,
|
|
@@ -37,9 +31,9 @@ from sentry_sdk.utils import (
|
|
|
37
31
|
from typing import TYPE_CHECKING
|
|
38
32
|
|
|
39
33
|
if TYPE_CHECKING:
|
|
40
|
-
from typing import Any, Awaitable, Callable,
|
|
34
|
+
from typing import Any, Awaitable, Callable, Dict, Optional, Tuple
|
|
41
35
|
|
|
42
|
-
from sentry_sdk._types import Event
|
|
36
|
+
from sentry_sdk._types import Event
|
|
43
37
|
|
|
44
38
|
try:
|
|
45
39
|
import starlette # type: ignore
|
|
@@ -89,7 +83,7 @@ class StarletteIntegration(Integration):
|
|
|
89
83
|
def __init__(
|
|
90
84
|
self,
|
|
91
85
|
transaction_style="url", # type: str
|
|
92
|
-
failed_request_status_codes=_DEFAULT_FAILED_REQUEST_STATUS_CODES, # type:
|
|
86
|
+
failed_request_status_codes=_DEFAULT_FAILED_REQUEST_STATUS_CODES, # type: Set[int]
|
|
93
87
|
middleware_spans=True, # type: bool
|
|
94
88
|
http_methods_to_capture=DEFAULT_HTTP_METHODS_TO_CAPTURE, # type: tuple[str, ...]
|
|
95
89
|
):
|
|
@@ -103,24 +97,7 @@ class StarletteIntegration(Integration):
|
|
|
103
97
|
self.middleware_spans = middleware_spans
|
|
104
98
|
self.http_methods_to_capture = tuple(map(str.upper, http_methods_to_capture))
|
|
105
99
|
|
|
106
|
-
|
|
107
|
-
self.failed_request_status_codes = (
|
|
108
|
-
failed_request_status_codes
|
|
109
|
-
) # type: Container[int]
|
|
110
|
-
else:
|
|
111
|
-
warnings.warn(
|
|
112
|
-
"Passing a list or None for failed_request_status_codes is deprecated. "
|
|
113
|
-
"Please pass a set of int instead.",
|
|
114
|
-
DeprecationWarning,
|
|
115
|
-
stacklevel=2,
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
if failed_request_status_codes is None:
|
|
119
|
-
self.failed_request_status_codes = _DEFAULT_FAILED_REQUEST_STATUS_CODES
|
|
120
|
-
else:
|
|
121
|
-
self.failed_request_status_codes = HttpCodeRangeContainer(
|
|
122
|
-
failed_request_status_codes
|
|
123
|
-
)
|
|
100
|
+
self.failed_request_status_codes = failed_request_status_codes
|
|
124
101
|
|
|
125
102
|
@staticmethod
|
|
126
103
|
def setup_once():
|
|
@@ -164,6 +141,7 @@ def _enable_span_for_middleware(middleware_class):
|
|
|
164
141
|
op=OP.MIDDLEWARE_STARLETTE,
|
|
165
142
|
name=middleware_name,
|
|
166
143
|
origin=StarletteIntegration.origin,
|
|
144
|
+
only_if_parent=True,
|
|
167
145
|
) as middleware_span:
|
|
168
146
|
middleware_span.set_tag("starlette.middleware_name", middleware_name)
|
|
169
147
|
|
|
@@ -174,6 +152,7 @@ def _enable_span_for_middleware(middleware_class):
|
|
|
174
152
|
op=OP.MIDDLEWARE_STARLETTE_RECEIVE,
|
|
175
153
|
name=getattr(receive, "__qualname__", str(receive)),
|
|
176
154
|
origin=StarletteIntegration.origin,
|
|
155
|
+
only_if_parent=True,
|
|
177
156
|
) as span:
|
|
178
157
|
span.set_tag("starlette.middleware_name", middleware_name)
|
|
179
158
|
return await receive(*args, **kwargs)
|
|
@@ -189,6 +168,7 @@ def _enable_span_for_middleware(middleware_class):
|
|
|
189
168
|
op=OP.MIDDLEWARE_STARLETTE_SEND,
|
|
190
169
|
name=getattr(send, "__qualname__", str(send)),
|
|
191
170
|
origin=StarletteIntegration.origin,
|
|
171
|
+
only_if_parent=True,
|
|
192
172
|
) as span:
|
|
193
173
|
span.set_tag("starlette.middleware_name", middleware_name)
|
|
194
174
|
return await send(*args, **kwargs)
|
|
@@ -329,7 +309,7 @@ def _add_user_to_sentry_scope(scope):
|
|
|
329
309
|
user_info.setdefault("email", starlette_user.email)
|
|
330
310
|
|
|
331
311
|
sentry_scope = sentry_sdk.get_isolation_scope()
|
|
332
|
-
sentry_scope.
|
|
312
|
+
sentry_scope.set_user(user_info)
|
|
333
313
|
|
|
334
314
|
|
|
335
315
|
def patch_authentication_middleware(middleware_class):
|
|
@@ -493,8 +473,8 @@ def patch_request_response():
|
|
|
493
473
|
return old_func(*args, **kwargs)
|
|
494
474
|
|
|
495
475
|
current_scope = sentry_sdk.get_current_scope()
|
|
496
|
-
if current_scope.
|
|
497
|
-
current_scope.
|
|
476
|
+
if current_scope.root_span is not None:
|
|
477
|
+
current_scope.root_span.update_active_thread()
|
|
498
478
|
|
|
499
479
|
sentry_scope = sentry_sdk.get_isolation_scope()
|
|
500
480
|
if sentry_scope.profile is not None:
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import sentry_sdk
|
|
2
|
-
from sentry_sdk.consts import OP
|
|
2
|
+
from sentry_sdk.consts import OP, SOURCE_FOR_STYLE, TransactionSource
|
|
3
3
|
from sentry_sdk.integrations import DidNotEnable, Integration
|
|
4
4
|
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
|
|
5
5
|
from sentry_sdk.scope import should_send_default_pii
|
|
6
|
-
from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource
|
|
7
6
|
from sentry_sdk.utils import (
|
|
8
7
|
ensure_integration_enabled,
|
|
9
8
|
event_from_exception,
|
|
@@ -140,6 +139,7 @@ def enable_span_for_middleware(middleware):
|
|
|
140
139
|
op=OP.MIDDLEWARE_STARLITE,
|
|
141
140
|
name=middleware_name,
|
|
142
141
|
origin=StarliteIntegration.origin,
|
|
142
|
+
only_if_parent=True,
|
|
143
143
|
) as middleware_span:
|
|
144
144
|
middleware_span.set_tag("starlite.middleware_name", middleware_name)
|
|
145
145
|
|
|
@@ -152,6 +152,7 @@ def enable_span_for_middleware(middleware):
|
|
|
152
152
|
op=OP.MIDDLEWARE_STARLITE_RECEIVE,
|
|
153
153
|
name=getattr(receive, "__qualname__", str(receive)),
|
|
154
154
|
origin=StarliteIntegration.origin,
|
|
155
|
+
only_if_parent=True,
|
|
155
156
|
) as span:
|
|
156
157
|
span.set_tag("starlite.middleware_name", middleware_name)
|
|
157
158
|
return await receive(*args, **kwargs)
|
|
@@ -169,6 +170,7 @@ def enable_span_for_middleware(middleware):
|
|
|
169
170
|
op=OP.MIDDLEWARE_STARLITE_SEND,
|
|
170
171
|
name=getattr(send, "__qualname__", str(send)),
|
|
171
172
|
origin=StarliteIntegration.origin,
|
|
173
|
+
only_if_parent=True,
|
|
172
174
|
) as span:
|
|
173
175
|
span.set_tag("starlite.middleware_name", middleware_name)
|
|
174
176
|
return await send(message)
|
|
@@ -13,10 +13,13 @@ from sentry_sdk.utils import (
|
|
|
13
13
|
SENSITIVE_DATA_SUBSTITUTE,
|
|
14
14
|
capture_internal_exceptions,
|
|
15
15
|
ensure_integration_enabled,
|
|
16
|
+
get_current_thread_meta,
|
|
17
|
+
http_client_status_to_breadcrumb_level,
|
|
16
18
|
is_sentry_url,
|
|
17
19
|
logger,
|
|
18
20
|
safe_repr,
|
|
19
21
|
parse_url,
|
|
22
|
+
set_thread_info_from_span,
|
|
20
23
|
)
|
|
21
24
|
|
|
22
25
|
from typing import TYPE_CHECKING
|
|
@@ -71,7 +74,7 @@ def _install_httplib():
|
|
|
71
74
|
|
|
72
75
|
client = sentry_sdk.get_client()
|
|
73
76
|
if client.get_integration(StdlibIntegration) is None or is_sentry_url(
|
|
74
|
-
client, host
|
|
77
|
+
client, f"{host}:{port}" # noqa: E231
|
|
75
78
|
):
|
|
76
79
|
return real_putrequest(self, method, url, *args, **kwargs)
|
|
77
80
|
|
|
@@ -93,12 +96,22 @@ def _install_httplib():
|
|
|
93
96
|
name="%s %s"
|
|
94
97
|
% (method, parsed_url.url if parsed_url else SENSITIVE_DATA_SUBSTITUTE),
|
|
95
98
|
origin="auto.http.stdlib.httplib",
|
|
99
|
+
only_if_parent=True,
|
|
96
100
|
)
|
|
97
|
-
span.
|
|
101
|
+
span.__enter__()
|
|
102
|
+
|
|
103
|
+
data = {
|
|
104
|
+
SPANDATA.HTTP_METHOD: method,
|
|
105
|
+
}
|
|
106
|
+
set_thread_info_from_span(data, span)
|
|
107
|
+
|
|
98
108
|
if parsed_url is not None:
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
109
|
+
data["url"] = parsed_url.url
|
|
110
|
+
data[SPANDATA.HTTP_QUERY] = parsed_url.query
|
|
111
|
+
data[SPANDATA.HTTP_FRAGMENT] = parsed_url.fragment
|
|
112
|
+
|
|
113
|
+
for key, value in data.items():
|
|
114
|
+
span.set_attribute(key, value)
|
|
102
115
|
|
|
103
116
|
rv = real_putrequest(self, method, url, *args, **kwargs)
|
|
104
117
|
|
|
@@ -117,6 +130,7 @@ def _install_httplib():
|
|
|
117
130
|
self.putheader(key, value)
|
|
118
131
|
|
|
119
132
|
self._sentrysdk_span = span # type: ignore[attr-defined]
|
|
133
|
+
self._sentrysdk_span_data = data # type: ignore[attr-defined]
|
|
120
134
|
|
|
121
135
|
return rv
|
|
122
136
|
|
|
@@ -130,10 +144,22 @@ def _install_httplib():
|
|
|
130
144
|
try:
|
|
131
145
|
rv = real_getresponse(self, *args, **kwargs)
|
|
132
146
|
|
|
133
|
-
|
|
134
|
-
|
|
147
|
+
span_data = getattr(self, "_sentrysdk_span_data", {})
|
|
148
|
+
span_data[SPANDATA.HTTP_STATUS_CODE] = int(rv.status)
|
|
149
|
+
span_data["reason"] = rv.reason
|
|
150
|
+
|
|
151
|
+
status_code = int(rv.status)
|
|
152
|
+
span.set_http_status(status_code)
|
|
153
|
+
span.set_attribute("reason", rv.reason)
|
|
154
|
+
|
|
155
|
+
sentry_sdk.add_breadcrumb(
|
|
156
|
+
type="http",
|
|
157
|
+
category="httplib",
|
|
158
|
+
data=span_data,
|
|
159
|
+
level=http_client_status_to_breadcrumb_level(status_code),
|
|
160
|
+
)
|
|
135
161
|
finally:
|
|
136
|
-
span.
|
|
162
|
+
span.__exit__(None, None, None)
|
|
137
163
|
|
|
138
164
|
return rv
|
|
139
165
|
|
|
@@ -207,6 +233,7 @@ def _install_subprocess():
|
|
|
207
233
|
op=OP.SUBPROCESS,
|
|
208
234
|
name=description,
|
|
209
235
|
origin="auto.subprocess.stdlib.subprocess",
|
|
236
|
+
only_if_parent=True,
|
|
210
237
|
) as span:
|
|
211
238
|
for k, v in sentry_sdk.get_current_scope().iter_trace_propagation_headers(
|
|
212
239
|
span=span
|
|
@@ -222,11 +249,29 @@ def _install_subprocess():
|
|
|
222
249
|
env["SUBPROCESS_" + k.upper().replace("-", "_")] = v
|
|
223
250
|
|
|
224
251
|
if cwd:
|
|
225
|
-
span.
|
|
252
|
+
span.set_attribute("subprocess.cwd", cwd)
|
|
226
253
|
|
|
227
254
|
rv = old_popen_init(self, *a, **kw)
|
|
228
255
|
|
|
229
256
|
span.set_tag("subprocess.pid", self.pid)
|
|
257
|
+
|
|
258
|
+
with capture_internal_exceptions():
|
|
259
|
+
thread_id, thread_name = get_current_thread_meta()
|
|
260
|
+
breadcrumb_data = {
|
|
261
|
+
"subprocess.pid": self.pid,
|
|
262
|
+
SPANDATA.THREAD_ID: thread_id,
|
|
263
|
+
SPANDATA.THREAD_NAME: thread_name,
|
|
264
|
+
}
|
|
265
|
+
if cwd:
|
|
266
|
+
breadcrumb_data["subprocess.cwd"] = cwd
|
|
267
|
+
|
|
268
|
+
sentry_sdk.add_breadcrumb(
|
|
269
|
+
type="subprocess",
|
|
270
|
+
category="subprocess",
|
|
271
|
+
message=description,
|
|
272
|
+
data=breadcrumb_data,
|
|
273
|
+
)
|
|
274
|
+
|
|
230
275
|
return rv
|
|
231
276
|
|
|
232
277
|
subprocess.Popen.__init__ = sentry_patched_popen_init # type: ignore
|
|
@@ -239,6 +284,7 @@ def _install_subprocess():
|
|
|
239
284
|
with sentry_sdk.start_span(
|
|
240
285
|
op=OP.SUBPROCESS_WAIT,
|
|
241
286
|
origin="auto.subprocess.stdlib.subprocess",
|
|
287
|
+
only_if_parent=True,
|
|
242
288
|
) as span:
|
|
243
289
|
span.set_tag("subprocess.pid", self.pid)
|
|
244
290
|
return old_popen_wait(self, *a, **kw)
|
|
@@ -253,6 +299,7 @@ def _install_subprocess():
|
|
|
253
299
|
with sentry_sdk.start_span(
|
|
254
300
|
op=OP.SUBPROCESS_COMMUNICATE,
|
|
255
301
|
origin="auto.subprocess.stdlib.subprocess",
|
|
302
|
+
only_if_parent=True,
|
|
256
303
|
) as span:
|
|
257
304
|
span.set_tag("subprocess.pid", self.pid)
|
|
258
305
|
return old_popen_communicate(self, *a, **kw)
|
|
@@ -107,14 +107,6 @@ def _patch_schema_init():
|
|
|
107
107
|
"False" if should_use_async_extension else "True",
|
|
108
108
|
)
|
|
109
109
|
|
|
110
|
-
# remove the built in strawberry sentry extension, if present
|
|
111
|
-
extensions = [
|
|
112
|
-
extension
|
|
113
|
-
for extension in extensions
|
|
114
|
-
if extension
|
|
115
|
-
not in (StrawberrySentryAsyncExtension, StrawberrySentrySyncExtension)
|
|
116
|
-
]
|
|
117
|
-
|
|
118
110
|
# add our extension
|
|
119
111
|
extensions.append(
|
|
120
112
|
SentryAsyncExtension if should_use_async_extension else SentrySyncExtension
|
|
@@ -184,58 +176,52 @@ class SentryAsyncExtension(SchemaExtension):
|
|
|
184
176
|
event_processor = _make_request_event_processor(self.execution_context)
|
|
185
177
|
scope.add_event_processor(event_processor)
|
|
186
178
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
)
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
origin=StrawberryIntegration.origin,
|
|
199
|
-
)
|
|
179
|
+
with sentry_sdk.start_span(
|
|
180
|
+
op=op,
|
|
181
|
+
name=description,
|
|
182
|
+
origin=StrawberryIntegration.origin,
|
|
183
|
+
only_if_parent=True,
|
|
184
|
+
) as graphql_span:
|
|
185
|
+
graphql_span.set_attribute("graphql.operation.type", operation_type)
|
|
186
|
+
graphql_span.set_attribute("graphql.document", self.execution_context.query)
|
|
187
|
+
graphql_span.set_attribute("graphql.resource_name", self._resource_name)
|
|
188
|
+
|
|
189
|
+
yield
|
|
200
190
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
self.graphql_span.set_data("graphql.document", self.execution_context.query)
|
|
204
|
-
self.graphql_span.set_data("graphql.resource_name", self._resource_name)
|
|
191
|
+
# we might have a more accurate operation_name after the parsing
|
|
192
|
+
self._operation_name = self.execution_context.operation_name
|
|
205
193
|
|
|
206
|
-
|
|
194
|
+
if self._operation_name is not None:
|
|
195
|
+
graphql_span.set_attribute(
|
|
196
|
+
"graphql.operation.name", self._operation_name
|
|
197
|
+
)
|
|
207
198
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
transaction.op = op
|
|
199
|
+
sentry_sdk.get_current_scope().set_transaction_name(
|
|
200
|
+
self._operation_name,
|
|
201
|
+
source=TransactionSource.COMPONENT,
|
|
202
|
+
)
|
|
213
203
|
|
|
214
|
-
|
|
204
|
+
root_span = graphql_span.root_span
|
|
205
|
+
if root_span:
|
|
206
|
+
root_span.op = op
|
|
215
207
|
|
|
216
208
|
def on_validate(self):
|
|
217
209
|
# type: () -> Generator[None, None, None]
|
|
218
|
-
|
|
210
|
+
with sentry_sdk.start_span(
|
|
219
211
|
op=OP.GRAPHQL_VALIDATE,
|
|
220
212
|
name="validation",
|
|
221
213
|
origin=StrawberryIntegration.origin,
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
yield
|
|
225
|
-
|
|
226
|
-
self.validation_span.finish()
|
|
214
|
+
):
|
|
215
|
+
yield
|
|
227
216
|
|
|
228
217
|
def on_parse(self):
|
|
229
218
|
# type: () -> Generator[None, None, None]
|
|
230
|
-
|
|
219
|
+
with sentry_sdk.start_span(
|
|
231
220
|
op=OP.GRAPHQL_PARSE,
|
|
232
221
|
name="parsing",
|
|
233
222
|
origin=StrawberryIntegration.origin,
|
|
234
|
-
)
|
|
235
|
-
|
|
236
|
-
yield
|
|
237
|
-
|
|
238
|
-
self.parsing_span.finish()
|
|
223
|
+
):
|
|
224
|
+
yield
|
|
239
225
|
|
|
240
226
|
def should_skip_tracing(self, _next, info):
|
|
241
227
|
# type: (Callable[[Any, GraphQLResolveInfo, Any, Any], Any], GraphQLResolveInfo) -> bool
|
|
@@ -257,15 +243,15 @@ class SentryAsyncExtension(SchemaExtension):
|
|
|
257
243
|
|
|
258
244
|
field_path = "{}.{}".format(info.parent_type, info.field_name)
|
|
259
245
|
|
|
260
|
-
with
|
|
246
|
+
with sentry_sdk.start_span(
|
|
261
247
|
op=OP.GRAPHQL_RESOLVE,
|
|
262
248
|
name="resolving {}".format(field_path),
|
|
263
249
|
origin=StrawberryIntegration.origin,
|
|
264
250
|
) as span:
|
|
265
|
-
span.
|
|
266
|
-
span.
|
|
267
|
-
span.
|
|
268
|
-
span.
|
|
251
|
+
span.set_attribute("graphql.field_name", info.field_name)
|
|
252
|
+
span.set_attribute("graphql.parent_type", info.parent_type.name)
|
|
253
|
+
span.set_attribute("graphql.field_path", field_path)
|
|
254
|
+
span.set_attribute("graphql.path", ".".join(map(str, info.path.as_list())))
|
|
269
255
|
|
|
270
256
|
return await self._resolve(_next, root, info, *args, **kwargs)
|
|
271
257
|
|
|
@@ -278,15 +264,15 @@ class SentrySyncExtension(SentryAsyncExtension):
|
|
|
278
264
|
|
|
279
265
|
field_path = "{}.{}".format(info.parent_type, info.field_name)
|
|
280
266
|
|
|
281
|
-
with
|
|
267
|
+
with sentry_sdk.start_span(
|
|
282
268
|
op=OP.GRAPHQL_RESOLVE,
|
|
283
269
|
name="resolving {}".format(field_path),
|
|
284
270
|
origin=StrawberryIntegration.origin,
|
|
285
271
|
) as span:
|
|
286
|
-
span.
|
|
287
|
-
span.
|
|
288
|
-
span.
|
|
289
|
-
span.
|
|
272
|
+
span.set_attribute("graphql.field_name", info.field_name)
|
|
273
|
+
span.set_attribute("graphql.parent_type", info.parent_type.name)
|
|
274
|
+
span.set_attribute("graphql.field_path", field_path)
|
|
275
|
+
span.set_attribute("graphql.path", ".".join(map(str, info.path.as_list())))
|
|
290
276
|
|
|
291
277
|
return _next(root, info, *args, **kwargs)
|
|
292
278
|
|
|
@@ -383,11 +369,6 @@ def _make_response_event_processor(response_data):
|
|
|
383
369
|
|
|
384
370
|
def _guess_if_using_async(extensions):
|
|
385
371
|
# type: (List[SchemaExtension]) -> bool
|
|
386
|
-
if StrawberrySentryAsyncExtension in extensions:
|
|
387
|
-
return True
|
|
388
|
-
elif StrawberrySentrySyncExtension in extensions:
|
|
389
|
-
return False
|
|
390
|
-
|
|
391
372
|
return bool(
|
|
392
373
|
{"starlette", "starlite", "litestar", "fastapi"} & set(_get_installed_modules())
|
|
393
374
|
)
|
|
@@ -4,12 +4,12 @@ from functools import wraps
|
|
|
4
4
|
from threading import Thread, current_thread
|
|
5
5
|
|
|
6
6
|
import sentry_sdk
|
|
7
|
+
from sentry_sdk import Scope
|
|
8
|
+
from sentry_sdk.scope import ScopeType
|
|
7
9
|
from sentry_sdk.integrations import Integration
|
|
8
|
-
from sentry_sdk.scope import use_isolation_scope, use_scope
|
|
9
10
|
from sentry_sdk.utils import (
|
|
10
11
|
event_from_exception,
|
|
11
12
|
capture_internal_exceptions,
|
|
12
|
-
logger,
|
|
13
13
|
reraise,
|
|
14
14
|
)
|
|
15
15
|
|
|
@@ -19,7 +19,6 @@ if TYPE_CHECKING:
|
|
|
19
19
|
from typing import Any
|
|
20
20
|
from typing import TypeVar
|
|
21
21
|
from typing import Callable
|
|
22
|
-
from typing import Optional
|
|
23
22
|
|
|
24
23
|
from sentry_sdk._types import ExcInfo
|
|
25
24
|
|
|
@@ -29,22 +28,10 @@ if TYPE_CHECKING:
|
|
|
29
28
|
class ThreadingIntegration(Integration):
|
|
30
29
|
identifier = "threading"
|
|
31
30
|
|
|
32
|
-
def __init__(self,
|
|
33
|
-
# type: (
|
|
34
|
-
if propagate_hub is not None:
|
|
35
|
-
logger.warning(
|
|
36
|
-
"Deprecated: propagate_hub is deprecated. This will be removed in the future."
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
# Note: propagate_hub did not have any effect on propagation of scope data
|
|
40
|
-
# scope data was always propagated no matter what the value of propagate_hub was
|
|
41
|
-
# This is why the default for propagate_scope is True
|
|
42
|
-
|
|
31
|
+
def __init__(self, propagate_scope=True):
|
|
32
|
+
# type: (bool) -> None
|
|
43
33
|
self.propagate_scope = propagate_scope
|
|
44
34
|
|
|
45
|
-
if propagate_hub is not None:
|
|
46
|
-
self.propagate_scope = propagate_hub
|
|
47
|
-
|
|
48
35
|
@staticmethod
|
|
49
36
|
def setup_once():
|
|
50
37
|
# type: () -> None
|
|
@@ -89,8 +76,8 @@ class ThreadingIntegration(Integration):
|
|
|
89
76
|
isolation_scope = sentry_sdk.get_isolation_scope().fork()
|
|
90
77
|
current_scope = sentry_sdk.get_current_scope().fork()
|
|
91
78
|
else:
|
|
92
|
-
isolation_scope =
|
|
93
|
-
current_scope =
|
|
79
|
+
isolation_scope = Scope(ty=ScopeType.ISOLATION)
|
|
80
|
+
current_scope = Scope(ty=ScopeType.CURRENT)
|
|
94
81
|
|
|
95
82
|
# Patching instance methods in `start()` creates a reference cycle if
|
|
96
83
|
# done in a naive way. See
|
|
@@ -112,7 +99,7 @@ class ThreadingIntegration(Integration):
|
|
|
112
99
|
|
|
113
100
|
|
|
114
101
|
def _wrap_run(isolation_scope_to_use, current_scope_to_use, old_run_func):
|
|
115
|
-
# type: (
|
|
102
|
+
# type: (sentry_sdk.Scope, sentry_sdk.Scope, F) -> F
|
|
116
103
|
@wraps(old_run_func)
|
|
117
104
|
def run(*a, **kw):
|
|
118
105
|
# type: (*Any, **Any) -> Any
|
|
@@ -124,12 +111,9 @@ def _wrap_run(isolation_scope_to_use, current_scope_to_use, old_run_func):
|
|
|
124
111
|
except Exception:
|
|
125
112
|
reraise(*_capture_exception())
|
|
126
113
|
|
|
127
|
-
|
|
128
|
-
with
|
|
129
|
-
|
|
130
|
-
return _run_old_run_func()
|
|
131
|
-
else:
|
|
132
|
-
return _run_old_run_func()
|
|
114
|
+
with sentry_sdk.use_isolation_scope(isolation_scope_to_use):
|
|
115
|
+
with sentry_sdk.use_scope(current_scope_to_use):
|
|
116
|
+
return _run_old_run_func()
|
|
133
117
|
|
|
134
118
|
return run # type: ignore
|
|
135
119
|
|
|
@@ -3,7 +3,6 @@ import contextlib
|
|
|
3
3
|
from inspect import iscoroutinefunction
|
|
4
4
|
|
|
5
5
|
import sentry_sdk
|
|
6
|
-
from sentry_sdk.api import continue_trace
|
|
7
6
|
from sentry_sdk.consts import OP
|
|
8
7
|
from sentry_sdk.scope import should_send_default_pii
|
|
9
8
|
from sentry_sdk.tracing import TransactionSource
|
|
@@ -20,13 +19,15 @@ from sentry_sdk.integrations._wsgi_common import (
|
|
|
20
19
|
RequestExtractor,
|
|
21
20
|
_filter_headers,
|
|
22
21
|
_is_json_content_type,
|
|
22
|
+
_request_headers_to_span_attributes,
|
|
23
23
|
)
|
|
24
24
|
from sentry_sdk.integrations.logging import ignore_logger
|
|
25
25
|
|
|
26
26
|
try:
|
|
27
27
|
from tornado import version_info as TORNADO_VERSION
|
|
28
|
-
from tornado.web import RequestHandler, HTTPError
|
|
29
28
|
from tornado.gen import coroutine
|
|
29
|
+
from tornado.httputil import HTTPServerRequest
|
|
30
|
+
from tornado.web import RequestHandler, HTTPError
|
|
30
31
|
except ImportError:
|
|
31
32
|
raise DidNotEnable("Tornado not installed")
|
|
32
33
|
|
|
@@ -42,6 +43,14 @@ if TYPE_CHECKING:
|
|
|
42
43
|
from sentry_sdk._types import Event, EventProcessor
|
|
43
44
|
|
|
44
45
|
|
|
46
|
+
REQUEST_PROPERTY_TO_ATTRIBUTE = {
|
|
47
|
+
"method": "http.request.method",
|
|
48
|
+
"path": "url.path",
|
|
49
|
+
"query": "url.query",
|
|
50
|
+
"protocol": "url.scheme",
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
45
54
|
class TornadoIntegration(Integration):
|
|
46
55
|
identifier = "tornado"
|
|
47
56
|
origin = f"auto.http.{identifier}"
|
|
@@ -111,22 +120,19 @@ def _handle_request_impl(self):
|
|
|
111
120
|
processor = _make_event_processor(weak_handler)
|
|
112
121
|
scope.add_event_processor(processor)
|
|
113
122
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
transaction, custom_sampling_context={"tornado_request": self.request}
|
|
128
|
-
):
|
|
129
|
-
yield
|
|
123
|
+
with sentry_sdk.continue_trace(headers):
|
|
124
|
+
with sentry_sdk.start_span(
|
|
125
|
+
op=OP.HTTP_SERVER,
|
|
126
|
+
# Like with all other integrations, this is our
|
|
127
|
+
# fallback transaction in case there is no route.
|
|
128
|
+
# sentry_urldispatcher_resolve is responsible for
|
|
129
|
+
# setting a transaction name later.
|
|
130
|
+
name="generic Tornado request",
|
|
131
|
+
source=TransactionSource.ROUTE,
|
|
132
|
+
origin=TornadoIntegration.origin,
|
|
133
|
+
attributes=_prepopulate_attributes(self.request),
|
|
134
|
+
):
|
|
135
|
+
yield
|
|
130
136
|
|
|
131
137
|
|
|
132
138
|
@ensure_integration_enabled(TornadoIntegration)
|
|
@@ -218,3 +224,36 @@ class TornadoRequestExtractor(RequestExtractor):
|
|
|
218
224
|
def size_of_file(self, file):
|
|
219
225
|
# type: (Any) -> int
|
|
220
226
|
return len(file.body or ())
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def _prepopulate_attributes(request):
|
|
230
|
+
# type: (HTTPServerRequest) -> dict[str, Any]
|
|
231
|
+
# https://www.tornadoweb.org/en/stable/httputil.html#tornado.httputil.HTTPServerRequest
|
|
232
|
+
attributes = {}
|
|
233
|
+
|
|
234
|
+
for prop, attr in REQUEST_PROPERTY_TO_ATTRIBUTE.items():
|
|
235
|
+
if getattr(request, prop, None) is not None:
|
|
236
|
+
attributes[attr] = getattr(request, prop)
|
|
237
|
+
|
|
238
|
+
if getattr(request, "version", None):
|
|
239
|
+
try:
|
|
240
|
+
proto, version = request.version.split("/")
|
|
241
|
+
attributes["network.protocol.name"] = proto
|
|
242
|
+
attributes["network.protocol.version"] = version
|
|
243
|
+
except ValueError:
|
|
244
|
+
attributes["network.protocol.name"] = request.version
|
|
245
|
+
|
|
246
|
+
if getattr(request, "host", None):
|
|
247
|
+
try:
|
|
248
|
+
address, port = request.host.split(":")
|
|
249
|
+
attributes["server.address"] = address
|
|
250
|
+
attributes["server.port"] = port
|
|
251
|
+
except ValueError:
|
|
252
|
+
attributes["server.address"] = request.host
|
|
253
|
+
|
|
254
|
+
with capture_internal_exceptions():
|
|
255
|
+
attributes["url.full"] = request.full_url()
|
|
256
|
+
|
|
257
|
+
attributes.update(_request_headers_to_span_attributes(request.headers))
|
|
258
|
+
|
|
259
|
+
return attributes
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import sentry_sdk
|
|
2
|
-
from sentry_sdk.integrations import Integration
|
|
2
|
+
from sentry_sdk.integrations import _check_minimum_version, Integration
|
|
3
3
|
from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware
|
|
4
4
|
from sentry_sdk.utils import ensure_integration_enabled, event_from_exception
|
|
5
5
|
|
|
6
|
+
from trytond import __version__ as trytond_version # type: ignore
|
|
6
7
|
from trytond.exceptions import TrytonException # type: ignore
|
|
7
8
|
from trytond.wsgi import app # type: ignore
|
|
8
9
|
|
|
@@ -19,6 +20,8 @@ class TrytondWSGIIntegration(Integration):
|
|
|
19
20
|
|
|
20
21
|
@staticmethod
|
|
21
22
|
def setup_once(): # type: () -> None
|
|
23
|
+
_check_minimum_version(TrytondWSGIIntegration, trytond_version)
|
|
24
|
+
|
|
22
25
|
app.wsgi_app = SentryWsgiMiddleware(
|
|
23
26
|
app.wsgi_app,
|
|
24
27
|
span_origin=TrytondWSGIIntegration.origin,
|