Skip to content

Commit 1e4085f

Browse files
committed
Only apply sampling if trace exists
1 parent f56fdd4 commit 1e4085f

File tree

2 files changed

+58
-5
lines changed

2 files changed

+58
-5
lines changed

sentry_sdk/metrics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def _capture_metric(
6868
)
6969
return
7070

71-
if sample_rate != 1.0:
71+
if sample_rate != 1.0 and trace_id is not None:
7272
attrs["sentry.client_sample_rate"] = sample_rate
7373

7474
metric = {

tests/test_metrics.py

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,12 @@ def test_metrics_sample_rate_basic(sentry_init, capture_envelopes):
284284
assert len(metrics) == 3
285285

286286
assert metrics[0]["name"] == "test.counter"
287-
assert metrics[0]["attributes"]["sentry.client_sample_rate"] == 0.5
287+
# No sentry.client_sample_rate when there's no trace context
288+
assert "sentry.client_sample_rate" not in metrics[0]["attributes"]
288289

289290
assert metrics[1]["name"] == "test.gauge"
290-
assert metrics[1]["attributes"]["sentry.client_sample_rate"] == 0.8
291+
# No sentry.client_sample_rate when there's no trace context
292+
assert "sentry.client_sample_rate" not in metrics[1]["attributes"]
291293

292294
assert metrics[2]["name"] == "test.distribution"
293295
assert "sentry.client_sample_rate" not in metrics[2]["attributes"]
@@ -316,7 +318,8 @@ def record_lost_event(reason, data_category, quantity):
316318

317319
assert len(metrics) == 2
318320

319-
assert metrics[0]["attributes"]["sentry.client_sample_rate"] == 0.5
321+
# No sentry.client_sample_rate when there's no trace context
322+
assert "sentry.client_sample_rate" not in metrics[0]["attributes"]
320323
assert (
321324
"sentry.client_sample_rate" not in metrics[1]["attributes"]
322325
) # 1.0 does not need a sample rate, it's implied to be 1.0
@@ -341,6 +344,56 @@ def test_metrics_no_sample_rate(sentry_init, capture_envelopes):
341344
assert "sentry.client_sample_rate" not in metrics[0]["attributes"]
342345

343346

347+
def test_metrics_sample_rate_no_trace_context(sentry_init, capture_envelopes):
348+
"""Test sentry.client_sample_rate not set when there's no trace context."""
349+
sentry_init()
350+
envelopes = capture_envelopes()
351+
352+
# Send metrics with sample_rate but without any active transaction/span
353+
sentry_sdk.metrics.count("test.counter", 1, sample_rate=0.5)
354+
sentry_sdk.metrics.gauge("test.gauge", 42, sample_rate=0.8)
355+
356+
get_client().flush()
357+
metrics = envelopes_to_metrics(envelopes)
358+
359+
assert len(metrics) == 2
360+
361+
# When there's no trace context, no sampling is performed,
362+
# so sentry.client_sample_rate should not be set
363+
assert "sentry.client_sample_rate" not in metrics[0]["attributes"]
364+
assert "sentry.client_sample_rate" not in metrics[1]["attributes"]
365+
366+
367+
def test_metrics_sample_rate_with_trace_context(
368+
sentry_init, capture_envelopes, monkeypatch
369+
):
370+
"""Test sentry.client_sample_rate is set when there's a trace context."""
371+
sentry_init(traces_sample_rate=1.0)
372+
envelopes = capture_envelopes()
373+
374+
# Mock the random sampling to ensure all metrics are included
375+
with mock.patch(
376+
"sentry_sdk.tracing_utils.Random.randrange",
377+
return_value=0, # Always sample (0 < any positive sample_rate)
378+
):
379+
# Send metrics with sample_rate within an active transaction
380+
with sentry_sdk.start_transaction() as _:
381+
sentry_sdk.metrics.count("test.counter", 1, sample_rate=0.5)
382+
sentry_sdk.metrics.gauge("test.gauge", 42, sample_rate=0.8)
383+
sentry_sdk.metrics.distribution("test.distribution", 200, sample_rate=1.0)
384+
385+
get_client().flush()
386+
metrics = envelopes_to_metrics(envelopes)
387+
388+
assert len(metrics) == 3
389+
390+
# When there's a trace context and sample_rate < 1.0, set attribute
391+
assert metrics[0]["attributes"]["sentry.client_sample_rate"] == 0.5
392+
assert metrics[1]["attributes"]["sentry.client_sample_rate"] == 0.8
393+
# sample_rate=1.0 doesn't need the attribute
394+
assert "sentry.client_sample_rate" not in metrics[2]["attributes"]
395+
396+
344397
@pytest.mark.parametrize("sample_rand", (0.0, 0.25, 0.5, 0.75))
345398
@pytest.mark.parametrize("sample_rate", (0.0, 0.25, 0.5, 0.75, 1.0))
346399
def test_metrics_sampling_decision(
@@ -361,7 +414,7 @@ def record_lost_event(reason, data_category, quantity):
361414
"sentry_sdk.tracing_utils.Random.randrange",
362415
return_value=int(sample_rand * 1000000),
363416
):
364-
with sentry_sdk.start_transaction() as transaction:
417+
with sentry_sdk.start_transaction() as _:
365418
sentry_sdk.metrics.count("test.counter", 1, sample_rate=sample_rate)
366419

367420
get_client().flush()

0 commit comments

Comments
 (0)