Repository: getsentry/sentry-python

Issue:
sample_rate option affecting crons checkin events
### How do you use Sentry?

Sentry Saas (sentry.io)

### Version

1.28.1

### Steps to Reproduce

Error event specific option `sample_rate` is affecting crons check in events

```
sentry_sdk.init(
    dsn="https://da93b3386b344b3182ed201d7a18bab0@o1407376.ingest.sentry.io/4504091267497984",
    sample_rate=0,
    debug=True,
    )
```

An init like the one above will cause no crons check in events to send.

### Expected Result

Crons checkin events should not be affected by the `sample_rate` option.

### Actual Result

Crons checkin events are being sampled.  Currently it looks like each event is also being sampled separately.  So if you have the `sample_rate` option set, even if the `in_progress` event gets sampled and sent, the `ok` event may not get sampled.

Discussion:

Patch:
diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py
index 9dd54165..02006e94 100644
--- a/sentry_sdk/client.py
+++ b/sentry_sdk/client.py
@@ -530,12 +530,16 @@ class _Client(object):
             self._update_session_from_event(session, event)
 
         is_transaction = event_opt.get("type") == "transaction"
+        is_checkin = event_opt.get("type") == "check_in"
 
-        if not is_transaction and not self._should_sample_error(event):
+        if (
+            not is_transaction
+            and not is_checkin
+            and not self._should_sample_error(event)
+        ):
             return None
 
         tracing_enabled = has_tracing_enabled(self.options)
-        is_checkin = event_opt.get("type") == "check_in"
         attachments = hint.get("attachments")
 
         trace_context = event_opt.get("contexts", {}).get("trace") or {}


Test patch:
diff --git a/tests/test_crons.py b/tests/test_crons.py
index 7688ac8a..5bdeb6ce 100644
--- a/tests/test_crons.py
+++ b/tests/test_crons.py
@@ -81,6 +81,18 @@ def test_capture_checkin_simple(sentry_init):
     assert check_in_id == "112233"
 
 
+def test_sample_rate_doesnt_affect_crons(sentry_init, capture_envelopes):
+    sentry_init(sample_rate=0)
+    envelopes = capture_envelopes()
+
+    capture_checkin(check_in_id="112233")
+
+    assert len(envelopes) == 1
+
+    check_in = envelopes[0].items[0].payload.json
+    assert check_in["check_in_id"] == "112233"
+
+
 def test_capture_checkin_new_id(sentry_init):
     sentry_init()
 
diff --git a/tests/tracing/test_sampling.py b/tests/tracing/test_sampling.py
index 376a4e09..6101a948 100644
--- a/tests/tracing/test_sampling.py
+++ b/tests/tracing/test_sampling.py
@@ -2,7 +2,7 @@ import random
 
 import pytest
 
-from sentry_sdk import Hub, start_span, start_transaction
+from sentry_sdk import Hub, start_span, start_transaction, capture_exception
 from sentry_sdk.tracing import Transaction
 from sentry_sdk.utils import logger
 
@@ -226,6 +226,18 @@ def test_passes_custom_samling_context_from_start_transaction_to_traces_sampler(
     )
 
 
+def test_sample_rate_affects_errors(sentry_init, capture_events):
+    sentry_init(sample_rate=0)
+    events = capture_events()
+
+    try:
+        1 / 0
+    except Exception:
+        capture_exception()
+
+    assert len(events) == 0
+
+
 @pytest.mark.parametrize(
     "traces_sampler_return_value",
     [