def register_handlers(client): from django.core.signals import got_request_exception, request_started, request_finished from elasticapm.contrib.django.handlers import exception_handler # Connect to Django's internal signal handlers got_request_exception.disconnect(dispatch_uid=ERROR_DISPATCH_UID) got_request_exception.connect(partial(exception_handler, client), dispatch_uid=ERROR_DISPATCH_UID, weak=False) request_started.disconnect(dispatch_uid=REQUEST_START_DISPATCH_UID) request_started.connect(partial(_request_started_handler, client), dispatch_uid=REQUEST_START_DISPATCH_UID, weak=False) request_finished.disconnect(dispatch_uid=REQUEST_FINISH_DISPATCH_UID) request_finished.connect( lambda sender, **kwargs: client.end_transaction() if _should_start_transaction(client) else None, dispatch_uid=REQUEST_FINISH_DISPATCH_UID, weak=False, ) # If we can import celery, register ourselves as exception handler try: import celery # noqa F401 from elasticapm.contrib.celery import register_exception_tracking try: register_exception_tracking(client) except Exception as e: client.logger.exception( "Failed installing django-celery hook: %s" % e) except ImportError: client.logger.debug("Not instrumenting Celery, couldn't import")
def request(self, **request): """ The master request method. Compose the environment dictionary and pass to the handler, return the result of the handler. Assume defaults for the query environment, which can be overridden using the arguments to the request. """ environ = self._base_environ(**request) # Curry a data dictionary into an instance of the template renderer # callback function. data = {} on_template_render = partial(store_rendered_templates, data) signal_uid = "template-render-%s" % id(request) signals.template_rendered.connect(on_template_render, dispatch_uid=signal_uid) # Capture exceptions created by the handler. exception_uid = "request-exception-%s" % id(request) got_request_exception.connect(self.store_exc_info, dispatch_uid=exception_uid) try: response = self.handler(environ) finally: signals.template_rendered.disconnect(dispatch_uid=signal_uid) got_request_exception.disconnect(dispatch_uid=exception_uid) # Look for a signaled exception, clear the current context exception # data, then re-raise the signaled exception. Also clear the signaled # exception from the local cache. response.exc_info = self.exc_info if self.exc_info: _, exc_value, _ = self.exc_info self.exc_info = None if self.raise_request_exception: raise exc_value # Save the client and request that stimulated the response. response.client = self response.request = request # Add any rendered template detail to the response. response.templates = data.get('templates', []) response.context = data.get('context') response.json = partial(self._parse_json, response) # Attach the ResolverMatch instance to the response. response.resolver_match = SimpleLazyObject( lambda: resolve(request['PATH_INFO'])) # Flatten a single context. Not really necessary anymore thanks to the # __getattr__ flattening in ContextList, but has some edge case # backwards compatibility implications. if response.context and len(response.context) == 1: response.context = response.context[0] # Update persistent cookie data. if response.cookies: self.cookies.update(response.cookies) return response
async def request(self, **request): """ The master request method. Compose the scope dictionary and pass to the handler, return the result of the handler. Assume defaults for the query environment, which can be overridden using the arguments to the request. """ if "follow" in request: raise NotImplementedError( "AsyncClient request methods do not accept the follow parameter." ) scope = self._base_scope(**request) # Curry a data dictionary into an instance of the template renderer # callback function. data = {} on_template_render = partial(store_rendered_templates, data) signal_uid = "template-render-%s" % id(request) signals.template_rendered.connect(on_template_render, dispatch_uid=signal_uid) # Capture exceptions created by the handler. exception_uid = "request-exception-%s" % id(request) got_request_exception.connect(self.store_exc_info, dispatch_uid=exception_uid) try: response = await self.handler(scope) finally: signals.template_rendered.disconnect(dispatch_uid=signal_uid) got_request_exception.disconnect(dispatch_uid=exception_uid) # Check for signaled exceptions. self.check_exception(response) # Save the client and request that stimulated the response. response.client = self response.request = request # Add any rendered template detail to the response. response.templates = data.get("templates", []) response.context = data.get("context") response.json = partial(self._parse_json, response) # Attach the ResolverMatch instance to the response. urlconf = getattr(response.asgi_request, "urlconf", None) response.resolver_match = SimpleLazyObject( lambda: resolve(request["path"], urlconf=urlconf), ) # Flatten a single context. Not really necessary anymore thanks to the # __getattr__ flattening in ContextList, but has some edge case # backwards compatibility implications. if response.context and len(response.context) == 1: response.context = response.context[0] # Update persistent cookie data. if response.cookies: self.cookies.update(response.cookies) return response
def request(self, **request): """ The master request method. Compose the environment dictionary and pass to the handler, return the result of the handler. Assume defaults for the query environment, which can be overridden using the arguments to the request. """ environ = self._base_environ(**request) # Curry a data dictionary into an instance of the template renderer # callback function. data = {} on_template_render = partial(store_rendered_templates, data) signal_uid = "template-render-%s" % id(request) signals.template_rendered.connect(on_template_render, dispatch_uid=signal_uid) # Capture exceptions created by the handler. exception_uid = "request-exception-%s" % id(request) got_request_exception.connect(self.store_exc_info, dispatch_uid=exception_uid) try: response = self.handler(environ) finally: signals.template_rendered.disconnect(dispatch_uid=signal_uid) got_request_exception.disconnect(dispatch_uid=exception_uid) # Look for a signaled exception, clear the current context exception # data, then re-raise the signaled exception. Also clear the signaled # exception from the local cache. response.exc_info = self.exc_info if self.exc_info: _, exc_value, _ = self.exc_info self.exc_info = None if self.raise_request_exception: raise exc_value # Save the client and request that stimulated the response. response.client = self response.request = request # Add any rendered template detail to the response. response.templates = data.get('templates', []) response.context = data.get('context') response.json = partial(self._parse_json, response) # Attach the ResolverMatch instance to the response. response.resolver_match = SimpleLazyObject(lambda: resolve(request['PATH_INFO'])) # Flatten a single context. Not really necessary anymore thanks to the # __getattr__ flattening in ContextList, but has some edge case # backwards compatibility implications. if response.context and len(response.context) == 1: response.context = response.context[0] # Update persistent cookie data. if response.cookies: self.cookies.update(response.cookies) return response
def test_exception_preservation(self): "An exception is preserved and reported correctly, even if sys.exc_clear is called." def on_request_exception(sender, request, **kwargs): sys.exc_clear() got_request_exception.connect(on_request_exception) try: with self.settings(DEBUG=True): handler = WSGIHandler() environ = RequestFactory().get(reverse('view_exception', args=(1,))).environ response = handler(environ, lambda *a, **k: None) self.assertContains(response, '<h2>Traceback ', status_code=500) self.assertContains(response, 'raise BrokenException(', status_code=500) finally: got_request_exception.disconnect(on_request_exception)
def test_exception_preservation(self): "An exception is preserved and reported correctly, even if sys.exc_clear is called." def on_request_exception(sender, request, **kwargs): sys.exc_clear() got_request_exception.connect(on_request_exception) try: with self.settings(DEBUG=True): handler = WSGIHandler() environ = RequestFactory().get( reverse('view_exception', args=(1, ))).environ response = handler(environ, lambda *a, **k: None) self.assertContains(response, '<h2>Traceback ', status_code=500) self.assertContains(response, 'raise BrokenException(', status_code=500) finally: got_request_exception.disconnect(on_request_exception)
def register_handlers(client): from django.core.signals import got_request_exception from elasticapm.contrib.django.handlers import exception_handler # Connect to Django's internal signal handler dispatch_uid = 'elasticapm-exceptions' got_request_exception.disconnect(dispatch_uid=dispatch_uid) got_request_exception.connect(partial(exception_handler, client), dispatch_uid=dispatch_uid, weak=False) # If we can import celery, register ourselves as exception handler try: import celery # noqa F401 from elasticapm.contrib.celery import register_exception_tracking try: register_exception_tracking(client) except Exception as e: client.logger.exception( 'Failed installing django-celery hook: %s' % e) except ImportError: client.logger.debug("Not instrumenting Celery, couldn't import")
from __future__ import unicode_literals
def request(self, **request): """ The master request method. Composes the environment dictionary and passes to the handler, returning the result of the handler. Assumes defaults for the query environment, which can be overridden using the arguments to the request. """ environ = self._base_environ(**request) # Curry a data dictionary into an instance of the template renderer # callback function. data = {} on_template_render = curry(store_rendered_templates, data) signal_uid = "template-render-%s" % id(request) signals.template_rendered.connect(on_template_render, dispatch_uid=signal_uid) # Capture exceptions created by the handler. exception_uid = "request-exception-%s" % id(request) got_request_exception.connect(self.store_exc_info, dispatch_uid=exception_uid) try: try: response = self.handler(environ) except TemplateDoesNotExist as e: # If the view raises an exception, Django will attempt to show # the 500.html template. If that template is not available, # we should ignore the error in favor of re-raising the # underlying exception that caused the 500 error. Any other # template found to be missing during view error handling # should be reported as-is. if e.args != ('500.html', ): raise # Look for a signalled exception, clear the current context # exception data, then re-raise the signalled exception. # Also make sure that the signalled exception is cleared from # the local cache! if self.exc_info: exc_info = self.exc_info self.exc_info = None six.reraise(*exc_info) # Save the client and request that stimulated the response. response.client = self response.request = request # Add any rendered template detail to the response. response.templates = data.get("templates", []) response.context = data.get("context") response.json = curry(self._parse_json, response) # Attach the ResolverMatch instance to the response response.resolver_match = SimpleLazyObject( lambda: resolve(request['PATH_INFO'])) # Flatten a single context. Not really necessary anymore thanks to # the __getattr__ flattening in ContextList, but has some edge-case # backwards-compatibility implications. if response.context and len(response.context) == 1: response.context = response.context[0] # Update persistent cookie data. if response.cookies: self.cookies.update(response.cookies) return response finally: signals.template_rendered.disconnect(dispatch_uid=signal_uid) got_request_exception.disconnect(dispatch_uid=exception_uid)
def tearDown(self): got_request_exception.disconnect(self._on_request_exception) self.exceptions = []
def request(self, **request): """ The master request method. Composes the environment dictionary and passes to the handler, returning the result of the handler. Assumes defaults for the query environment, which can be overridden using the arguments to the request. """ environ = self._base_environ(**request) # Curry a data dictionary into an instance of the template renderer # callback function. data = {} on_template_render = curry(store_rendered_templates, data) signal_uid = "template-render-%s" % id(request) signals.template_rendered.connect(on_template_render, dispatch_uid=signal_uid) # Capture exceptions created by the handler. exception_uid = "request-exception-%s" % id(request) got_request_exception.connect(self.store_exc_info, dispatch_uid=exception_uid) try: try: response = self.handler(environ) except TemplateDoesNotExist as e: # If the view raises an exception, Django will attempt to show # the 500.html template. If that template is not available, # we should ignore the error in favor of re-raising the # underlying exception that caused the 500 error. Any other # template found to be missing during view error handling # should be reported as-is. if e.args != ('500.html',): raise # Look for a signalled exception, clear the current context # exception data, then re-raise the signalled exception. # Also make sure that the signalled exception is cleared from # the local cache! if self.exc_info: exc_info = self.exc_info self.exc_info = None six.reraise(*exc_info) # Save the client and request that stimulated the response. response.client = self response.request = request # Add any rendered template detail to the response. response.templates = data.get("templates", []) response.context = data.get("context") response.json = curry(self._parse_json, response) # Attach the ResolverMatch instance to the response response.resolver_match = SimpleLazyObject(lambda: resolve(request['PATH_INFO'])) # Flatten a single context. Not really necessary anymore thanks to # the __getattr__ flattening in ContextList, but has some edge-case # backwards-compatibility implications. if response.context and len(response.context) == 1: response.context = response.context[0] # Update persistent cookie data. if response.cookies: self.cookies.update(response.cookies) return response finally: signals.template_rendered.disconnect(dispatch_uid=signal_uid) got_request_exception.disconnect(dispatch_uid=exception_uid)
for k in [k for k in sys.modules if k.startswith('django')]: del sys.modules[k] # Force sys.path to have our own directory first, in case we want to import from it. sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) # Must set this env var *before* importing any part of Django os.environ['DJANGO_SETTINGS_MODULE'] = 'errorbucket.settings' import django.core.handlers.wsgi from django.core.signals import got_request_exception import django.db import django.dispatch.dispatcher def log_exception(*args, **kwds): logging.exception('Exception in request:') got_request_exception.connect(log_exception) # Log errors. got_request_exception.disconnect( django.db._rollback_on_exception) # Unregister the rollback event handler. def main(): util.run_wsgi_app(django.core.handlers.wsgi.WSGIHandler()) if __name__ == '__main__': main()
def uninstall(self): request_started.disconnect(self.before_request) got_request_exception.disconnect(self.exception_handler) if self.celery_handler: self.celery_handler.uninstall()
import logging, os, sys from google.appengine.ext.webapp import util # Remove the standard version of Django. for k in [k for k in sys.modules if k.startswith('django')]: del sys.modules[k] # Force sys.path to have our own directory first, in case we want to import from it. sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) # Must set this env var *before* importing any part of Django os.environ['DJANGO_SETTINGS_MODULE'] = 'errorbucket.settings' import django.core.handlers.wsgi from django.core.signals import got_request_exception import django.db import django.dispatch.dispatcher def log_exception(*args, **kwds): logging.exception('Exception in request:') got_request_exception.connect(log_exception) # Log errors. got_request_exception.disconnect(django.db._rollback_on_exception) # Unregister the rollback event handler. def main(): util.run_wsgi_app(django.core.handlers.wsgi.WSGIHandler()) if __name__ == '__main__': main()
# Force Django to reload its settings. from django.conf import settings settings._target = None # Must set this env var before importing any part of Django os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings' import logging import django.core.handlers.wsgi import django.core.signals import django.db import django.dispatch.dispatcher def log_exception(*args, **kwds): logging.exception('Exception in request:') from django.core.signals import got_request_exception # Log errors. got_request_exception.connect(log_exception) # Unregister the rollback event handler. got_request_exception.disconnect(django.db._rollback_on_exception) def main(): # Create a Django application for WSGI. application = django.core.handlers.wsgi.WSGIHandler() # Run the WSGI CGI handler with that application. util.run_wsgi_app(application) if __name__ == '__main__': main()