Source code for superdjango.contrib.errors.middleware

# Imports

from django.conf import settings
from django.core.cache import cache
from django import http
from django.http import HttpResponse
from django.views import debug
from hashlib import sha1
from importlib import import_module
import sys

# Exports

___all__ = (
    "ErrorCaptureMiddleware",
)

# Constants

ERROR_CAPTURE_DEBUG = getattr(settings, "SUPERDJANGO_ERROR_CAPTURE_DEBUG", False)
ERROR_CAPTURE_REPEAT_SECONDS = getattr(settings, "SUPERDJANGO_ERROR_CAPTURE_REPEAT_SECONDS", 3600)
ERROR_CAPTURE_HANDLERS = getattr(settings, "SUPERDJANGO_ERROR_CAPTURE_HANDLERS", list())

# Classes


[docs]class ErrorCaptureMiddleware(object): """Middleware for capturing exceptions.""" traceback = __import__('traceback')
[docs] def __init__(self, get_response): self.get_response = get_response
def __call__(self, request): return self.get_response(request)
[docs] def capture_exception(self, request, exception): """Runs the exception capture process. :param request: The current HTTP request. :param exception: The exception being raised. :rtype: BaseType[HttpResponse] """ # Just raise if it's a 404. if isinstance(exception, http.Http404): raise exception # Get content and info. content = self.traceback.format_exc() info = sys.exc_info() # Don't handle in DEBUG mode unless specifically requested. if settings.DEBUG and not ERROR_CAPTURE_DEBUG: return debug.technical_500_response(request, *info) # Hash is used to identify the exception in cache. _hash = sha1() _hash.update(content.encode("utf-8")) digest = _hash.hexdigest() # Don't do anything if the exception has been handled previously. if cache.get(digest) is not None: return # Cached to avoid repetition. cache.set(digest, content, ERROR_CAPTURE_REPEAT_SECONDS) # Initialize the report to be passed to the handlers. report = debug.ExceptionReporter(request, *info) # Iterate through handlers. The last result is returned if it's a response. context = dict() result = None for handler in ERROR_CAPTURE_HANDLERS: callback_class = self._get_handler_instance(handler) if callback_class is None: continue if result and type(result) is dict: context.update(result) instance = callback_class() result = instance(report, context=context) if result and isinstance(result, HttpResponse): return result return debug.technical_500_response(request, *info)
[docs] def process_exception(self, request, exception): """Process the exception.""" return self.capture_exception(request, exception)
# noinspection PyMethodMayBeStatic def _get_handler_instance(self, dotted): """Get the handler instance from the given dotted path. :param dotted: The dotted path to the handler. :type dotted: str :returns: The instance or ``None`` if it could not be loaded. """ class_name = dotted.split(".")[-1] dotted = dotted.replace(".%s" % class_name, "") try: module = import_module(dotted) try: return getattr(module, class_name) except AttributeError: return None except ImportError: return None