diff --git a/src/sentry/api/handlers.py b/src/sentry/api/handlers.py index 8227489ec0e3b5..fed7e1d0d62efa 100644 --- a/src/sentry/api/handlers.py +++ b/src/sentry/api/handlers.py @@ -1,3 +1,4 @@ +import sentry_sdk from rest_framework.exceptions import Throttled from rest_framework.views import exception_handler @@ -6,8 +7,16 @@ def custom_exception_handler(exc, context): if isinstance(exc, RateLimitExceeded): - # If Snuba throws a RateLimitExceeded then it'll likely be available - # after another second. - exc = Throttled(wait=1) + # capture the rate limited exception so we can see it in Sentry + with sentry_sdk.new_scope() as scope: + scope.fingerprint = ["snuba-api-rate-limit-exceeded"] + sentry_sdk.capture_exception( + exc, + level="warning", + ) + # let the client know that they've been rate limited with details + exc = Throttled( + detail="Rate limit exceeded. Please try your query with a smaller date range or fewer projects." + ) return exception_handler(exc, context) diff --git a/tests/sentry/api/test_handlers.py b/tests/sentry/api/test_handlers.py index e01799f722f317..75b94ad3fe28e0 100644 --- a/tests/sentry/api/test_handlers.py +++ b/tests/sentry/api/test_handlers.py @@ -12,7 +12,9 @@ class RateLimitedEndpoint(Endpoint): permission_classes = (AllowAny,) def get(self, request): - raise RateLimitExceeded() + raise RateLimitExceeded( + "Rate limit exceeded. Please try your query with a smaller date range or fewer projects." + ) urlpatterns = [re_path(r"^/$", RateLimitedEndpoint.as_view(), name="sentry-test")] @@ -28,4 +30,7 @@ def test_simple(self): resp = self.get_response() assert resp.status_code == 429 - assert resp.data["detail"] == "Request was throttled. Expected available in 1 second." + assert ( + resp.data["detail"] + == "Rate limit exceeded. Please try your query with a smaller date range or fewer projects." + )