sentry-sdk 2.30.0__py2.py3-none-any.whl → 3.0.0a2__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 (109) hide show
  1. sentry_sdk/__init__.py +3 -8
  2. sentry_sdk/_compat.py +0 -1
  3. sentry_sdk/_init_implementation.py +6 -44
  4. sentry_sdk/_types.py +2 -64
  5. sentry_sdk/ai/monitoring.py +14 -10
  6. sentry_sdk/ai/utils.py +1 -1
  7. sentry_sdk/api.py +56 -169
  8. sentry_sdk/client.py +27 -72
  9. sentry_sdk/consts.py +60 -23
  10. sentry_sdk/debug.py +0 -10
  11. sentry_sdk/envelope.py +1 -3
  12. sentry_sdk/feature_flags.py +1 -1
  13. sentry_sdk/integrations/__init__.py +4 -2
  14. sentry_sdk/integrations/_asgi_common.py +5 -6
  15. sentry_sdk/integrations/_wsgi_common.py +11 -40
  16. sentry_sdk/integrations/aiohttp.py +104 -57
  17. sentry_sdk/integrations/anthropic.py +10 -7
  18. sentry_sdk/integrations/arq.py +24 -13
  19. sentry_sdk/integrations/asgi.py +102 -83
  20. sentry_sdk/integrations/asyncio.py +1 -0
  21. sentry_sdk/integrations/asyncpg.py +45 -30
  22. sentry_sdk/integrations/aws_lambda.py +109 -92
  23. sentry_sdk/integrations/boto3.py +38 -9
  24. sentry_sdk/integrations/bottle.py +1 -1
  25. sentry_sdk/integrations/celery/__init__.py +51 -41
  26. sentry_sdk/integrations/clickhouse_driver.py +59 -28
  27. sentry_sdk/integrations/cohere.py +2 -0
  28. sentry_sdk/integrations/django/__init__.py +25 -46
  29. sentry_sdk/integrations/django/asgi.py +6 -2
  30. sentry_sdk/integrations/django/caching.py +13 -22
  31. sentry_sdk/integrations/django/middleware.py +1 -0
  32. sentry_sdk/integrations/django/signals_handlers.py +3 -1
  33. sentry_sdk/integrations/django/templates.py +8 -12
  34. sentry_sdk/integrations/django/transactions.py +1 -6
  35. sentry_sdk/integrations/django/views.py +5 -2
  36. sentry_sdk/integrations/falcon.py +7 -25
  37. sentry_sdk/integrations/fastapi.py +3 -3
  38. sentry_sdk/integrations/flask.py +1 -1
  39. sentry_sdk/integrations/gcp.py +63 -38
  40. sentry_sdk/integrations/graphene.py +6 -13
  41. sentry_sdk/integrations/grpc/aio/client.py +14 -8
  42. sentry_sdk/integrations/grpc/aio/server.py +19 -21
  43. sentry_sdk/integrations/grpc/client.py +8 -6
  44. sentry_sdk/integrations/grpc/server.py +12 -14
  45. sentry_sdk/integrations/httpx.py +47 -12
  46. sentry_sdk/integrations/huey.py +26 -22
  47. sentry_sdk/integrations/huggingface_hub.py +1 -0
  48. sentry_sdk/integrations/langchain.py +22 -15
  49. sentry_sdk/integrations/litestar.py +4 -2
  50. sentry_sdk/integrations/logging.py +7 -2
  51. sentry_sdk/integrations/openai.py +2 -0
  52. sentry_sdk/integrations/pymongo.py +18 -25
  53. sentry_sdk/integrations/pyramid.py +1 -1
  54. sentry_sdk/integrations/quart.py +3 -3
  55. sentry_sdk/integrations/ray.py +23 -17
  56. sentry_sdk/integrations/redis/_async_common.py +29 -18
  57. sentry_sdk/integrations/redis/_sync_common.py +28 -19
  58. sentry_sdk/integrations/redis/modules/caches.py +13 -10
  59. sentry_sdk/integrations/redis/modules/queries.py +14 -11
  60. sentry_sdk/integrations/redis/rb.py +4 -4
  61. sentry_sdk/integrations/redis/redis.py +6 -6
  62. sentry_sdk/integrations/redis/redis_cluster.py +18 -18
  63. sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +4 -4
  64. sentry_sdk/integrations/redis/utils.py +64 -24
  65. sentry_sdk/integrations/rq.py +68 -23
  66. sentry_sdk/integrations/rust_tracing.py +28 -43
  67. sentry_sdk/integrations/sanic.py +23 -13
  68. sentry_sdk/integrations/socket.py +9 -5
  69. sentry_sdk/integrations/sqlalchemy.py +8 -8
  70. sentry_sdk/integrations/starlette.py +11 -31
  71. sentry_sdk/integrations/starlite.py +4 -2
  72. sentry_sdk/integrations/stdlib.py +56 -9
  73. sentry_sdk/integrations/strawberry.py +40 -59
  74. sentry_sdk/integrations/threading.py +10 -26
  75. sentry_sdk/integrations/tornado.py +57 -18
  76. sentry_sdk/integrations/trytond.py +4 -1
  77. sentry_sdk/integrations/wsgi.py +84 -38
  78. sentry_sdk/opentelemetry/__init__.py +9 -0
  79. sentry_sdk/opentelemetry/consts.py +33 -0
  80. sentry_sdk/opentelemetry/contextvars_context.py +81 -0
  81. sentry_sdk/{integrations/opentelemetry → opentelemetry}/propagator.py +19 -28
  82. sentry_sdk/opentelemetry/sampler.py +326 -0
  83. sentry_sdk/opentelemetry/scope.py +218 -0
  84. sentry_sdk/opentelemetry/span_processor.py +335 -0
  85. sentry_sdk/opentelemetry/tracing.py +59 -0
  86. sentry_sdk/opentelemetry/utils.py +484 -0
  87. sentry_sdk/profiler/__init__.py +0 -40
  88. sentry_sdk/profiler/continuous_profiler.py +1 -30
  89. sentry_sdk/profiler/transaction_profiler.py +5 -56
  90. sentry_sdk/scope.py +108 -361
  91. sentry_sdk/sessions.py +0 -87
  92. sentry_sdk/tracing.py +415 -1161
  93. sentry_sdk/tracing_utils.py +130 -166
  94. sentry_sdk/transport.py +4 -104
  95. sentry_sdk/utils.py +169 -152
  96. {sentry_sdk-2.30.0.dist-info → sentry_sdk-3.0.0a2.dist-info}/METADATA +3 -5
  97. sentry_sdk-3.0.0a2.dist-info/RECORD +154 -0
  98. sentry_sdk-3.0.0a2.dist-info/entry_points.txt +2 -0
  99. sentry_sdk/hub.py +0 -739
  100. sentry_sdk/integrations/opentelemetry/__init__.py +0 -7
  101. sentry_sdk/integrations/opentelemetry/consts.py +0 -5
  102. sentry_sdk/integrations/opentelemetry/integration.py +0 -58
  103. sentry_sdk/integrations/opentelemetry/span_processor.py +0 -391
  104. sentry_sdk/metrics.py +0 -965
  105. sentry_sdk-2.30.0.dist-info/RECORD +0 -152
  106. sentry_sdk-2.30.0.dist-info/entry_points.txt +0 -2
  107. {sentry_sdk-2.30.0.dist-info → sentry_sdk-3.0.0a2.dist-info}/WHEEL +0 -0
  108. {sentry_sdk-2.30.0.dist-info → sentry_sdk-3.0.0a2.dist-info}/licenses/LICENSE +0 -0
  109. {sentry_sdk-2.30.0.dist-info → sentry_sdk-3.0.0a2.dist-info}/top_level.txt +0 -0
sentry_sdk/client.py CHANGED
@@ -6,10 +6,9 @@ from collections.abc import Mapping
6
6
  from datetime import datetime, timezone
7
7
  from importlib import import_module
8
8
  from typing import TYPE_CHECKING, List, Dict, cast, overload
9
- import warnings
10
9
 
11
10
  import sentry_sdk
12
- from sentry_sdk._compat import PY37, check_uwsgi_thread_support
11
+ from sentry_sdk._compat import check_uwsgi_thread_support
13
12
  from sentry_sdk.utils import (
14
13
  AnnotatedValue,
15
14
  ContextVar,
@@ -21,7 +20,6 @@ from sentry_sdk.utils import (
21
20
  get_type_name,
22
21
  get_default_release,
23
22
  handle_in_app,
24
- is_gevent,
25
23
  logger,
26
24
  )
27
25
  from sentry_sdk.serializer import serialize
@@ -31,14 +29,14 @@ from sentry_sdk.consts import (
31
29
  SPANDATA,
32
30
  DEFAULT_MAX_VALUE_LENGTH,
33
31
  DEFAULT_OPTIONS,
34
- INSTRUMENTER,
35
32
  VERSION,
36
33
  ClientConstructor,
37
34
  )
38
- from sentry_sdk.integrations import _DEFAULT_INTEGRATIONS, setup_integrations
35
+ from sentry_sdk.integrations import setup_integrations
39
36
  from sentry_sdk.integrations.dedupe import DedupeIntegration
40
37
  from sentry_sdk.sessions import SessionFlusher
41
38
  from sentry_sdk.envelope import Envelope
39
+
42
40
  from sentry_sdk.profiler.continuous_profiler import setup_continuous_profiler
43
41
  from sentry_sdk.profiler.transaction_profiler import (
44
42
  has_profiling_enabled,
@@ -60,7 +58,6 @@ if TYPE_CHECKING:
60
58
 
61
59
  from sentry_sdk._types import Event, Hint, SDKInfo, Log
62
60
  from sentry_sdk.integrations import Integration
63
- from sentry_sdk.metrics import MetricsAggregator
64
61
  from sentry_sdk.scope import Scope
65
62
  from sentry_sdk.session import Session
66
63
  from sentry_sdk.spotlight import SpotlightClient
@@ -116,9 +113,6 @@ def _get_options(*args, **kwargs):
116
113
  if rv["server_name"] is None and hasattr(socket, "gethostname"):
117
114
  rv["server_name"] = socket.gethostname()
118
115
 
119
- if rv["instrumenter"] is None:
120
- rv["instrumenter"] = INSTRUMENTER.SENTRY
121
-
122
116
  if rv["project_root"] is None:
123
117
  try:
124
118
  project_root = os.getcwd()
@@ -127,9 +121,6 @@ def _get_options(*args, **kwargs):
127
121
 
128
122
  rv["project_root"] = project_root
129
123
 
130
- if rv["enable_tracing"] is True and rv["traces_sample_rate"] is None:
131
- rv["traces_sample_rate"] = 1.0
132
-
133
124
  if rv["event_scrubber"] is None:
134
125
  rv["event_scrubber"] = EventScrubber(
135
126
  send_default_pii=(
@@ -148,24 +139,9 @@ def _get_options(*args, **kwargs):
148
139
  env_to_bool(os.environ.get("SENTRY_KEEP_ALIVE"), strict=True) or False
149
140
  )
150
141
 
151
- if rv["enable_tracing"] is not None:
152
- warnings.warn(
153
- "The `enable_tracing` parameter is deprecated. Please use `traces_sample_rate` instead.",
154
- DeprecationWarning,
155
- stacklevel=2,
156
- )
157
-
158
142
  return rv
159
143
 
160
144
 
161
- try:
162
- # Python 3.6+
163
- module_not_found_error = ModuleNotFoundError
164
- except Exception:
165
- # Older Python versions
166
- module_not_found_error = ImportError # type: ignore
167
-
168
-
169
145
  class BaseClient:
170
146
  """
171
147
  .. versionadded:: 2.0.0
@@ -183,7 +159,6 @@ class BaseClient:
183
159
 
184
160
  self.transport = None # type: Optional[Transport]
185
161
  self.monitor = None # type: Optional[Monitor]
186
- self.metrics_aggregator = None # type: Optional[MetricsAggregator]
187
162
  self.log_batcher = None # type: Optional[LogBatcher]
188
163
 
189
164
  def __getstate__(self, *args, **kwargs):
@@ -309,7 +284,7 @@ class _Client(BaseClient):
309
284
  function_obj = getattr(module_obj, function_name)
310
285
  setattr(module_obj, function_name, trace(function_obj))
311
286
  logger.debug("Enabled tracing for %s", function_qualname)
312
- except module_not_found_error:
287
+ except ModuleNotFoundError:
313
288
  try:
314
289
  # Try to import a class
315
290
  # ex: "mymodule.submodule.MyClassName.member_function"
@@ -362,26 +337,7 @@ class _Client(BaseClient):
362
337
 
363
338
  self.session_flusher = SessionFlusher(capture_func=_capture_envelope)
364
339
 
365
- self.metrics_aggregator = None # type: Optional[MetricsAggregator]
366
340
  experiments = self.options.get("_experiments", {})
367
- if experiments.get("enable_metrics", True):
368
- # Context vars are not working correctly on Python <=3.6
369
- # with gevent.
370
- metrics_supported = not is_gevent() or PY37
371
- if metrics_supported:
372
- from sentry_sdk.metrics import MetricsAggregator
373
-
374
- self.metrics_aggregator = MetricsAggregator(
375
- capture_func=_capture_envelope,
376
- enable_code_locations=bool(
377
- experiments.get("metric_code_locations", True)
378
- ),
379
- )
380
- else:
381
- logger.info(
382
- "Metrics not supported on Python 3.6 and lower with gevent."
383
- )
384
-
385
341
  self.log_batcher = None
386
342
  if experiments.get("enable_logs", False):
387
343
  from sentry_sdk._log_batcher import LogBatcher
@@ -396,19 +352,6 @@ class _Client(BaseClient):
396
352
  )
397
353
  )
398
354
 
399
- if self.options["_experiments"].get("otel_powered_performance", False):
400
- logger.debug(
401
- "[OTel] Enabling experimental OTel-powered performance monitoring."
402
- )
403
- self.options["instrumenter"] = INSTRUMENTER.OTEL
404
- if (
405
- "sentry_sdk.integrations.opentelemetry.integration.OpenTelemetryIntegration"
406
- not in _DEFAULT_INTEGRATIONS
407
- ):
408
- _DEFAULT_INTEGRATIONS.append(
409
- "sentry_sdk.integrations.opentelemetry.integration.OpenTelemetryIntegration",
410
- )
411
-
412
355
  self.integrations = setup_integrations(
413
356
  self.options["integrations"],
414
357
  with_defaults=self.options["default_integrations"],
@@ -456,6 +399,15 @@ class _Client(BaseClient):
456
399
  except Exception as e:
457
400
  logger.debug("Can not set up continuous profiler. (%s)", e)
458
401
 
402
+ from sentry_sdk.opentelemetry.tracing import (
403
+ patch_readable_span,
404
+ setup_sentry_tracing,
405
+ )
406
+
407
+ patch_readable_span()
408
+ setup_sentry_tracing()
409
+
410
+ logger.debug("[Tracing] Finished setting up OpenTelemetry")
459
411
  finally:
460
412
  _client_init_debug.set(old_debug)
461
413
 
@@ -463,7 +415,6 @@ class _Client(BaseClient):
463
415
 
464
416
  if (
465
417
  self.monitor
466
- or self.metrics_aggregator
467
418
  or self.log_batcher
468
419
  or has_profiling_enabled(self.options)
469
420
  or isinstance(self.transport, BaseHttpTransport)
@@ -530,7 +481,7 @@ class _Client(BaseClient):
530
481
  )
531
482
  return None
532
483
 
533
- event = event_
484
+ event = event_ # type: Optional[Event] # type: ignore[no-redef]
534
485
  spans_delta = spans_before - len(
535
486
  cast(List[Dict[str, object]], event.get("spans", []))
536
487
  )
@@ -627,7 +578,7 @@ class _Client(BaseClient):
627
578
  and event is not None
628
579
  and event.get("type") != "transaction"
629
580
  ):
630
- new_event = None
581
+ new_event = None # type: Optional[Event]
631
582
  with capture_internal_exceptions():
632
583
  new_event = before_send(event, hint or {})
633
584
  if new_event is None:
@@ -644,7 +595,7 @@ class _Client(BaseClient):
644
595
  if event.get("exception"):
645
596
  DedupeIntegration.reset_last_seen()
646
597
 
647
- event = new_event
598
+ event = new_event # type: Optional[Event] # type: ignore[no-redef]
648
599
 
649
600
  before_send_transaction = self.options["before_send_transaction"]
650
601
  if (
@@ -668,13 +619,15 @@ class _Client(BaseClient):
668
619
  quantity=spans_before + 1, # +1 for the transaction itself
669
620
  )
670
621
  else:
671
- spans_delta = spans_before - len(new_event.get("spans", []))
622
+ spans_delta = spans_before - len(
623
+ cast(List[Dict[str, object]], new_event.get("spans", []))
624
+ )
672
625
  if spans_delta > 0 and self.transport is not None:
673
626
  self.transport.record_lost_event(
674
627
  reason="before_send", data_category="span", quantity=spans_delta
675
628
  )
676
629
 
677
- event = new_event
630
+ event = new_event # type: Optional[Event] # type: ignore[no-redef]
678
631
 
679
632
  return event
680
633
 
@@ -923,7 +876,7 @@ class _Client(BaseClient):
923
876
  log["attributes"]["sentry.trace.parent_span_id"] = span.span_id
924
877
 
925
878
  if log.get("trace_id") is None:
926
- transaction = current_scope.transaction
879
+ transaction = current_scope.root_span
927
880
  propagation_context = isolation_scope.get_active_propagation_context()
928
881
  if transaction is not None:
929
882
  log["trace_id"] = transaction.trace_id
@@ -1010,13 +963,15 @@ class _Client(BaseClient):
1010
963
  """
1011
964
  if self.transport is not None:
1012
965
  self.flush(timeout=timeout, callback=callback)
966
+
1013
967
  self.session_flusher.kill()
1014
- if self.metrics_aggregator is not None:
1015
- self.metrics_aggregator.kill()
968
+
1016
969
  if self.log_batcher is not None:
1017
970
  self.log_batcher.kill()
971
+
1018
972
  if self.monitor:
1019
973
  self.monitor.kill()
974
+
1020
975
  self.transport.kill()
1021
976
  self.transport = None
1022
977
 
@@ -1037,10 +992,10 @@ class _Client(BaseClient):
1037
992
  if timeout is None:
1038
993
  timeout = self.options["shutdown_timeout"]
1039
994
  self.session_flusher.flush()
1040
- if self.metrics_aggregator is not None:
1041
- self.metrics_aggregator.flush()
995
+
1042
996
  if self.log_batcher is not None:
1043
997
  self.log_batcher.flush()
998
+
1044
999
  self.transport.flush(timeout=timeout, callback=callback)
1045
1000
 
1046
1001
  def __enter__(self):
sentry_sdk/consts.py CHANGED
@@ -47,12 +47,9 @@ if TYPE_CHECKING:
47
47
  EventProcessor,
48
48
  Hint,
49
49
  Log,
50
- MeasurementUnit,
51
50
  ProfilerMode,
52
51
  TracesSampler,
53
52
  TransactionProcessor,
54
- MetricTags,
55
- MetricValue,
56
53
  )
57
54
 
58
55
  # Experiments are feature flags to enable and disable certain unstable SDK
@@ -73,11 +70,6 @@ if TYPE_CHECKING:
73
70
  "transport_compression_algo": Optional[CompressionAlgo],
74
71
  "transport_num_pools": Optional[int],
75
72
  "transport_http2": Optional[bool],
76
- "enable_metrics": Optional[bool],
77
- "before_emit_metric": Optional[
78
- Callable[[str, MetricValue, MeasurementUnit, MetricTags], bool]
79
- ],
80
- "metric_code_locations": Optional[bool],
81
73
  "enable_logs": Optional[bool],
82
74
  "before_send_log": Optional[Callable[[Log, Hint], Optional[Log]]],
83
75
  },
@@ -97,11 +89,6 @@ FALSE_VALUES = [
97
89
  ]
98
90
 
99
91
 
100
- class INSTRUMENTER:
101
- SENTRY = "sentry"
102
- OTEL = "otel"
103
-
104
-
105
92
  class SPANDATA:
106
93
  """
107
94
  Additional information describing the type of the span.
@@ -175,7 +162,7 @@ class SPANDATA:
175
162
 
176
163
  AI_TOOL_CALLS = "ai.tool_calls"
177
164
  """
178
- For an AI model call, the function that was called. This is deprecated for OpenAI, and replaced by tool_calls
165
+ For an AI model call, the function that was called.
179
166
  """
180
167
 
181
168
  AI_TOOLS = "ai.tools"
@@ -265,6 +252,24 @@ class SPANDATA:
265
252
  Example: "qa-pipeline"
266
253
  """
267
254
 
255
+ AI_PROMPT_TOKENS_USED = "ai.prompt_tokens.used"
256
+ """
257
+ The number of input prompt tokens used by the model.
258
+ Example: 10
259
+ """
260
+
261
+ AI_COMPLETION_TOKENS_USED = "ai.completion_tokens.used"
262
+ """
263
+ The number of output completion tokens used by the model.
264
+ Example: 10
265
+ """
266
+
267
+ AI_TOTAL_TOKENS_USED = "ai.total_tokens.used"
268
+ """
269
+ The total number of tokens (input + output) used by the request to the model.
270
+ Example: 20
271
+ """
272
+
268
273
  AI_TEXTS = "ai.texts"
269
274
  """
270
275
  Raw text inputs provided to the model.
@@ -551,6 +556,46 @@ class OP:
551
556
  SOCKET_DNS = "socket.dns"
552
557
 
553
558
 
559
+ BAGGAGE_HEADER_NAME = "baggage"
560
+ SENTRY_TRACE_HEADER_NAME = "sentry-trace"
561
+
562
+ DEFAULT_SPAN_ORIGIN = "manual"
563
+ DEFAULT_SPAN_NAME = "<unlabeled span>"
564
+
565
+
566
+ # Transaction source
567
+ # see https://develop.sentry.dev/sdk/event-payloads/transaction/#transaction-annotations
568
+ class TransactionSource(str, Enum):
569
+ COMPONENT = "component"
570
+ CUSTOM = "custom"
571
+ ROUTE = "route"
572
+ TASK = "task"
573
+ URL = "url"
574
+ VIEW = "view"
575
+
576
+ def __str__(self):
577
+ # type: () -> str
578
+ return self.value
579
+
580
+
581
+ # These are typically high cardinality and the server hates them
582
+ LOW_QUALITY_TRANSACTION_SOURCES = [
583
+ TransactionSource.URL,
584
+ ]
585
+
586
+ SOURCE_FOR_STYLE = {
587
+ "endpoint": TransactionSource.COMPONENT,
588
+ "function_name": TransactionSource.COMPONENT,
589
+ "handler_name": TransactionSource.COMPONENT,
590
+ "method_and_path_pattern": TransactionSource.ROUTE,
591
+ "path": TransactionSource.URL,
592
+ "route_name": TransactionSource.COMPONENT,
593
+ "route_pattern": TransactionSource.ROUTE,
594
+ "uri_template": TransactionSource.ROUTE,
595
+ "url": TransactionSource.ROUTE,
596
+ }
597
+
598
+
554
599
  # This type exists to trick mypy and PyCharm into thinking `init` and `Client`
555
600
  # take these arguments (even though they take opaque **kwargs)
556
601
  class ClientConstructor:
@@ -584,7 +629,6 @@ class ClientConstructor:
584
629
  debug=None, # type: Optional[bool]
585
630
  attach_stacktrace=False, # type: bool
586
631
  ca_certs=None, # type: Optional[str]
587
- propagate_traces=True, # type: bool
588
632
  traces_sample_rate=None, # type: Optional[float]
589
633
  traces_sampler=None, # type: Optional[TracesSampler]
590
634
  profiles_sample_rate=None, # type: Optional[float]
@@ -598,10 +642,8 @@ class ClientConstructor:
598
642
  send_client_reports=True, # type: bool
599
643
  _experiments={}, # type: Experiments # noqa: B006
600
644
  proxy_headers=None, # type: Optional[Dict[str, str]]
601
- instrumenter=INSTRUMENTER.SENTRY, # type: Optional[str]
602
645
  before_send_transaction=None, # type: Optional[TransactionProcessor]
603
646
  project_root=None, # type: Optional[str]
604
- enable_tracing=None, # type: Optional[bool]
605
647
  include_local_variables=True, # type: Optional[bool]
606
648
  include_source_context=True, # type: Optional[bool]
607
649
  trace_propagation_targets=[ # noqa: B006
@@ -990,11 +1032,6 @@ class ClientConstructor:
990
1032
 
991
1033
  :param profile_session_sample_rate:
992
1034
 
993
-
994
- :param enable_tracing:
995
-
996
- :param propagate_traces:
997
-
998
1035
  :param auto_session_tracking:
999
1036
 
1000
1037
  :param spotlight:
@@ -1026,4 +1063,4 @@ DEFAULT_OPTIONS = _get_default_options()
1026
1063
  del _get_default_options
1027
1064
 
1028
1065
 
1029
- VERSION = "2.30.0"
1066
+ VERSION = "3.0.0a2"
sentry_sdk/debug.py CHANGED
@@ -1,6 +1,5 @@
1
1
  import sys
2
2
  import logging
3
- import warnings
4
3
 
5
4
  from sentry_sdk import get_client
6
5
  from sentry_sdk.client import _client_init_debug
@@ -30,12 +29,3 @@ def configure_logger():
30
29
  logger.addHandler(_handler)
31
30
  logger.setLevel(logging.DEBUG)
32
31
  logger.addFilter(_DebugFilter())
33
-
34
-
35
- def configure_debug_hub():
36
- # type: () -> None
37
- warnings.warn(
38
- "configure_debug_hub is deprecated. Please remove calls to it, as it is a no-op.",
39
- DeprecationWarning,
40
- stacklevel=2,
41
- )
sentry_sdk/envelope.py CHANGED
@@ -280,8 +280,6 @@ class Item:
280
280
  return "profile"
281
281
  elif ty == "profile_chunk":
282
282
  return "profile_chunk"
283
- elif ty == "statsd":
284
- return "metric_bucket"
285
283
  elif ty == "check_in":
286
284
  return "monitor"
287
285
  else:
@@ -341,7 +339,7 @@ class Item:
341
339
  # if no length was specified we need to read up to the end of line
342
340
  # and remove it (if it is present, i.e. not the very last char in an eof terminated envelope)
343
341
  payload = f.readline().rstrip(b"\n")
344
- if headers.get("type") in ("event", "transaction", "metric_buckets"):
342
+ if headers.get("type") in ("event", "transaction"):
345
343
  rv = cls(headers=headers, payload=PayloadRef(json=parse_json(payload)))
346
344
  else:
347
345
  rv = cls(headers=headers, payload=payload)
@@ -69,4 +69,4 @@ def add_feature_flag(flag, result):
69
69
 
70
70
  span = sentry_sdk.get_current_span()
71
71
  if span:
72
- span.set_flag(f"flag.evaluation.{flag}", result)
72
+ span.set_flag(flag, result)
@@ -131,10 +131,11 @@ _MIN_VERSIONS = {
131
131
  "celery": (4, 4, 7),
132
132
  "chalice": (1, 16, 0),
133
133
  "clickhouse_driver": (0, 2, 0),
134
+ "common": (1, 4, 0), # opentelemetry-sdk
134
135
  "cohere": (5, 4, 0),
135
- "django": (1, 8),
136
+ "django": (2, 0),
136
137
  "dramatiq": (1, 9),
137
- "falcon": (1, 4),
138
+ "falcon": (3, 0),
138
139
  "fastapi": (0, 79, 0),
139
140
  "flask": (1, 1, 4),
140
141
  "gql": (3, 4, 1),
@@ -157,6 +158,7 @@ _MIN_VERSIONS = {
157
158
  "statsig": (0, 55, 3),
158
159
  "strawberry": (0, 209, 5),
159
160
  "tornado": (6, 0),
161
+ "trytond": (5, 0),
160
162
  "typer": (0, 15),
161
163
  "unleash": (6, 0, 1),
162
164
  }
@@ -3,7 +3,7 @@ import urllib
3
3
  from sentry_sdk.scope import should_send_default_pii
4
4
  from sentry_sdk.integrations._wsgi_common import _filter_headers
5
5
 
6
- from typing import TYPE_CHECKING
6
+ from typing import TYPE_CHECKING, cast
7
7
 
8
8
  if TYPE_CHECKING:
9
9
  from typing import Any
@@ -21,7 +21,7 @@ def _get_headers(asgi_scope):
21
21
  Extract headers from the ASGI scope, in the format that the Sentry protocol expects.
22
22
  """
23
23
  headers = {} # type: Dict[str, str]
24
- for raw_key, raw_value in asgi_scope["headers"]:
24
+ for raw_key, raw_value in asgi_scope.get("headers", {}):
25
25
  key = raw_key.decode("latin-1")
26
26
  value = raw_value.decode("latin-1")
27
27
  if key in headers:
@@ -32,13 +32,12 @@ def _get_headers(asgi_scope):
32
32
  return headers
33
33
 
34
34
 
35
- def _get_url(asgi_scope, default_scheme, host):
36
- # type: (Dict[str, Any], Literal["ws", "http"], Optional[Union[AnnotatedValue, str]]) -> str
35
+ def _get_url(asgi_scope, default_scheme=None, host=None):
36
+ # type: (Dict[str, Any], Optional[Literal["ws", "http"]], Optional[Union[AnnotatedValue, str]]) -> str
37
37
  """
38
38
  Extract URL from the ASGI scope, without also including the querystring.
39
39
  """
40
- scheme = asgi_scope.get("scheme", default_scheme)
41
-
40
+ scheme = cast(str, asgi_scope.get("scheme", default_scheme))
42
41
  server = asgi_scope.get("server", None)
43
42
  path = asgi_scope.get("root_path", "") + asgi_scope.get("path", "")
44
43
 
@@ -1,10 +1,9 @@
1
- from contextlib import contextmanager
2
1
  import json
3
2
  from copy import deepcopy
4
3
 
5
4
  import sentry_sdk
6
5
  from sentry_sdk.scope import should_send_default_pii
7
- from sentry_sdk.utils import AnnotatedValue, logger
6
+ from sentry_sdk.utils import AnnotatedValue, SENSITIVE_DATA_SUBSTITUTE
8
7
 
9
8
  try:
10
9
  from django.http.request import RawPostDataException
@@ -16,12 +15,11 @@ from typing import TYPE_CHECKING
16
15
  if TYPE_CHECKING:
17
16
  from typing import Any
18
17
  from typing import Dict
19
- from typing import Iterator
20
18
  from typing import Mapping
21
19
  from typing import MutableMapping
22
20
  from typing import Optional
23
21
  from typing import Union
24
- from sentry_sdk._types import Event, HttpStatusCodeRange
22
+ from sentry_sdk._types import Event
25
23
 
26
24
 
27
25
  SENSITIVE_ENV_KEYS = (
@@ -52,13 +50,6 @@ DEFAULT_HTTP_METHODS_TO_CAPTURE = (
52
50
  )
53
51
 
54
52
 
55
- # This noop context manager can be replaced with "from contextlib import nullcontext" when we drop Python 3.6 support
56
- @contextmanager
57
- def nullcontext():
58
- # type: () -> Iterator[None]
59
- yield
60
-
61
-
62
53
  def request_body_within_bounds(client, content_length):
63
54
  # type: (Optional[sentry_sdk.client.BaseClient], int) -> bool
64
55
  if client is None:
@@ -237,35 +228,15 @@ def _filter_headers(headers):
237
228
  }
238
229
 
239
230
 
240
- def _in_http_status_code_range(code, code_ranges):
241
- # type: (object, list[HttpStatusCodeRange]) -> bool
242
- for target in code_ranges:
243
- if isinstance(target, int):
244
- if code == target:
245
- return True
246
- continue
247
-
248
- try:
249
- if code in target:
250
- return True
251
- except TypeError:
252
- logger.warning(
253
- "failed_request_status_codes has to be a list of integers or containers"
254
- )
255
-
256
- return False
257
-
231
+ def _request_headers_to_span_attributes(headers):
232
+ # type: (dict[str, str]) -> dict[str, str]
233
+ attributes = {}
258
234
 
259
- class HttpCodeRangeContainer:
260
- """
261
- Wrapper to make it possible to use list[HttpStatusCodeRange] as a Container[int].
262
- Used for backwards compatibility with the old `failed_request_status_codes` option.
263
- """
235
+ headers = _filter_headers(headers)
264
236
 
265
- def __init__(self, code_ranges):
266
- # type: (list[HttpStatusCodeRange]) -> None
267
- self._code_ranges = code_ranges
237
+ for header, value in headers.items():
238
+ if isinstance(value, AnnotatedValue):
239
+ value = SENSITIVE_DATA_SUBSTITUTE
240
+ attributes[f"http.request.header.{header.lower()}"] = value
268
241
 
269
- def __contains__(self, item):
270
- # type: (object) -> bool
271
- return _in_http_status_code_range(item, self._code_ranges)
242
+ return attributes