diff --git a/howfast_apm/flask.py b/howfast_apm/flask.py index 87de3a3..f06e167 100644 --- a/howfast_apm/flask.py +++ b/howfast_apm/flask.py @@ -81,7 +81,7 @@ def _start_response_wrapped(status, *args, **kwargs): return_value = self.wsgi_app(environ, _start_response_wrapped) # Stop the timer as soon as possible to get the best measure of the function's execution time end = timer() - except Exception: + except BaseException: # The WSGI app raised an exception, let's still save the point before raising the # exception again # First, "stop" the timer now to get the good measure of the function's execution time diff --git a/tests/test_middleware_flask.py b/tests/test_middleware_flask.py index 5cfc699..0a9ff82 100644 --- a/tests/test_middleware_flask.py +++ b/tests/test_middleware_flask.py @@ -22,9 +22,13 @@ def external_call(): requests.put('https://does-not-exist/') return 'ok' + @app.route('/exception') + def exception(): + raise Exception("Unhandled exception, kaboom!") + @app.route('/error') def error(): - raise Exception("Unhandled exception, kaboom!") + raise SystemExit() return app @@ -83,7 +87,7 @@ def test_with_exception(HowFastFlaskMiddleware): middleware = HowFastFlaskMiddleware(app, app_id='some-dsn') tester = app.test_client() - response = tester.get('/error') + response = tester.get('/exception') assert response.status_code == 500 assert middleware._save_point.called is True assert middleware._save_point.call_count == 1 @@ -92,6 +96,26 @@ def test_with_exception(HowFastFlaskMiddleware): assert point.get('time_request_started') < datetime.now(timezone.utc) assert point.get('method') == "GET" assert point.get('response_status') == "500 INTERNAL SERVER ERROR" + assert point.get('uri') == "/exception" + + +def test_with_error(HowFastFlaskMiddleware): + """ The middleware should gracefully handle routes that raise an Error """ + app = create_app() + middleware = HowFastFlaskMiddleware(app, app_id='some-dsn') + + tester = app.test_client() + with pytest.raises(SystemExit): + # Flask will propagate the SystemExit instead of catching it + tester.get('/error') + # However, the failure should still be logged by the middleware + assert middleware._save_point.called is True + assert middleware._save_point.call_count == 1 + point = middleware._save_point.call_args[1] + assert point.get('time_elapsed') > 0 + assert point.get('time_request_started') < datetime.now(timezone.utc) + assert point.get('method') == "GET" + assert point.get('response_status') == "500 INTERNAL SERVER ERROR" assert point.get('uri') == "/error"