diff --git a/README.rst b/README.rst index e8ef13b..9e17089 100644 --- a/README.rst +++ b/README.rst @@ -48,6 +48,15 @@ Quickstart Note: ``handler500`` is only used if ``DEBUG = False`` in django settings. +3b) Instead of using ``handler500`` you can use a middleware to catch and send all the +exceptions to Google Cloud error reporting API. Just add the middleware in your settings:: + + # in myproject/settings.py + MIDDLEWARE = [ + ... + "dj_cloud_error.middleware.GoogleCloudMiddleware", + ] + Settings ======== diff --git a/dj_cloud_error/middleware.py b/dj_cloud_error/middleware.py new file mode 100644 index 0000000..fca123e --- /dev/null +++ b/dj_cloud_error/middleware.py @@ -0,0 +1,27 @@ +import os + +from google.cloud import error_reporting + + +class GoogleCloudMiddleware: + def __init__(self, get_response): + self.get_response = get_response + # One-time configuration and initialization. + service = os.environ.get("GOOGLE_CLOUD_ERROR_SERVICE", None) + version = os.environ.get("GOOGLE_CLOUD_ERROR_VERSION", None) + self.client = error_reporting.Client(service=service, version=version) + + def __call__(self, request): + # Code to be executed for each request before + # the view (and later middleware) are called. + + response = self.get_response(request) + + # Code to be executed for each request/response after + # the view is called. + + return response + + def process_exception(self, request, exception): + self.client.report_exception() + return None diff --git a/tests/test_middleware.py b/tests/test_middleware.py new file mode 100644 index 0000000..122d6d9 --- /dev/null +++ b/tests/test_middleware.py @@ -0,0 +1,27 @@ +from unittest import mock + +from django.test import TestCase, modify_settings, override_settings +from django.urls import reverse + +from tests.apps.example.views import MyException + + +class TestMiddleware(TestCase): + def setUp(self): + self.exception = Exception() + + @modify_settings( + MIDDLEWARE={ + "append": "dj_cloud_error.middleware.GoogleCloudMiddleware", + } + ) + @override_settings(DEBUG=False) + def test_process_exception(self): + with mock.patch( + "google.cloud.error_reporting.Client", autospec=True + ) as mock_client_class, self.assertRaises(MyException): + self.client.get(reverse("example:error")) + + mock_client_class.assert_called() + mock_client = mock_client_class() + mock_client.report_exception.assert_called()