Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
7 changes: 0 additions & 7 deletions sentry_sdk/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand All @@ -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]]],
Comment thread
cursor[bot] marked this conversation as resolved.
"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,
Expand Down
11 changes: 1 addition & 10 deletions sentry_sdk/tracing_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 3 additions & 9 deletions sentry_sdk/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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(
Expand All @@ -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":
Expand Down
28 changes: 0 additions & 28 deletions tests/test_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
57 changes: 0 additions & 57 deletions tests/test_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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
Expand Down
120 changes: 0 additions & 120 deletions tests/tracing/test_span_streaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
):
Expand Down Expand Up @@ -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"),
[
Expand Down
Loading