sentry-sdk 3.0.0a2__py2.py3-none-any.whl → 3.0.0a4__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.

Files changed (159) hide show
  1. sentry_sdk/__init__.py +4 -0
  2. sentry_sdk/_compat.py +5 -12
  3. sentry_sdk/_init_implementation.py +7 -7
  4. sentry_sdk/_log_batcher.py +17 -29
  5. sentry_sdk/_lru_cache.py +7 -9
  6. sentry_sdk/_queue.py +2 -4
  7. sentry_sdk/_types.py +9 -16
  8. sentry_sdk/_werkzeug.py +5 -7
  9. sentry_sdk/ai/monitoring.py +45 -33
  10. sentry_sdk/ai/utils.py +8 -5
  11. sentry_sdk/api.py +91 -87
  12. sentry_sdk/attachments.py +10 -12
  13. sentry_sdk/client.py +119 -159
  14. sentry_sdk/consts.py +432 -223
  15. sentry_sdk/crons/api.py +16 -17
  16. sentry_sdk/crons/decorator.py +25 -27
  17. sentry_sdk/debug.py +4 -6
  18. sentry_sdk/envelope.py +46 -112
  19. sentry_sdk/feature_flags.py +9 -15
  20. sentry_sdk/integrations/__init__.py +24 -19
  21. sentry_sdk/integrations/_asgi_common.py +16 -18
  22. sentry_sdk/integrations/_wsgi_common.py +22 -33
  23. sentry_sdk/integrations/aiohttp.py +33 -31
  24. sentry_sdk/integrations/anthropic.py +43 -38
  25. sentry_sdk/integrations/argv.py +3 -4
  26. sentry_sdk/integrations/ariadne.py +16 -18
  27. sentry_sdk/integrations/arq.py +20 -29
  28. sentry_sdk/integrations/asgi.py +63 -37
  29. sentry_sdk/integrations/asyncio.py +15 -17
  30. sentry_sdk/integrations/asyncpg.py +1 -1
  31. sentry_sdk/integrations/atexit.py +6 -10
  32. sentry_sdk/integrations/aws_lambda.py +26 -36
  33. sentry_sdk/integrations/beam.py +10 -18
  34. sentry_sdk/integrations/boto3.py +20 -18
  35. sentry_sdk/integrations/bottle.py +25 -34
  36. sentry_sdk/integrations/celery/__init__.py +40 -59
  37. sentry_sdk/integrations/celery/beat.py +22 -26
  38. sentry_sdk/integrations/celery/utils.py +15 -17
  39. sentry_sdk/integrations/chalice.py +8 -10
  40. sentry_sdk/integrations/clickhouse_driver.py +22 -32
  41. sentry_sdk/integrations/cloud_resource_context.py +9 -16
  42. sentry_sdk/integrations/cohere.py +19 -25
  43. sentry_sdk/integrations/dedupe.py +5 -8
  44. sentry_sdk/integrations/django/__init__.py +69 -74
  45. sentry_sdk/integrations/django/asgi.py +25 -33
  46. sentry_sdk/integrations/django/caching.py +24 -20
  47. sentry_sdk/integrations/django/middleware.py +18 -21
  48. sentry_sdk/integrations/django/signals_handlers.py +12 -11
  49. sentry_sdk/integrations/django/templates.py +21 -18
  50. sentry_sdk/integrations/django/transactions.py +16 -11
  51. sentry_sdk/integrations/django/views.py +8 -12
  52. sentry_sdk/integrations/dramatiq.py +21 -21
  53. sentry_sdk/integrations/excepthook.py +10 -10
  54. sentry_sdk/integrations/executing.py +3 -4
  55. sentry_sdk/integrations/falcon.py +27 -42
  56. sentry_sdk/integrations/fastapi.py +13 -16
  57. sentry_sdk/integrations/flask.py +31 -38
  58. sentry_sdk/integrations/gcp.py +13 -16
  59. sentry_sdk/integrations/gnu_backtrace.py +7 -20
  60. sentry_sdk/integrations/gql.py +16 -17
  61. sentry_sdk/integrations/graphene.py +14 -13
  62. sentry_sdk/integrations/grpc/__init__.py +3 -2
  63. sentry_sdk/integrations/grpc/aio/client.py +2 -2
  64. sentry_sdk/integrations/grpc/aio/server.py +15 -14
  65. sentry_sdk/integrations/grpc/client.py +21 -11
  66. sentry_sdk/integrations/grpc/consts.py +2 -0
  67. sentry_sdk/integrations/grpc/server.py +12 -8
  68. sentry_sdk/integrations/httpx.py +11 -14
  69. sentry_sdk/integrations/huey.py +14 -21
  70. sentry_sdk/integrations/huggingface_hub.py +17 -17
  71. sentry_sdk/integrations/langchain.py +204 -114
  72. sentry_sdk/integrations/launchdarkly.py +13 -10
  73. sentry_sdk/integrations/litestar.py +40 -38
  74. sentry_sdk/integrations/logging.py +29 -36
  75. sentry_sdk/integrations/loguru.py +16 -20
  76. sentry_sdk/integrations/modules.py +3 -4
  77. sentry_sdk/integrations/openai.py +421 -204
  78. sentry_sdk/integrations/openai_agents/__init__.py +49 -0
  79. sentry_sdk/integrations/openai_agents/consts.py +1 -0
  80. sentry_sdk/integrations/openai_agents/patches/__init__.py +4 -0
  81. sentry_sdk/integrations/openai_agents/patches/agent_run.py +152 -0
  82. sentry_sdk/integrations/openai_agents/patches/models.py +52 -0
  83. sentry_sdk/integrations/openai_agents/patches/runner.py +42 -0
  84. sentry_sdk/integrations/openai_agents/patches/tools.py +84 -0
  85. sentry_sdk/integrations/openai_agents/spans/__init__.py +5 -0
  86. sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +20 -0
  87. sentry_sdk/integrations/openai_agents/spans/ai_client.py +46 -0
  88. sentry_sdk/integrations/openai_agents/spans/execute_tool.py +47 -0
  89. sentry_sdk/integrations/openai_agents/spans/handoff.py +24 -0
  90. sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +41 -0
  91. sentry_sdk/integrations/openai_agents/utils.py +153 -0
  92. sentry_sdk/integrations/openfeature.py +12 -8
  93. sentry_sdk/integrations/pure_eval.py +6 -10
  94. sentry_sdk/integrations/pymongo.py +14 -18
  95. sentry_sdk/integrations/pyramid.py +31 -36
  96. sentry_sdk/integrations/quart.py +23 -28
  97. sentry_sdk/integrations/ray.py +73 -64
  98. sentry_sdk/integrations/redis/__init__.py +7 -4
  99. sentry_sdk/integrations/redis/_async_common.py +18 -12
  100. sentry_sdk/integrations/redis/_sync_common.py +16 -15
  101. sentry_sdk/integrations/redis/modules/caches.py +17 -8
  102. sentry_sdk/integrations/redis/modules/queries.py +9 -8
  103. sentry_sdk/integrations/redis/rb.py +3 -2
  104. sentry_sdk/integrations/redis/redis.py +4 -4
  105. sentry_sdk/integrations/redis/redis_cluster.py +10 -8
  106. sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +3 -2
  107. sentry_sdk/integrations/redis/utils.py +21 -22
  108. sentry_sdk/integrations/rq.py +13 -16
  109. sentry_sdk/integrations/rust_tracing.py +10 -7
  110. sentry_sdk/integrations/sanic.py +34 -46
  111. sentry_sdk/integrations/serverless.py +22 -27
  112. sentry_sdk/integrations/socket.py +29 -17
  113. sentry_sdk/integrations/spark/__init__.py +1 -0
  114. sentry_sdk/integrations/spark/spark_driver.py +45 -83
  115. sentry_sdk/integrations/spark/spark_worker.py +7 -11
  116. sentry_sdk/integrations/sqlalchemy.py +22 -19
  117. sentry_sdk/integrations/starlette.py +89 -93
  118. sentry_sdk/integrations/starlite.py +31 -37
  119. sentry_sdk/integrations/statsig.py +5 -4
  120. sentry_sdk/integrations/stdlib.py +32 -28
  121. sentry_sdk/integrations/strawberry.py +63 -50
  122. sentry_sdk/integrations/sys_exit.py +7 -11
  123. sentry_sdk/integrations/threading.py +13 -15
  124. sentry_sdk/integrations/tornado.py +28 -32
  125. sentry_sdk/integrations/trytond.py +4 -3
  126. sentry_sdk/integrations/typer.py +8 -6
  127. sentry_sdk/integrations/unleash.py +5 -4
  128. sentry_sdk/integrations/wsgi.py +47 -46
  129. sentry_sdk/logger.py +13 -9
  130. sentry_sdk/monitor.py +16 -28
  131. sentry_sdk/opentelemetry/consts.py +11 -4
  132. sentry_sdk/opentelemetry/contextvars_context.py +17 -15
  133. sentry_sdk/opentelemetry/propagator.py +38 -21
  134. sentry_sdk/opentelemetry/sampler.py +51 -34
  135. sentry_sdk/opentelemetry/scope.py +46 -37
  136. sentry_sdk/opentelemetry/span_processor.py +43 -59
  137. sentry_sdk/opentelemetry/tracing.py +32 -12
  138. sentry_sdk/opentelemetry/utils.py +180 -196
  139. sentry_sdk/profiler/continuous_profiler.py +108 -97
  140. sentry_sdk/profiler/transaction_profiler.py +70 -97
  141. sentry_sdk/profiler/utils.py +11 -15
  142. sentry_sdk/scope.py +251 -264
  143. sentry_sdk/scrubber.py +22 -26
  144. sentry_sdk/serializer.py +48 -65
  145. sentry_sdk/session.py +44 -61
  146. sentry_sdk/sessions.py +35 -49
  147. sentry_sdk/spotlight.py +15 -21
  148. sentry_sdk/tracing.py +118 -184
  149. sentry_sdk/tracing_utils.py +103 -123
  150. sentry_sdk/transport.py +131 -157
  151. sentry_sdk/utils.py +278 -309
  152. sentry_sdk/worker.py +16 -28
  153. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/METADATA +1 -1
  154. sentry_sdk-3.0.0a4.dist-info/RECORD +168 -0
  155. sentry_sdk-3.0.0a2.dist-info/RECORD +0 -154
  156. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/WHEEL +0 -0
  157. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/entry_points.txt +0 -0
  158. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/licenses/LICENSE +0 -0
  159. {sentry_sdk-3.0.0a2.dist-info → sentry_sdk-3.0.0a4.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import functools
2
3
  import inspect
3
4
  import sys
@@ -8,7 +9,7 @@ from importlib import import_module
8
9
  import sentry_sdk
9
10
  from sentry_sdk.consts import OP, SPANDATA, SOURCE_FOR_STYLE, TransactionSource
10
11
  from sentry_sdk.scope import add_global_event_processor, should_send_default_pii
11
- from sentry_sdk.serializer import add_global_repr_processor
12
+ from sentry_sdk.serializer import add_global_repr_processor, add_repr_sequence_type
12
13
  from sentry_sdk.tracing_utils import add_query_source, record_sql_queries
13
14
  from sentry_sdk.utils import (
14
15
  AnnotatedValue,
@@ -107,18 +108,17 @@ class DjangoIntegration(Integration):
107
108
  middleware_spans = None
108
109
  signals_spans = None
109
110
  cache_spans = None
110
- signals_denylist = [] # type: list[signals.Signal]
111
+ signals_denylist: list[signals.Signal] = []
111
112
 
112
113
  def __init__(
113
114
  self,
114
- transaction_style="url", # type: str
115
- middleware_spans=True, # type: bool
116
- signals_spans=True, # type: bool
117
- cache_spans=True, # type: bool
118
- signals_denylist=None, # type: Optional[list[signals.Signal]]
119
- http_methods_to_capture=DEFAULT_HTTP_METHODS_TO_CAPTURE, # type: tuple[str, ...]
120
- ):
121
- # type: (...) -> None
115
+ transaction_style: str = "url",
116
+ middleware_spans: bool = True,
117
+ signals_spans: bool = True,
118
+ cache_spans: bool = True,
119
+ signals_denylist: Optional[list[signals.Signal]] = None,
120
+ http_methods_to_capture: tuple[str, ...] = DEFAULT_HTTP_METHODS_TO_CAPTURE,
121
+ ) -> None:
122
122
  if transaction_style not in TRANSACTION_STYLE_VALUES:
123
123
  raise ValueError(
124
124
  "Invalid value for transaction_style: %s (must be in %s)"
@@ -135,8 +135,7 @@ class DjangoIntegration(Integration):
135
135
  self.http_methods_to_capture = tuple(map(str.upper, http_methods_to_capture))
136
136
 
137
137
  @staticmethod
138
- def setup_once():
139
- # type: () -> None
138
+ def setup_once() -> None:
140
139
  _check_minimum_version(DjangoIntegration, DJANGO_VERSION)
141
140
 
142
141
  install_sql_hook()
@@ -151,8 +150,9 @@ class DjangoIntegration(Integration):
151
150
  old_app = WSGIHandler.__call__
152
151
 
153
152
  @ensure_integration_enabled(DjangoIntegration, old_app)
154
- def sentry_patched_wsgi_handler(self, environ, start_response):
155
- # type: (Any, Dict[str, str], Callable[..., Any]) -> _ScopedResponse
153
+ def sentry_patched_wsgi_handler(
154
+ self: Any, environ: Dict[str, str], start_response: Callable[..., Any]
155
+ ) -> _ScopedResponse:
156
156
  bound_old_app = old_app.__get__(self, WSGIHandler)
157
157
 
158
158
  from django.conf import settings
@@ -182,8 +182,9 @@ class DjangoIntegration(Integration):
182
182
  signals.got_request_exception.connect(_got_request_exception)
183
183
 
184
184
  @add_global_event_processor
185
- def process_django_templates(event, hint):
186
- # type: (Event, Optional[Hint]) -> Optional[Event]
185
+ def process_django_templates(
186
+ event: Event, hint: Optional[Hint]
187
+ ) -> Optional[Event]:
187
188
  if hint is None:
188
189
  return event
189
190
 
@@ -225,8 +226,9 @@ class DjangoIntegration(Integration):
225
226
  return event
226
227
 
227
228
  @add_global_repr_processor
228
- def _django_queryset_repr(value, hint):
229
- # type: (Any, Dict[str, Any]) -> Union[NotImplementedType, str]
229
+ def _django_queryset_repr(
230
+ value: Any, hint: Dict[str, Any]
231
+ ) -> Union[NotImplementedType, str]:
230
232
  try:
231
233
  # Django 1.6 can fail to import `QuerySet` when Django settings
232
234
  # have not yet been initialized.
@@ -252,6 +254,7 @@ class DjangoIntegration(Integration):
252
254
  patch_views()
253
255
  patch_templates()
254
256
  patch_signals()
257
+ add_template_context_repr_sequence()
255
258
 
256
259
  if patch_caching is not None:
257
260
  patch_caching()
@@ -261,8 +264,7 @@ _DRF_PATCHED = False
261
264
  _DRF_PATCH_LOCK = threading.Lock()
262
265
 
263
266
 
264
- def _patch_drf():
265
- # type: () -> None
267
+ def _patch_drf() -> None:
266
268
  """
267
269
  Patch Django Rest Framework for more/better request data. DRF's request
268
270
  type is a wrapper around Django's request type. The attribute we're
@@ -305,8 +307,9 @@ def _patch_drf():
305
307
  old_drf_initial = APIView.initial
306
308
 
307
309
  @functools.wraps(old_drf_initial)
308
- def sentry_patched_drf_initial(self, request, *args, **kwargs):
309
- # type: (APIView, Any, *Any, **Any) -> Any
310
+ def sentry_patched_drf_initial(
311
+ self: APIView, request: Any, *args: Any, **kwargs: Any
312
+ ) -> Any:
310
313
  with capture_internal_exceptions():
311
314
  request._request._sentry_drf_request_backref = weakref.ref(
312
315
  request
@@ -317,8 +320,7 @@ def _patch_drf():
317
320
  APIView.initial = sentry_patched_drf_initial
318
321
 
319
322
 
320
- def _patch_channels():
321
- # type: () -> None
323
+ def _patch_channels() -> None:
322
324
  try:
323
325
  from channels.http import AsgiHandler # type: ignore
324
326
  except ImportError:
@@ -342,8 +344,7 @@ def _patch_channels():
342
344
  patch_channels_asgi_handler_impl(AsgiHandler)
343
345
 
344
346
 
345
- def _patch_django_asgi_handler():
346
- # type: () -> None
347
+ def _patch_django_asgi_handler() -> None:
347
348
  try:
348
349
  from django.core.handlers.asgi import ASGIHandler
349
350
  except ImportError:
@@ -364,8 +365,9 @@ def _patch_django_asgi_handler():
364
365
  patch_django_asgi_handler_impl(ASGIHandler)
365
366
 
366
367
 
367
- def _set_transaction_name_and_source(scope, transaction_style, request):
368
- # type: (sentry_sdk.Scope, str, WSGIRequest) -> None
368
+ def _set_transaction_name_and_source(
369
+ scope: sentry_sdk.Scope, transaction_style: str, request: WSGIRequest
370
+ ) -> None:
369
371
  try:
370
372
  transaction_name = None
371
373
  if transaction_style == "function_name":
@@ -408,8 +410,7 @@ def _set_transaction_name_and_source(scope, transaction_style, request):
408
410
  pass
409
411
 
410
412
 
411
- def _before_get_response(request):
412
- # type: (WSGIRequest) -> None
413
+ def _before_get_response(request: WSGIRequest) -> None:
413
414
  integration = sentry_sdk.get_client().get_integration(DjangoIntegration)
414
415
  if integration is None:
415
416
  return
@@ -425,8 +426,9 @@ def _before_get_response(request):
425
426
  )
426
427
 
427
428
 
428
- def _attempt_resolve_again(request, scope, transaction_style):
429
- # type: (WSGIRequest, sentry_sdk.Scope, str) -> None
429
+ def _attempt_resolve_again(
430
+ request: WSGIRequest, scope: sentry_sdk.Scope, transaction_style: str
431
+ ) -> None:
430
432
  """
431
433
  Some django middlewares overwrite request.urlconf
432
434
  so we need to respect that contract,
@@ -438,8 +440,7 @@ def _attempt_resolve_again(request, scope, transaction_style):
438
440
  _set_transaction_name_and_source(scope, transaction_style, request)
439
441
 
440
442
 
441
- def _after_get_response(request):
442
- # type: (WSGIRequest) -> None
443
+ def _after_get_response(request: WSGIRequest) -> None:
443
444
  integration = sentry_sdk.get_client().get_integration(DjangoIntegration)
444
445
  if integration is None or integration.transaction_style != "url":
445
446
  return
@@ -448,8 +449,7 @@ def _after_get_response(request):
448
449
  _attempt_resolve_again(request, scope, integration.transaction_style)
449
450
 
450
451
 
451
- def _patch_get_response():
452
- # type: () -> None
452
+ def _patch_get_response() -> None:
453
453
  """
454
454
  patch get_response, because at that point we have the Django request object
455
455
  """
@@ -458,8 +458,9 @@ def _patch_get_response():
458
458
  old_get_response = BaseHandler.get_response
459
459
 
460
460
  @functools.wraps(old_get_response)
461
- def sentry_patched_get_response(self, request):
462
- # type: (Any, WSGIRequest) -> Union[HttpResponse, BaseException]
461
+ def sentry_patched_get_response(
462
+ self: Any, request: WSGIRequest
463
+ ) -> Union[HttpResponse, BaseException]:
463
464
  _before_get_response(request)
464
465
  rv = old_get_response(self, request)
465
466
  _after_get_response(request)
@@ -473,10 +474,10 @@ def _patch_get_response():
473
474
  patch_get_response_async(BaseHandler, _before_get_response)
474
475
 
475
476
 
476
- def _make_wsgi_request_event_processor(weak_request, integration):
477
- # type: (Callable[[], WSGIRequest], DjangoIntegration) -> EventProcessor
478
- def wsgi_request_event_processor(event, hint):
479
- # type: (Event, dict[str, Any]) -> Event
477
+ def _make_wsgi_request_event_processor(
478
+ weak_request: Callable[[], WSGIRequest], integration: DjangoIntegration
479
+ ) -> EventProcessor:
480
+ def wsgi_request_event_processor(event: Event, hint: dict[str, Any]) -> Event:
480
481
  # if the request is gone we are fine not logging the data from
481
482
  # it. This might happen if the processor is pushed away to
482
483
  # another thread.
@@ -501,8 +502,7 @@ def _make_wsgi_request_event_processor(weak_request, integration):
501
502
  return wsgi_request_event_processor
502
503
 
503
504
 
504
- def _got_request_exception(request=None, **kwargs):
505
- # type: (WSGIRequest, **Any) -> None
505
+ def _got_request_exception(request: WSGIRequest = None, **kwargs: Any) -> None:
506
506
  client = sentry_sdk.get_client()
507
507
  integration = client.get_integration(DjangoIntegration)
508
508
  if integration is None:
@@ -521,8 +521,7 @@ def _got_request_exception(request=None, **kwargs):
521
521
 
522
522
 
523
523
  class DjangoRequestExtractor(RequestExtractor):
524
- def __init__(self, request):
525
- # type: (Union[WSGIRequest, ASGIRequest]) -> None
524
+ def __init__(self, request: Union[WSGIRequest, ASGIRequest]) -> None:
526
525
  try:
527
526
  drf_request = request._sentry_drf_request_backref()
528
527
  if drf_request is not None:
@@ -531,18 +530,16 @@ class DjangoRequestExtractor(RequestExtractor):
531
530
  pass
532
531
  self.request = request
533
532
 
534
- def env(self):
535
- # type: () -> Dict[str, str]
533
+ def env(self) -> Dict[str, str]:
536
534
  return self.request.META
537
535
 
538
- def cookies(self):
539
- # type: () -> Dict[str, Union[str, AnnotatedValue]]
536
+ def cookies(self) -> Dict[str, Union[str, AnnotatedValue]]:
540
537
  privacy_cookies = [
541
538
  django_settings.CSRF_COOKIE_NAME,
542
539
  django_settings.SESSION_COOKIE_NAME,
543
540
  ]
544
541
 
545
- clean_cookies = {} # type: Dict[str, Union[str, AnnotatedValue]]
542
+ clean_cookies: Dict[str, Union[str, AnnotatedValue]] = {}
546
543
  for key, val in self.request.COOKIES.items():
547
544
  if key in privacy_cookies:
548
545
  clean_cookies[key] = SENSITIVE_DATA_SUBSTITUTE
@@ -551,32 +548,26 @@ class DjangoRequestExtractor(RequestExtractor):
551
548
 
552
549
  return clean_cookies
553
550
 
554
- def raw_data(self):
555
- # type: () -> bytes
551
+ def raw_data(self) -> bytes:
556
552
  return self.request.body
557
553
 
558
- def form(self):
559
- # type: () -> QueryDict
554
+ def form(self) -> QueryDict:
560
555
  return self.request.POST
561
556
 
562
- def files(self):
563
- # type: () -> MultiValueDict
557
+ def files(self) -> MultiValueDict:
564
558
  return self.request.FILES
565
559
 
566
- def size_of_file(self, file):
567
- # type: (Any) -> int
560
+ def size_of_file(self, file: Any) -> int:
568
561
  return file.size
569
562
 
570
- def parsed_body(self):
571
- # type: () -> Optional[Dict[str, Any]]
563
+ def parsed_body(self) -> Optional[Dict[str, Any]]:
572
564
  try:
573
565
  return self.request.data
574
566
  except Exception:
575
567
  return RequestExtractor.parsed_body(self)
576
568
 
577
569
 
578
- def _set_user_info(request, event):
579
- # type: (WSGIRequest, Event) -> None
570
+ def _set_user_info(request: WSGIRequest, event: Event) -> None:
580
571
  user_info = event.setdefault("user", {})
581
572
 
582
573
  user = getattr(request, "user", None)
@@ -600,8 +591,7 @@ def _set_user_info(request, event):
600
591
  pass
601
592
 
602
593
 
603
- def install_sql_hook():
604
- # type: () -> None
594
+ def install_sql_hook() -> None:
605
595
  """If installed this causes Django's queries to be captured."""
606
596
  try:
607
597
  from django.db.backends.utils import CursorWrapper
@@ -615,8 +605,7 @@ def install_sql_hook():
615
605
  real_connect = BaseDatabaseWrapper.connect
616
606
 
617
607
  @ensure_integration_enabled(DjangoIntegration, real_execute)
618
- def execute(self, sql, params=None):
619
- # type: (CursorWrapper, Any, Optional[Any]) -> Any
608
+ def execute(self: CursorWrapper, sql: Any, params: Optional[Any] = None) -> Any:
620
609
  with record_sql_queries(
621
610
  cursor=self.cursor,
622
611
  query=sql,
@@ -634,8 +623,7 @@ def install_sql_hook():
634
623
  return result
635
624
 
636
625
  @ensure_integration_enabled(DjangoIntegration, real_executemany)
637
- def executemany(self, sql, param_list):
638
- # type: (CursorWrapper, Any, List[Any]) -> Any
626
+ def executemany(self: CursorWrapper, sql: Any, param_list: List[Any]) -> Any:
639
627
  with record_sql_queries(
640
628
  cursor=self.cursor,
641
629
  query=sql,
@@ -654,8 +642,7 @@ def install_sql_hook():
654
642
  return result
655
643
 
656
644
  @ensure_integration_enabled(DjangoIntegration, real_connect)
657
- def connect(self):
658
- # type: (BaseDatabaseWrapper) -> None
645
+ def connect(self: BaseDatabaseWrapper) -> None:
659
646
  with capture_internal_exceptions():
660
647
  sentry_sdk.add_breadcrumb(message="connect", category="query")
661
648
 
@@ -663,7 +650,7 @@ def install_sql_hook():
663
650
  op=OP.DB,
664
651
  name="connect",
665
652
  origin=DjangoIntegration.origin_db,
666
- only_if_parent=True,
653
+ only_as_child_span=True,
667
654
  ) as span:
668
655
  _set_db_data(span, self)
669
656
  return real_connect(self)
@@ -674,8 +661,7 @@ def install_sql_hook():
674
661
  ignore_logger("django.db.backends")
675
662
 
676
663
 
677
- def _set_db_data(span, cursor_or_db):
678
- # type: (Span, Any) -> None
664
+ def _set_db_data(span: Span, cursor_or_db: Any) -> None:
679
665
  db = cursor_or_db.db if hasattr(cursor_or_db, "db") else cursor_or_db
680
666
  vendor = db.vendor
681
667
  span.set_attribute(SPANDATA.DB_SYSTEM, vendor)
@@ -724,3 +710,12 @@ def _set_db_data(span, cursor_or_db):
724
710
  server_socket_address = connection_params.get("unix_socket")
725
711
  if server_socket_address is not None:
726
712
  span.set_attribute(SPANDATA.SERVER_SOCKET_ADDRESS, server_socket_address)
713
+
714
+
715
+ def add_template_context_repr_sequence() -> None:
716
+ try:
717
+ from django.template.context import BaseContext
718
+
719
+ add_repr_sequence_type(BaseContext)
720
+ except Exception:
721
+ pass
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  """
2
4
  Instrumentation for Django 3.0
3
5
 
@@ -51,10 +53,8 @@ else:
51
53
  return func
52
54
 
53
55
 
54
- def _make_asgi_request_event_processor(request):
55
- # type: (ASGIRequest) -> EventProcessor
56
- def asgi_request_event_processor(event, hint):
57
- # type: (Event, dict[str, Any]) -> Event
56
+ def _make_asgi_request_event_processor(request: ASGIRequest) -> EventProcessor:
57
+ def asgi_request_event_processor(event: Event, hint: dict[str, Any]) -> Event:
58
58
  # if the request is gone we are fine not logging the data from
59
59
  # it. This might happen if the processor is pushed away to
60
60
  # another thread.
@@ -81,16 +81,16 @@ def _make_asgi_request_event_processor(request):
81
81
  return asgi_request_event_processor
82
82
 
83
83
 
84
- def patch_django_asgi_handler_impl(cls):
85
- # type: (Any) -> None
84
+ def patch_django_asgi_handler_impl(cls: Any) -> None:
86
85
 
87
86
  from sentry_sdk.integrations.django import DjangoIntegration
88
87
 
89
88
  old_app = cls.__call__
90
89
 
91
90
  @functools.wraps(old_app)
92
- async def sentry_patched_asgi_handler(self, scope, receive, send):
93
- # type: (Any, Any, Any, Any) -> Any
91
+ async def sentry_patched_asgi_handler(
92
+ self: Any, scope: Any, receive: Any, send: Any
93
+ ) -> Any:
94
94
  integration = sentry_sdk.get_client().get_integration(DjangoIntegration)
95
95
  if integration is None:
96
96
  return await old_app(self, scope, receive, send)
@@ -111,8 +111,7 @@ def patch_django_asgi_handler_impl(cls):
111
111
  old_create_request = cls.create_request
112
112
 
113
113
  @ensure_integration_enabled(DjangoIntegration, old_create_request)
114
- def sentry_patched_create_request(self, *args, **kwargs):
115
- # type: (Any, *Any, **Any) -> Any
114
+ def sentry_patched_create_request(self: Any, *args: Any, **kwargs: Any) -> Any:
116
115
  request, error_response = old_create_request(self, *args, **kwargs)
117
116
  scope = sentry_sdk.get_isolation_scope()
118
117
  scope.add_event_processor(_make_asgi_request_event_processor(request))
@@ -122,21 +121,20 @@ def patch_django_asgi_handler_impl(cls):
122
121
  cls.create_request = sentry_patched_create_request
123
122
 
124
123
 
125
- def patch_get_response_async(cls, _before_get_response):
126
- # type: (Any, Any) -> None
124
+ def patch_get_response_async(cls: Any, _before_get_response: Any) -> None:
127
125
  old_get_response_async = cls.get_response_async
128
126
 
129
127
  @functools.wraps(old_get_response_async)
130
- async def sentry_patched_get_response_async(self, request):
131
- # type: (Any, Any) -> Union[HttpResponse, BaseException]
128
+ async def sentry_patched_get_response_async(
129
+ self: Any, request: Any
130
+ ) -> Union[HttpResponse, BaseException]:
132
131
  _before_get_response(request)
133
132
  return await old_get_response_async(self, request)
134
133
 
135
134
  cls.get_response_async = sentry_patched_get_response_async
136
135
 
137
136
 
138
- def patch_channels_asgi_handler_impl(cls):
139
- # type: (Any) -> None
137
+ def patch_channels_asgi_handler_impl(cls: Any) -> None:
140
138
  import channels # type: ignore
141
139
 
142
140
  from sentry_sdk.integrations.django import DjangoIntegration
@@ -145,8 +143,9 @@ def patch_channels_asgi_handler_impl(cls):
145
143
  old_app = cls.__call__
146
144
 
147
145
  @functools.wraps(old_app)
148
- async def sentry_patched_asgi_handler(self, receive, send):
149
- # type: (Any, Any, Any) -> Any
146
+ async def sentry_patched_asgi_handler(
147
+ self: Any, receive: Any, send: Any
148
+ ) -> Any:
150
149
  integration = sentry_sdk.get_client().get_integration(DjangoIntegration)
151
150
  if integration is None:
152
151
  return await old_app(self, receive, send)
@@ -168,13 +167,11 @@ def patch_channels_asgi_handler_impl(cls):
168
167
  patch_django_asgi_handler_impl(cls)
169
168
 
170
169
 
171
- def wrap_async_view(callback):
172
- # type: (Any) -> Any
170
+ def wrap_async_view(callback: Any) -> Any:
173
171
  from sentry_sdk.integrations.django import DjangoIntegration
174
172
 
175
173
  @functools.wraps(callback)
176
- async def sentry_wrapped_callback(request, *args, **kwargs):
177
- # type: (Any, *Any, **Any) -> Any
174
+ async def sentry_wrapped_callback(request: Any, *args: Any, **kwargs: Any) -> Any:
178
175
  current_scope = sentry_sdk.get_current_scope()
179
176
  if current_scope.root_span is not None:
180
177
  current_scope.root_span.update_active_thread()
@@ -187,15 +184,14 @@ def wrap_async_view(callback):
187
184
  op=OP.VIEW_RENDER,
188
185
  name=request.resolver_match.view_name,
189
186
  origin=DjangoIntegration.origin,
190
- only_if_parent=True,
187
+ only_as_child_span=True,
191
188
  ):
192
189
  return await callback(request, *args, **kwargs)
193
190
 
194
191
  return sentry_wrapped_callback
195
192
 
196
193
 
197
- def _asgi_middleware_mixin_factory(_check_middleware_span):
198
- # type: (Callable[..., Any]) -> Any
194
+ def _asgi_middleware_mixin_factory(_check_middleware_span: Callable[..., Any]) -> Any:
199
195
  """
200
196
  Mixin class factory that generates a middleware mixin for handling requests
201
197
  in async mode.
@@ -205,14 +201,12 @@ def _asgi_middleware_mixin_factory(_check_middleware_span):
205
201
  if TYPE_CHECKING:
206
202
  _inner = None
207
203
 
208
- def __init__(self, get_response):
209
- # type: (Callable[..., Any]) -> None
204
+ def __init__(self, get_response: Callable[..., Any]) -> None:
210
205
  self.get_response = get_response
211
206
  self._acall_method = None
212
207
  self._async_check()
213
208
 
214
- def _async_check(self):
215
- # type: () -> None
209
+ def _async_check(self) -> None:
216
210
  """
217
211
  If get_response is a coroutine function, turns us into async mode so
218
212
  a thread is not consumed during a whole request.
@@ -221,16 +215,14 @@ def _asgi_middleware_mixin_factory(_check_middleware_span):
221
215
  if iscoroutinefunction(self.get_response):
222
216
  markcoroutinefunction(self)
223
217
 
224
- def async_route_check(self):
225
- # type: () -> bool
218
+ def async_route_check(self) -> bool:
226
219
  """
227
220
  Function that checks if we are in async mode,
228
221
  and if we are forwards the handling of requests to __acall__
229
222
  """
230
223
  return iscoroutinefunction(self.get_response)
231
224
 
232
- async def __acall__(self, *args, **kwargs):
233
- # type: (*Any, **Any) -> Any
225
+ async def __acall__(self, *args: Any, **kwargs: Any) -> Any:
234
226
  f = self._acall_method
235
227
  if f is None:
236
228
  if hasattr(self._inner, "__acall__"):
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import functools
2
3
  from typing import TYPE_CHECKING
3
4
  from sentry_sdk.integrations.redis.utils import _get_safe_key, _key_as_string
@@ -28,22 +29,29 @@ METHODS_TO_INSTRUMENT = [
28
29
  ]
29
30
 
30
31
 
31
- def _get_span_description(method_name, args, kwargs):
32
- # type: (str, tuple[Any], dict[str, Any]) -> str
32
+ def _get_span_description(
33
+ method_name: str, args: tuple[Any], kwargs: dict[str, Any]
34
+ ) -> str:
33
35
  return _key_as_string(_get_safe_key(method_name, args, kwargs))
34
36
 
35
37
 
36
- def _patch_cache_method(cache, method_name, address, port):
37
- # type: (CacheHandler, str, Optional[str], Optional[int]) -> None
38
+ def _patch_cache_method(
39
+ cache: CacheHandler, method_name: str, address: Optional[str], port: Optional[int]
40
+ ) -> None:
38
41
  from sentry_sdk.integrations.django import DjangoIntegration
39
42
 
40
43
  original_method = getattr(cache, method_name)
41
44
 
42
45
  @ensure_integration_enabled(DjangoIntegration, original_method)
43
46
  def _instrument_call(
44
- cache, method_name, original_method, args, kwargs, address, port
45
- ):
46
- # type: (CacheHandler, str, Callable[..., Any], tuple[Any, ...], dict[str, Any], Optional[str], Optional[int]) -> Any
47
+ cache: CacheHandler,
48
+ method_name: str,
49
+ original_method: Callable[..., Any],
50
+ args: tuple[Any, ...],
51
+ kwargs: dict[str, Any],
52
+ address: Optional[str],
53
+ port: Optional[int],
54
+ ) -> Any:
47
55
  is_set_operation = method_name.startswith("set")
48
56
  is_get_operation = not is_set_operation
49
57
 
@@ -54,7 +62,7 @@ def _patch_cache_method(cache, method_name, address, port):
54
62
  op=op,
55
63
  name=description,
56
64
  origin=DjangoIntegration.origin,
57
- only_if_parent=True,
65
+ only_as_child_span=True,
58
66
  ) as span:
59
67
  value = original_method(*args, **kwargs)
60
68
 
@@ -91,8 +99,7 @@ def _patch_cache_method(cache, method_name, address, port):
91
99
  return value
92
100
 
93
101
  @functools.wraps(original_method)
94
- def sentry_method(*args, **kwargs):
95
- # type: (*Any, **Any) -> Any
102
+ def sentry_method(*args: Any, **kwargs: Any) -> Any:
96
103
  return _instrument_call(
97
104
  cache, method_name, original_method, args, kwargs, address, port
98
105
  )
@@ -100,16 +107,16 @@ def _patch_cache_method(cache, method_name, address, port):
100
107
  setattr(cache, method_name, sentry_method)
101
108
 
102
109
 
103
- def _patch_cache(cache, address=None, port=None):
104
- # type: (CacheHandler, Optional[str], Optional[int]) -> None
110
+ def _patch_cache(
111
+ cache: CacheHandler, address: Optional[str] = None, port: Optional[int] = None
112
+ ) -> None:
105
113
  if not hasattr(cache, "_sentry_patched"):
106
114
  for method_name in METHODS_TO_INSTRUMENT:
107
115
  _patch_cache_method(cache, method_name, address, port)
108
116
  cache._sentry_patched = True
109
117
 
110
118
 
111
- def _get_address_port(settings):
112
- # type: (dict[str, Any]) -> tuple[Optional[str], Optional[int]]
119
+ def _get_address_port(settings: dict[str, Any]) -> tuple[Optional[str], Optional[int]]:
113
120
  location = settings.get("LOCATION")
114
121
 
115
122
  # TODO: location can also be an array of locations
@@ -134,8 +141,7 @@ def _get_address_port(settings):
134
141
  return address, int(port) if port is not None else None
135
142
 
136
143
 
137
- def patch_caching():
138
- # type: () -> None
144
+ def patch_caching() -> None:
139
145
  from sentry_sdk.integrations.django import DjangoIntegration
140
146
 
141
147
  if not hasattr(CacheHandler, "_sentry_patched"):
@@ -143,8 +149,7 @@ def patch_caching():
143
149
  original_get_item = CacheHandler.__getitem__
144
150
 
145
151
  @functools.wraps(original_get_item)
146
- def sentry_get_item(self, alias):
147
- # type: (CacheHandler, str) -> Any
152
+ def sentry_get_item(self: CacheHandler, alias: str) -> Any:
148
153
  cache = original_get_item(self, alias)
149
154
 
150
155
  integration = sentry_sdk.get_client().get_integration(DjangoIntegration)
@@ -166,8 +171,7 @@ def patch_caching():
166
171
  original_create_connection = CacheHandler.create_connection
167
172
 
168
173
  @functools.wraps(original_create_connection)
169
- def sentry_create_connection(self, alias):
170
- # type: (CacheHandler, str) -> Any
174
+ def sentry_create_connection(self: CacheHandler, alias: str) -> Any:
171
175
  cache = original_create_connection(self, alias)
172
176
 
173
177
  integration = sentry_sdk.get_client().get_integration(DjangoIntegration)