diff --git a/sentry_sdk/integrations/bottle.py b/sentry_sdk/integrations/bottle.py index 8f3ede8190..68df00cfde 100644 --- a/sentry_sdk/integrations/bottle.py +++ b/sentry_sdk/integrations/bottle.py @@ -75,6 +75,19 @@ def setup_once() -> None: version = parse_version(BOTTLE_VERSION) _check_minimum_version(BottleIntegration, version) + # Bottle's Route.__repr__ might lead to a never-terminating while True + # loop when attach_stacktrace=True. + def _sentry_route_repr(self: "Route") -> str: + cb = self.callback + return "<%s %s -> %s:%s>" % ( + self.method, + self.rule, + getattr(cb, "__module__", "?"), + getattr(cb, "__name__", "?"), + ) + + Route.__sentry_repr__ = _sentry_route_repr + old_app = Bottle.__call__ @ensure_integration_enabled(BottleIntegration, old_app) diff --git a/tests/integrations/bottle/test_bottle.py b/tests/integrations/bottle/test_bottle.py index b224d59753..a4e23789ea 100644 --- a/tests/integrations/bottle/test_bottle.py +++ b/tests/integrations/bottle/test_bottle.py @@ -166,6 +166,39 @@ def index(): assert len(event["request"]["data"]["foo"]["bar"]) == 1034 +def test_attach_stacktrace_doesnt_hang(sentry_init, capture_events, app, get_client): + sentry_init( + integrations=[BottleIntegration()], + max_request_body_size="always", + attach_stacktrace=True, + ) + + data = {"foo": {"bar": "a" * (1024)}} + + @app.route("/", method="POST") + def index(): + import bottle + + assert bottle.request.json == data + assert bottle.request.body.read() == json.dumps(data).encode("ascii") + capture_message("hi") + return "ok" + + events = capture_events() + + client = get_client() + response = client.get("/") + + response = client.post("/", content_type="application/json", data=json.dumps(data)) + assert response[1] == "200 OK" + + (event,) = events + + # As long as this test finishes, we're good. It's just making sure we don't + # hang. + assert event["request"]["data"] + + @pytest.mark.parametrize("data", [{}, []], ids=["empty-dict", "empty-list"]) def test_empty_json_request(sentry_init, capture_events, app, data, get_client): sentry_init(integrations=[BottleIntegration()])