From 34b318cec4fa6b28c8af4789d275a8bbd7572415 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Fri, 31 May 2019 09:52:34 +0200 Subject: [PATCH 1/6] ref(pyramid): Errorhandlers now swallow events --- sentry_sdk/integrations/pyramid.py | 31 +++++++++++----------- tests/integrations/pyramid/test_pyramid.py | 10 +++---- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/sentry_sdk/integrations/pyramid.py b/sentry_sdk/integrations/pyramid.py index 277aa1716b..76e1449aff 100644 --- a/sentry_sdk/integrations/pyramid.py +++ b/sentry_sdk/integrations/pyramid.py @@ -66,20 +66,13 @@ def sentry_patched_handle_request(self, request, *args, **kwargs): # type: (Any, Request, *Any, **Any) -> Response hub = Hub.current integration = hub.get_integration(PyramidIntegration) - if integration is None: - return old_handle_request(self, request, *args, **kwargs) - - with hub.configure_scope() as scope: - scope.add_event_processor( - _make_event_processor(weakref.ref(request), integration) - ) + if integration is not None: + with hub.configure_scope() as scope: + scope.add_event_processor( + _make_event_processor(weakref.ref(request), integration) + ) - try: - return old_handle_request(self, request, *args, **kwargs) - except Exception: - exc_info = sys.exc_info() - _capture_exception(exc_info) - reraise(*exc_info) + return old_handle_request(self, request, *args, **kwargs) Router.handle_request = sentry_patched_handle_request @@ -92,14 +85,22 @@ def sentry_patched_wsgi_call(self, environ, start_response): if integration is None: return old_wsgi_call(self, environ, start_response) - return SentryWsgiMiddleware(lambda *a, **kw: old_wsgi_call(self, *a, **kw))( + def sentry_patched_inner_wsgi_call(environ, start_response): + try: + return old_wsgi_call(self, environ, start_response) + except Exception: + einfo = sys.exc_info() + _capture_exception(einfo) + reraise(*einfo) + + return SentryWsgiMiddleware(sentry_patched_inner_wsgi_call)( environ, start_response ) Router.__call__ = sentry_patched_wsgi_call -def _capture_exception(exc_info, **kwargs): +def _capture_exception(exc_info): # type: (ExcInfo, **Any) -> None if exc_info[0] is None or issubclass(exc_info[0], HTTPException): return diff --git a/tests/integrations/pyramid/test_pyramid.py b/tests/integrations/pyramid/test_pyramid.py index 2a15a68d0f..e5c85e2f99 100644 --- a/tests/integrations/pyramid/test_pyramid.py +++ b/tests/integrations/pyramid/test_pyramid.py @@ -237,8 +237,7 @@ def errorhandler(exc, request): client = get_client() client.get("/") - error, = errors - assert type(error) is Exception + assert not errors def test_error_in_errorhandler( @@ -262,12 +261,9 @@ def error_handler(err, request): with pytest.raises(ZeroDivisionError): client.get("/") - event1, event2 = events - - exception, = event1["exception"]["values"] - assert exception["type"] == "ValueError" + event, = events - exception = event2["exception"]["values"][-1] + exception = event["exception"]["values"][-1] assert exception["type"] == "ZeroDivisionError" From b0809211e5ddab9dcd588519fcbc8136453befab Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Fri, 31 May 2019 10:18:26 +0200 Subject: [PATCH 2/6] feat: Capture exceptions if errorhandler returned a 500 --- sentry_sdk/integrations/pyramid.py | 19 ++++++++++ tests/integrations/pyramid/test_pyramid.py | 43 ++++++++++++++++++---- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/sentry_sdk/integrations/pyramid.py b/sentry_sdk/integrations/pyramid.py index 76e1449aff..6bde2179c8 100644 --- a/sentry_sdk/integrations/pyramid.py +++ b/sentry_sdk/integrations/pyramid.py @@ -59,6 +59,7 @@ def __init__(self, transaction_style="route_name"): def setup_once(): # type: () -> None from pyramid.router import Router # type: ignore + from pyramid.request import Request # type: ignore old_handle_request = Router.handle_request @@ -76,6 +77,24 @@ def sentry_patched_handle_request(self, request, *args, **kwargs): Router.handle_request = sentry_patched_handle_request + if hasattr(Request, "invoke_exception_view"): + old_invoke_exception_view = Request.invoke_exception_view + + def sentry_patched_invoke_exception_view(self, *args, **kwargs): + rv = old_invoke_exception_view(self, *args, **kwargs) + + if ( + self.exc_info + and all(self.exc_info) + and rv.status_int == 500 + and Hub.current.get_integration(PyramidIntegration) is not None + ): + _capture_exception(self.exc_info) + + return rv + + Request.invoke_exception_view = sentry_patched_invoke_exception_view + old_wsgi_call = Router.__call__ def sentry_patched_wsgi_call(self, environ, start_response): diff --git a/tests/integrations/pyramid/test_pyramid.py b/tests/integrations/pyramid/test_pyramid.py index e5c85e2f99..6e869ba963 100644 --- a/tests/integrations/pyramid/test_pyramid.py +++ b/tests/integrations/pyramid/test_pyramid.py @@ -1,21 +1,23 @@ import json - -from io import BytesIO - import logging - +import pkg_resources import pytest -from pyramid.authorization import ACLAuthorizationPolicy +from io import BytesIO + import pyramid.testing +from pyramid.authorization import ACLAuthorizationPolicy from pyramid.response import Response -from werkzeug.test import Client - from sentry_sdk import capture_message, add_breadcrumb from sentry_sdk.integrations.pyramid import PyramidIntegration +from werkzeug.test import Client + + +PYRAMID_VERSION = pkg_resources.get_distribution("pyramid").version + def hi(request): capture_message("hi") @@ -219,7 +221,7 @@ def errorhandler(exc, request): assert not events -def test_errorhandler( +def test_errorhandler_ok( sentry_init, pyramid_config, capture_exceptions, route, get_client ): sentry_init(integrations=[PyramidIntegration()]) @@ -240,6 +242,31 @@ def errorhandler(exc, request): assert not errors +@pytest.mark.skipif( + PYRAMID_VERSION < (1, 8), + reason="We don't have the right hooks in older Pyramid versions", +) +def test_errorhandler_500( + sentry_init, pyramid_config, capture_exceptions, route, get_client +): + sentry_init(integrations=[PyramidIntegration()]) + errors = capture_exceptions() + + @route("/") + def index(request): + raise Exception() + + def errorhandler(exc, request): + return Response("bad request", status=500) + + pyramid_config.add_view(errorhandler, context=Exception) + + client = get_client() + client.get("/") + + assert not errors + + def test_error_in_errorhandler( sentry_init, pyramid_config, capture_events, route, get_client ): From 21595132122dbbc9e7211b5fbaff6241e64aa48b Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 1 Jun 2019 16:19:40 +0200 Subject: [PATCH 3/6] fix: Fix tests --- tests/integrations/pyramid/test_pyramid.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/integrations/pyramid/test_pyramid.py b/tests/integrations/pyramid/test_pyramid.py index 6e869ba963..1af7f67e2f 100644 --- a/tests/integrations/pyramid/test_pyramid.py +++ b/tests/integrations/pyramid/test_pyramid.py @@ -16,7 +16,9 @@ from werkzeug.test import Client -PYRAMID_VERSION = pkg_resources.get_distribution("pyramid").version +PYRAMID_VERSION = tuple( + map(int, pkg_resources.get_distribution("pyramid").version.split(".")) +) def hi(request): From 4f3cdb0f1d93151496300fccb338dfe93429251a Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 1 Jun 2019 16:54:36 +0200 Subject: [PATCH 4/6] fix: Fix tests --- tests/integrations/pyramid/test_pyramid.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/integrations/pyramid/test_pyramid.py b/tests/integrations/pyramid/test_pyramid.py index 1af7f67e2f..9bbb3c7eec 100644 --- a/tests/integrations/pyramid/test_pyramid.py +++ b/tests/integrations/pyramid/test_pyramid.py @@ -245,7 +245,7 @@ def errorhandler(exc, request): @pytest.mark.skipif( - PYRAMID_VERSION < (1, 8), + PYRAMID_VERSION < (1, 9), reason="We don't have the right hooks in older Pyramid versions", ) def test_errorhandler_500( @@ -256,7 +256,7 @@ def test_errorhandler_500( @route("/") def index(request): - raise Exception() + 1 / 0 def errorhandler(exc, request): return Response("bad request", status=500) @@ -264,9 +264,13 @@ def errorhandler(exc, request): pyramid_config.add_view(errorhandler, context=Exception) client = get_client() - client.get("/") + app_iter, status, headers = client.get("/") + assert b"".join(app_iter) == b"bad request" + assert status.lower() == '500 internal server error' - assert not errors + error, = errors + + assert isinstance(error, ZeroDivisionError) def test_error_in_errorhandler( From d0f95531c9dc8b456d31974cfb6ed15ab0bc6f3e Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 1 Jun 2019 17:08:09 +0200 Subject: [PATCH 5/6] fix: Fix formatting --- tests/integrations/pyramid/test_pyramid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integrations/pyramid/test_pyramid.py b/tests/integrations/pyramid/test_pyramid.py index 9bbb3c7eec..e27387c1b7 100644 --- a/tests/integrations/pyramid/test_pyramid.py +++ b/tests/integrations/pyramid/test_pyramid.py @@ -266,7 +266,7 @@ def errorhandler(exc, request): client = get_client() app_iter, status, headers = client.get("/") assert b"".join(app_iter) == b"bad request" - assert status.lower() == '500 internal server error' + assert status.lower() == "500 internal server error" error, = errors From 73a3dcaab6ebb04d64c0855b92fd16e843191b05 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sat, 1 Jun 2019 19:50:43 +0200 Subject: [PATCH 6/6] fix: Fix linters --- sentry_sdk/integrations/pyramid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_sdk/integrations/pyramid.py b/sentry_sdk/integrations/pyramid.py index 6bde2179c8..2bec0a73d3 100644 --- a/sentry_sdk/integrations/pyramid.py +++ b/sentry_sdk/integrations/pyramid.py @@ -120,7 +120,7 @@ def sentry_patched_inner_wsgi_call(environ, start_response): def _capture_exception(exc_info): - # type: (ExcInfo, **Any) -> None + # type: (ExcInfo) -> None if exc_info[0] is None or issubclass(exc_info[0], HTTPException): return hub = Hub.current