Skip to content

Commit 07c12d5

Browse files
committed
Revert "chore: Remove start_span(sampled=X)"
This reverts commit 33d6f1b.
1 parent bb46a2a commit 07c12d5

File tree

6 files changed

+58
-9
lines changed

6 files changed

+58
-9
lines changed

MIGRATION_GUIDE.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ Looking to upgrade from Sentry SDK 2.x to 3.x? Here's a comprehensive list of wh
157157
- `Transport.capture_event` has been removed. Use `Transport.capture_envelope` instead.
158158
- Function transports are no longer supported. Subclass the `Transport` instead.
159159
- `start_transaction` (`start_span`) no longer takes the following arguments:
160-
- `sampled`: use a `traces_sampler` to adjust the sampling rate
161160
- `trace_id`, `baggage`: use `continue_trace` for propagation from headers or environment variables
162161
- `same_process_as_parent`
163162
- `span_id`

sentry_sdk/integrations/opentelemetry/consts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ class SentrySpanAttribute:
3333
NAME = "sentry.name"
3434
SOURCE = "sentry.source"
3535
CONTEXT = "sentry.context"
36+
CUSTOM_SAMPLED = "sentry.custom_sampled" # used for saving start_span(sampled=X)

sentry_sdk/integrations/opentelemetry/sampler.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,26 @@ def should_sample(
211211
# We are the head SDK and we need to generate a new sample_rand
212212
sample_rand = cast(Decimal, _generate_sample_rand(str(trace_id), (0, 1)))
213213

214+
# Explicit sampled value provided at start_span
215+
custom_sampled = cast(
216+
"Optional[bool]", attributes.get(SentrySpanAttribute.CUSTOM_SAMPLED)
217+
)
218+
if custom_sampled is not None:
219+
if is_root_span:
220+
sample_rate = float(custom_sampled)
221+
if sample_rate > 0:
222+
return sampled_result(
223+
parent_span_context, attributes, sample_rate=sample_rate
224+
)
225+
else:
226+
return dropped_result(
227+
parent_span_context, attributes, sample_rate=sample_rate
228+
)
229+
else:
230+
logger.debug(
231+
f"[Tracing] Ignoring sampled param for non-root span {name}"
232+
)
233+
214234
# Check if there is a traces_sampler
215235
# Traces_sampler is responsible to check parent sampled to have full transactions.
216236
has_traces_sampler = callable(client.options.get("traces_sampler"))

sentry_sdk/tracing.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ def __init__(
282282
op=None, # type: Optional[str]
283283
description=None, # type: Optional[str]
284284
status=None, # type: Optional[str]
285+
sampled=None, # type: Optional[bool]
285286
start_timestamp=None, # type: Optional[Union[datetime, float]]
286287
origin=None, # type: Optional[str]
287288
name=None, # type: Optional[str]
@@ -332,6 +333,8 @@ def __init__(
332333
attributes[SentrySpanAttribute.SOURCE] = source
333334
if description is not None:
334335
attributes[SentrySpanAttribute.DESCRIPTION] = description
336+
if sampled is not None:
337+
attributes[SentrySpanAttribute.CUSTOM_SAMPLED] = sampled
335338

336339
parent_context = None
337340
if parent_span is not None:

tests/integrations/sqlalchemy/test_sqlalchemy.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class Address(Base):
111111
Session = sessionmaker(bind=engine) # noqa: N806
112112
session = Session()
113113

114-
with sentry_sdk.start_span(name="test_transaction"):
114+
with sentry_sdk.start_span(name="test_transaction", sampled=True):
115115
with session.begin_nested():
116116
session.query(Person).first()
117117

@@ -185,7 +185,7 @@ class Address(Base):
185185
Session = sessionmaker(bind=engine) # noqa: N806
186186
session = Session()
187187

188-
with sentry_sdk.start_span(name="test_transaction"):
188+
with sentry_sdk.start_span(name="test_transaction", sampled=True):
189189
with session.begin_nested():
190190
session.query(Person).first()
191191

@@ -304,7 +304,7 @@ def test_query_source_disabled(sentry_init, capture_events):
304304

305305
events = capture_events()
306306

307-
with sentry_sdk.start_span(name="test_transaction"):
307+
with sentry_sdk.start_span(name="test_transaction", sampled=True):
308308
Base = declarative_base() # noqa: N806
309309

310310
class Person(Base):
@@ -356,7 +356,7 @@ def test_query_source_enabled(sentry_init, capture_events, enable_db_query_sourc
356356

357357
events = capture_events()
358358

359-
with sentry_sdk.start_span(name="test_transaction"):
359+
with sentry_sdk.start_span(name="test_transaction", sampled=True):
360360
Base = declarative_base() # noqa: N806
361361

362362
class Person(Base):
@@ -403,7 +403,7 @@ def test_query_source(sentry_init, capture_events):
403403
)
404404
events = capture_events()
405405

406-
with sentry_sdk.start_span(name="test_transaction"):
406+
with sentry_sdk.start_span(name="test_transaction", sampled=True):
407407
Base = declarative_base() # noqa: N806
408408

409409
class Person(Base):
@@ -473,7 +473,7 @@ def test_query_source_with_module_in_search_path(sentry_init, capture_events):
473473
query_first_model_from_session,
474474
)
475475

476-
with sentry_sdk.start_span(name="test_transaction"):
476+
with sentry_sdk.start_span(name="test_transaction", sampled=True):
477477
Base = declarative_base() # noqa: N806
478478

479479
class Person(Base):
@@ -531,7 +531,7 @@ def test_no_query_source_if_duration_too_short(sentry_init, capture_events):
531531
)
532532
events = capture_events()
533533

534-
with sentry_sdk.start_span(name="test_transaction"):
534+
with sentry_sdk.start_span(name="test_transaction", sampled=True):
535535
Base = declarative_base() # noqa: N806
536536

537537
class Person(Base):
@@ -599,7 +599,7 @@ def test_query_source_if_duration_over_threshold(sentry_init, capture_events):
599599
)
600600
events = capture_events()
601601

602-
with sentry_sdk.start_span(name="test_transaction"):
602+
with sentry_sdk.start_span(name="test_transaction", sampled=True):
603603
Base = declarative_base() # noqa: N806
604604

605605
class Person(Base):

tests/tracing/test_sampling.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,19 @@ def test_sampling_decided_only_for_root_spans(sentry_init):
2323
assert root_span2.sampled is not None
2424

2525

26+
@pytest.mark.parametrize("sampled", [True, False])
27+
def test_nested_span_sampling_override(sentry_init, sampled):
28+
sentry_init(traces_sample_rate=1.0)
29+
30+
with start_span(name="outer", sampled=sampled) as outer_span:
31+
assert outer_span.sampled is sampled
32+
with start_span(name="inner", sampled=(not sampled)) as inner_span:
33+
# won't work because the child span inherits the sampling decision
34+
# from the parent
35+
assert inner_span.sampled is sampled
36+
assert outer_span.sampled is sampled
37+
38+
2639
def test_no_double_sampling(sentry_init, capture_events):
2740
# Transactions should not be subject to the global/error sample rate.
2841
# Only the traces_sample_rate should apply.
@@ -143,6 +156,19 @@ def test_ignores_inherited_sample_decision_when_traces_sampler_defined(
143156
assert span.sampled is not parent_sampling_decision
144157

145158

159+
@pytest.mark.parametrize("explicit_decision", [True, False])
160+
def test_traces_sampler_doesnt_overwrite_explicitly_passed_sampling_decision(
161+
sentry_init, explicit_decision
162+
):
163+
# make traces_sampler pick the opposite of the explicit decision, to prove
164+
# that the explicit decision takes precedence
165+
traces_sampler = mock.Mock(return_value=not explicit_decision)
166+
sentry_init(traces_sampler=traces_sampler)
167+
168+
with start_span(name="dogpark", sampled=explicit_decision) as span:
169+
assert span.sampled is explicit_decision
170+
171+
146172
@pytest.mark.parametrize("parent_sampling_decision", [True, False])
147173
def test_inherits_parent_sampling_decision_when_traces_sampler_undefined(
148174
sentry_init, parent_sampling_decision

0 commit comments

Comments
 (0)