diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 94871b4a77..7684fe8825 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -82,6 +82,11 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh - The deprecated `propagate_traces` option has been removed. Use `trace_propagation_targets` instead, which gives you more power over trace propagation. Note that only the top-level `init` option was removed; the `propagate_traces` option of the Celery integration remains available. - Removed Spotlight integration for Django. See [Spotlight 2.0](https://github.com/getsentry/spotlight/issues/891) for more context. - The deprecated parameter `propagate_hub` in `ThreadingIntegration()` was removed. +- The experimental `max_spans` option was removed. +- The experimental `before_send_log` option was removed. Use the top-level `before_send_log` instead. +- The experimental `before_send_metric` option was removed. Use the top-level `before_send_metric` instead. +- The experimental `ignore_spans` option was removed. Use the top-level `ignore_spans` instead. +- The experimental `before_send_span` option was removed. Use the top-level `before_send_span` instead. - The SDK won't set any tags on its own anymore. - The `update_current_span` API was removed. diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py index 3d4e403fd9..1db1fdeaca 100644 --- a/sentry_sdk/consts.py +++ b/sentry_sdk/consts.py @@ -64,7 +64,6 @@ class CompressionAlgo(Enum): Experiments = TypedDict( "Experiments", { - "max_spans": Optional[int], "max_flags": Optional[int], "record_sql_params": Optional[bool], "continuous_profiling_auto_start": Optional[bool], @@ -74,13 +73,7 @@ class CompressionAlgo(Enum): "transport_num_pools": Optional[int], "transport_http2": Optional[bool], "transport_async": Optional[bool], - "before_send_log": Optional[Callable[[Log, Hint], Optional[Log]]], - "before_send_metric": Optional[Callable[[Metric, Hint], Optional[Metric]]], "trace_lifecycle": Optional[Literal["static", "stream"]], - "ignore_spans": Optional[IgnoreSpansConfig], - "before_send_span": Optional[ - Callable[[SpanJSON, Hint], Optional[SpanJSON]] - ], "data_collection": Optional[DataCollectionUserOptions], }, total=False, diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index c7ed24ba56..148f106680 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -1690,16 +1690,7 @@ def _make_sampling_decision( def is_ignored_span(name: str, attributes: "Optional[Attributes]") -> bool: """Determine if a span fits one of the rules in ignore_spans.""" client = sentry_sdk.get_client() - is_ignored_at_top_level = client.options.get("ignore_spans", None) - is_ignored_in_experiment_config = (client.options.get("_experiments") or {}).get( - "ignore_spans" - ) - - ignore_spans = ( - is_ignored_at_top_level - if is_ignored_at_top_level is not None - else is_ignored_in_experiment_config - ) + ignore_spans = client.options.get("ignore_spans", None) if not ignore_spans: return False diff --git a/sentry_sdk/utils.py b/sentry_sdk/utils.py index 5974266826..8edae094d9 100644 --- a/sentry_sdk/utils.py +++ b/sentry_sdk/utils.py @@ -1945,9 +1945,7 @@ def get_before_send_log( if options is None: return None - return options.get("before_send_log") or options["_experiments"].get( - "before_send_log" - ) + return options.get("before_send_log") def get_before_send_metric( @@ -1956,9 +1954,7 @@ def get_before_send_metric( if options is None: return None - return options.get("before_send_metric") or options["_experiments"].get( - "before_send_metric" - ) + return options.get("before_send_metric") def get_before_send_span( @@ -1967,9 +1963,7 @@ def get_before_send_span( if options is None: return None - return options.get("before_send_span") or options["_experiments"].get( - "before_send_span" - ) + return options.get("before_send_span") def format_attribute(val: "Any") -> "AttributeValue": diff --git a/tests/test_logs.py b/tests/test_logs.py index b189724ba4..2761ac6742 100644 --- a/tests/test_logs.py +++ b/tests/test_logs.py @@ -106,34 +106,6 @@ def _before_log(record, hint): assert before_log_called is True -def test_logs_before_send_log_experimental_option_still_works( - sentry_init, capture_items -): - before_log_called = False - - def _before_log(record, hint): - nonlocal before_log_called - before_log_called = True - - return record - - sentry_init( - _experiments={ - "before_send_log": _before_log, - }, - ) - items = capture_items("log") - - sentry_sdk.logger.error("This is an error log...") - - get_client().flush() - logs = [item.payload for item in items] - assert len(logs) == 1 - - assert logs[0]["attributes"]["sentry.severity_text"] == "error" - assert before_log_called is True - - @pytest.mark.tests_internal_exceptions def test_logs_before_send_log_raises_does_not_crash_application( sentry_init, capture_items diff --git a/tests/test_metrics.py b/tests/test_metrics.py index 7596176b8a..d177176943 100644 --- a/tests/test_metrics.py +++ b/tests/test_metrics.py @@ -40,22 +40,6 @@ def test_metrics_basics(sentry_init, capture_items): assert metrics[2]["unit"] == "second" -def test_metrics_experimental_option(sentry_init, capture_items): - sentry_init() - items = capture_items("trace_metric") - - sentry_sdk.metrics.count("test.counter", 5) - - get_client().flush() - - metrics = [item.payload for item in items] - assert len(metrics) == 1 - - assert metrics[0]["name"] == "test.counter" - assert metrics[0]["type"] == "counter" - assert metrics[0]["value"] == 5.0 - - def test_metrics_with_attributes(sentry_init, capture_items): sentry_init(release="1.0.0", environment="test", server_name="test-server") items = capture_items("trace_metric") @@ -211,47 +195,6 @@ def _before_metric(record, hint): assert before_metric_called -def test_metrics_experimental_before_send(sentry_init, capture_items): - before_metric_called = False - - def _before_metric(record, hint): - nonlocal before_metric_called - - assert set(record.keys()) == { - "timestamp", - "trace_id", - "span_id", - "name", - "type", - "value", - "unit", - "attributes", - } - - if record["name"] == "test.skip": - return None - - before_metric_called = True - return record - - sentry_init( - _experiments={ - "before_send_metric": _before_metric, - }, - ) - items = capture_items("trace_metric") - - sentry_sdk.metrics.count("test.skip", 1) - sentry_sdk.metrics.count("test.keep", 1) - - get_client().flush() - - metrics = [item.payload for item in items] - assert len(metrics) == 1 - assert metrics[0]["name"] == "test.keep" - assert before_metric_called - - @pytest.mark.tests_internal_exceptions def test_metrics_before_send_raises_does_not_crash_application( sentry_init, capture_items diff --git a/tests/tracing/test_span_streaming.py b/tests/tracing/test_span_streaming.py index 8aef2f7d17..ea0dea1e17 100644 --- a/tests/tracing/test_span_streaming.py +++ b/tests/tracing/test_span_streaming.py @@ -384,67 +384,6 @@ def before_send_span(span, hint): assert "mutated" not in span["attributes"] -def test_before_send_span_set_in_experiments(sentry_init, capture_items): - def before_send_span(span, hint): - span["name"] = "from experiments" - return span - - sentry_init( - traces_sample_rate=1.0, - trace_lifecycle="stream", - _experiments={ - "before_send_span": before_send_span, - }, - ) - - items = capture_items("span") - - with sentry_sdk.traces.start_span(name="span"): - ... - - sentry_sdk.get_client().flush() - spans = [item.payload for item in items] - - assert len(spans) == 1 - (span,) = spans - - assert span["name"] == "from experiments" - - -def test_before_send_span_top_level_takes_precedence_over_experiments( - sentry_init, capture_items -): - def top_level(span, hint): - span["name"] = "top-level" - return span - - def experimental(span, hint): - span["name"] = "experimental" - return span - - sentry_init( - traces_sample_rate=1.0, - trace_lifecycle="stream", - before_send_span=top_level, - _experiments={ - "before_send_span": experimental, - }, - ) - - items = capture_items("span") - - with sentry_sdk.traces.start_span(name="span"): - ... - - sentry_sdk.get_client().flush() - spans = [item.payload for item in items] - - assert len(spans) == 1 - (span,) = spans - - assert span["name"] == "top-level" - - def test_before_send_span_warns_without_span_streaming(sentry_init): import warnings @@ -1413,41 +1352,6 @@ def test_set_span_status_on_ignored_span(sentry_init, capture_items): ] -@pytest.mark.parametrize( - ("ignore_spans", "name", "attributes", "ignored"), IGNORE_SPANS_CASES -) -def test_ignore_spans_set_in_experiments( - sentry_init, capture_items, ignore_spans, name, attributes, ignored -): - sentry_init( - traces_sample_rate=1.0, - _experiments={ - "trace_lifecycle": "stream", - "ignore_spans": ignore_spans, - }, - ) - - items = capture_items("span") - - with sentry_sdk.traces.start_span(name=name, attributes=attributes) as span: - if ignored: - assert span.sampled is False - assert isinstance(span, NoOpStreamedSpan) - else: - assert span.sampled is True - assert isinstance(span, StreamedSpan) - - sentry_sdk.get_client().flush() - spans = [item.payload for item in items] - - if ignored: - assert len(spans) == 0 - else: - assert len(spans) == 1 - (span,) = spans - assert span["name"] == name - - def test_ignore_spans_basic( sentry_init, capture_items, capture_record_lost_event_calls ): @@ -1973,30 +1877,6 @@ def test_ignore_spans_top_level_with_trace_lifecycle_in_experiments( assert span["name"] == "not ignored" -def test_ignore_spans_empty_top_level_overrides_experiments(sentry_init, capture_items): - # An explicit empty top-level ignore_spans should disable ignoring, - # taking precedence over any rules set in _experiments. - sentry_init( - traces_sample_rate=1.0, - trace_lifecycle="stream", - ignore_spans=[], - _experiments={"ignore_spans": ["ignored"]}, - ) - - items = capture_items("span") - - with sentry_sdk.traces.start_span(name="ignored") as span: - assert span.sampled is True - assert isinstance(span, StreamedSpan) - - sentry_sdk.get_client().flush() - spans = [item.payload for item in items] - - assert len(spans) == 1 - (span,) = spans - assert span["name"] == "ignored" - - @pytest.mark.parametrize( ("options", "streaming_enabled"), [