Skip to content

Commit 1ecae19

Browse files
authored
fix(tracemetrics): Switch experimental backend to kwarg rate (#101520)
### Summary Based on some digging, last time we tried to use an option with metrics it caused INC-1101 and INC-1130 with spikes hitting db in production as some metrics are module/import level. This will be slower (as it needs a deploy to change volume) but we can still kill switch via tracemetrics-ingestion in relay.
1 parent 740eeee commit 1ecae19

File tree

4 files changed

+23
-26
lines changed

4 files changed

+23
-26
lines changed

src/sentry/metrics/sentry_sdk.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
1+
from random import random
12
from typing import Any
23

34
from sentry_sdk import _metrics as metrics
45

5-
from sentry import options
6-
from sentry.options.rollout import in_random_rollout
7-
86
from .base import MetricsBackend, Tags
97

108
__all__ = ["SentrySDKMetricsBackend"]
119

1210

1311
class SentrySDKMetricsBackend(MetricsBackend):
1412
def __init__(self, **kwargs: Any) -> None:
15-
self._rollout_option = kwargs.pop(
16-
"rollout_option", "tracemetrics.sentry_sdk_metrics_backend_rate"
17-
)
13+
self._experimental_sample_rate = kwargs.pop("experimental_sample_rate", 0.0)
1814
self._deny_list = tuple(kwargs.pop("deny_list", []))
1915
super().__init__(**kwargs)
2016

@@ -24,10 +20,11 @@ def _is_denied(self, key: str) -> bool:
2420
def _should_send(self, key: str) -> bool:
2521
if self._is_denied(key):
2622
return False
27-
# We don't want to send metrics before the cache exists to avoid excessive cache misses.
28-
if not options.default_store.cache:
29-
return False
30-
return in_random_rollout(self._rollout_option)
23+
return self._should_sample_experimental()
24+
25+
def _should_sample_experimental(self) -> bool:
26+
"""Sample based on passed in sample rate, can't use options as they hit the db too much."""
27+
return self._experimental_sample_rate >= 1.0 or random() < self._experimental_sample_rate
3128

3229
def incr(
3330
self,

src/sentry/options/defaults.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2767,12 +2767,6 @@
27672767
flags=FLAG_PRIORITIZE_DISK | FLAG_AUTOMATOR_MODIFIABLE,
27682768
)
27692769

2770-
register(
2771-
"tracemetrics.sentry_sdk_metrics_backend_rate",
2772-
type=Float,
2773-
default=0.0,
2774-
flags=FLAG_AUTOMATOR_MODIFIABLE,
2775-
)
27762770

27772771
# TODO: For now, only a small number of projects are going through a grouping config transition at
27782772
# any given time, so we're sampling at 100% in order to be able to get good signal. Once we've fully

tests/sentry/metrics/test_dualwrite.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from unittest import mock
22

33
from sentry.metrics.dualwrite import DualWriteMetricsBackend
4-
from sentry.testutils.helpers.options import override_options
54
from sentry.testutils.thread_leaks.pytest import thread_leak_allowlist
65

76

@@ -36,15 +35,14 @@ def test_dualwrite_distribution(distribution, timing):
3635
distribution.assert_not_called()
3736

3837

39-
@override_options({"tracemetrics.sentry_sdk_metrics_backend_rate": 1.0})
4038
@mock.patch("sentry_sdk._metrics.count")
4139
@mock.patch("datadog.dogstatsd.base.DogStatsd.increment")
4240
@thread_leak_allowlist(reason="datadog dualwrite metrics", issue=98803)
4341
def test_dualwrite_experimental_backend(dogstatsd_incr, sentry_sdk_incr):
4442
backend = DualWriteMetricsBackend(
4543
primary_backend="sentry.metrics.dogstatsd.DogStatsdMetricsBackend",
4644
experimental_backend="sentry.metrics.sentry_sdk.SentrySDKMetricsBackend",
47-
experimental_args={"deny_list": ["denied"]},
45+
experimental_args={"deny_list": ["denied"], "experimental_sample_rate": 1.0},
4846
)
4947

5048
backend.incr("allowed", tags={"test": "tag"}, unit="none")
@@ -59,15 +57,14 @@ def test_dualwrite_experimental_backend(dogstatsd_incr, sentry_sdk_incr):
5957
sentry_sdk_incr.assert_not_called()
6058

6159

62-
@override_options({"tracemetrics.sentry_sdk_metrics_backend_rate": 0.0})
6360
@mock.patch("sentry_sdk._metrics.gauge")
6461
@mock.patch("datadog.dogstatsd.base.DogStatsd.gauge")
6562
@thread_leak_allowlist(reason="datadog dualwrite metrics", issue=98803)
6663
def test_dualwrite_experimental_backend_rollout_disabled(dogstatsd_gauge, sentry_sdk_gauge):
6764
backend = DualWriteMetricsBackend(
6865
primary_backend="sentry.metrics.dogstatsd.DogStatsdMetricsBackend",
6966
experimental_backend="sentry.metrics.sentry_sdk.SentrySDKMetricsBackend",
70-
experimental_args={"deny_list": []},
67+
experimental_args={"deny_list": [], "experimental_sample_rate": 0.0},
7168
)
7269

7370
backend.gauge("metric", 42, tags={"test": "tag"}, unit="none")

tests/sentry/metrics/test_sentry_sdk.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
class TestSentrySDKMetricsBackend:
99
@pytest.fixture
1010
def backend(self):
11-
return SentrySDKMetricsBackend(prefix="test.")
11+
return SentrySDKMetricsBackend(prefix="test.", experimental_sample_rate=1.0)
1212

1313
@mock.patch("sentry_sdk._metrics.count")
1414
def test_incr(self, mock_count, backend):
@@ -77,9 +77,18 @@ def test_event_noop(self, backend):
7777
backend.event("title", "message")
7878

7979
@mock.patch("sentry_sdk._metrics.count")
80-
def test_incr_sampling(self, mock_count, backend):
81-
with mock.patch.object(backend, "_should_send", return_value=True):
82-
with mock.patch.object(backend, "_should_sample", return_value=False):
83-
backend.incr("foo", amount=1)
80+
def test_incr_sampling(self, mock_count):
81+
backend = SentrySDKMetricsBackend(prefix="test.", experimental_sample_rate=0.0)
82+
backend.incr("foo", amount=1)
83+
mock_count.assert_not_called()
8484

85+
@mock.patch("sentry_sdk._metrics.count")
86+
def test_incr_deny_list(self, mock_count):
87+
backend = SentrySDKMetricsBackend(
88+
prefix="test.", experimental_sample_rate=1.0, deny_list=["denied"]
89+
)
90+
backend.incr("denied.metric", amount=1)
8591
mock_count.assert_not_called()
92+
93+
backend.incr("allowed.metric", amount=1)
94+
mock_count.assert_called_once()

0 commit comments

Comments
 (0)