Permalink
Browse files

Improved the exception handling to use logging where available & only…

… manually send errors on Django <1.3. Thanks to cyberdelia for the original patch!
  • Loading branch information...
1 parent ed0fe09 commit 7dd3905b306b0ea447bd0c3e61ef8e71c590b7da @cyberdelia cyberdelia committed with toastdriven Apr 28, 2011
Showing with 95 additions and 36 deletions.
  1. +15 −9 tastypie/resources.py
  2. +53 −27 tests/core/tests/resources.py
  3. +8 −0 tests/core/utils.py
  4. +19 −0 tests/settings_core.py
View
@@ -1,4 +1,6 @@
+import logging
import warnings
+import django
from django.conf import settings
from django.conf.urls.defaults import patterns, url
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, ValidationError
@@ -226,16 +228,20 @@ def _handle_500(self, request, exception):
# When DEBUG is False, send an error message to the admins (unless it's
# a 404, in which case we check the setting).
- if not isinstance(exception, (NotFound, ObjectDoesNotExist)) or getattr(settings, 'SEND_BROKEN_LINK_EMAILS', False):
- from django.core.mail import mail_admins
- subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path)
- try:
- request_repr = repr(request)
- except:
- request_repr = "Request repr() unavailable"
+ if not isinstance(exception, (NotFound, ObjectDoesNotExist)):
+ log = logging.getLogger('django.request.tastypie')
+ log.error('Internal Server Error: %s' % request.path, exc_info=sys.exc_info(), extra={'status_code': 500, 'request':request})
+
+ if django.VERSION < (1, 3, 0) and getattr(settings, 'SEND_BROKEN_LINK_EMAILS', False):
+ from django.core.mail import mail_admins
+ subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path)
+ try:
+ request_repr = repr(request)
+ except:
+ request_repr = "Request repr() unavailable"
- message = "%s\n\n%s" % (the_trace, request_repr)
- mail_admins(subject, message, fail_silently=True)
+ message = "%s\n\n%s" % (the_trace, request_repr)
+ mail_admins(subject, message, fail_silently=True)
# Prep the data going out.
data = {
@@ -2,6 +2,7 @@
import copy
import datetime
from decimal import Decimal
+import django
from django.conf import settings
from django.contrib.auth.models import User
from django.core.cache import cache
@@ -24,6 +25,7 @@
from tastypie.validation import Validation, FormValidation
from core.models import Note, Subject, MediaBit
from core.tests.mocks import MockRequest
+from core.utils import SimpleHandler
try:
import json
except ImportError:
@@ -2313,31 +2315,55 @@ def test_debug_on_without_full(self):
def test_debug_off(self):
settings.DEBUG = False
settings.TASTYPIE_FULL_DEBUG = False
- mail.outbox = []
-
- resp = self.resource.wrap_view('get_list')(self.request, pk=1)
- self.assertEqual(resp.status_code, 500)
- self.assertEqual(resp.content, '{"error_message": "Sorry, this request could not be processed. Please try again later."}')
- self.assertEqual(len(mail.outbox), 1)
- # Ensure that 404s don't send email.
- resp = self.resource.wrap_view('get_detail')(self.request, pk=10000000)
- self.assertEqual(resp.status_code, 404)
- self.assertEqual(resp.content, '{"error_message": "Sorry, this request could not be processed. Please try again later."}')
- self.assertEqual(len(mail.outbox), 1)
-
- # Ensure that 404s (with broken link emails enabled) DO send email.
- settings.SEND_BROKEN_LINK_EMAILS = True
- resp = self.resource.wrap_view('get_detail')(self.request, pk=10000000)
- self.assertEqual(resp.status_code, 404)
- self.assertEqual(resp.content, '{"error_message": "Sorry, this request could not be processed. Please try again later."}')
- self.assertEqual(len(mail.outbox), 2)
-
- # Now with a custom message.
- settings.TASTYPIE_CANNED_ERROR = "Oops, you bwoke it."
-
- resp = self.resource.wrap_view('get_list')(self.request, pk=1)
- self.assertEqual(resp.status_code, 500)
- self.assertEqual(resp.content, '{"error_message": "Oops, you bwoke it."}')
- self.assertEqual(len(mail.outbox), 3)
- mail.outbox = []
+ if django.VERSION >= (1, 3, 0):
+ SimpleHandler.logged = []
+
+ resp = self.resource.wrap_view('get_list')(self.request, pk=1)
+ self.assertEqual(resp.status_code, 500)
+ self.assertEqual(resp.content, '{"error_message": "Sorry, this request could not be processed. Please try again later."}')
+ self.assertEqual(len(SimpleHandler.logged), 1)
+
+ # Ensure that 404s don't send email.
+ resp = self.resource.wrap_view('get_detail')(self.request, pk=10000000)
+ self.assertEqual(resp.status_code, 404)
+ self.assertEqual(resp.content, '{"error_message": "Sorry, this request could not be processed. Please try again later."}')
+ self.assertEqual(len(SimpleHandler.logged), 1)
+
+ # Now with a custom message.
+ settings.TASTYPIE_CANNED_ERROR = "Oops, you bwoke it."
+
+ resp = self.resource.wrap_view('get_list')(self.request, pk=1)
+ self.assertEqual(resp.status_code, 500)
+ self.assertEqual(resp.content, '{"error_message": "Oops, you bwoke it."}')
+ self.assertEqual(len(SimpleHandler.logged), 2)
+ SimpleHandler.logged = []
+ else:
+ mail.outbox = []
+
+ resp = self.resource.wrap_view('get_list')(self.request, pk=1)
+ self.assertEqual(resp.status_code, 500)
+ self.assertEqual(resp.content, '{"error_message": "Sorry, this request could not be processed. Please try again later."}')
+ self.assertEqual(len(mail.outbox), 1)
+
+ # Ensure that 404s don't send email.
+ resp = self.resource.wrap_view('get_detail')(self.request, pk=10000000)
+ self.assertEqual(resp.status_code, 404)
+ self.assertEqual(resp.content, '{"error_message": "Sorry, this request could not be processed. Please try again later."}')
+ self.assertEqual(len(mail.outbox), 1)
+
+ # Ensure that 404s (with broken link emails enabled) DO send email.
+ settings.SEND_BROKEN_LINK_EMAILS = True
+ resp = self.resource.wrap_view('get_detail')(self.request, pk=10000000)
+ self.assertEqual(resp.status_code, 404)
+ self.assertEqual(resp.content, '{"error_message": "Sorry, this request could not be processed. Please try again later."}')
+ self.assertEqual(len(mail.outbox), 2)
+
+ # Now with a custom message.
+ settings.TASTYPIE_CANNED_ERROR = "Oops, you bwoke it."
+
+ resp = self.resource.wrap_view('get_list')(self.request, pk=1)
+ self.assertEqual(resp.status_code, 500)
+ self.assertEqual(resp.content, '{"error_message": "Oops, you bwoke it."}')
+ self.assertEqual(len(mail.outbox), 3)
+ mail.outbox = []
View
@@ -0,0 +1,8 @@
+import logging
+
+
+class SimpleHandler(logging.Handler):
+ logged = []
+
+ def emit(self, record):
+ SimpleHandler.logged.append(record)
View
@@ -3,3 +3,22 @@
ROOT_URLCONF = 'core.tests.api_urls'
MEDIA_URL = 'http://localhost:8080/media/'
+
+LOGGING = {
+ 'version': 1,
+ 'disable_existing_loggers': True,
+ 'handlers': {
+ 'simple': {
+ 'level': 'ERROR',
+ 'class': 'core.utils.SimpleHandler',
+ }
+ },
+ 'loggers': {
+ 'django.request': {
+ 'handlers': ['simple'],
+ 'level': 'ERROR',
+ 'propagate': False,
+ },
+ }
+}
+

0 comments on commit 7dd3905

Please sign in to comment.