7

I'm running a Django site (via Apache/mod_python) and I use Django's facilities to inform me and other developers about internal server errors. Sometimes errors like those appear:

Traceback (most recent call last):

  File "/opt/webapp/externals/lib/django/core/handlers/base.py", line 92, in get_response
    response = callback(request, *callback_args, **callback_kwargs)

  File "/opt/webapp/csite/apps/customers/views.py", line 29, in feedback
    form = FeedbackForm(request.POST)

  File "/opt/webapp/externals/lib/django/core/handlers/modpython.py", line 113, in _get_post
    self._load_post_and_files()

  File "/opt/webapp/externals/lib/django/core/handlers/modpython.py", line 96, in _load_post_and_files
    self._post, self._files = http.QueryDict(self.raw_post_data, encoding=self._encoding), datastructures.MultiValueDict()

  File "/opt/webapp/externals/lib/django/core/handlers/modpython.py", line 163, in _get_raw_post_data
    self._raw_post_data = self._req.read()

IOError: Client read error (Timeout?)

As far as I found out, those IOErrors are generated by clients that disconnect in the wrong moment and that it's not a problem of my site.

If that is the case: Can I disable the emails for those errors somehow? I really don't want to know about errors that I cannot fix and that aren't really errors.

vvvvv
  • 25,404
  • 19
  • 49
  • 81
Michael
  • 8,920
  • 3
  • 38
  • 56

3 Answers3

11

Extending the solution by @dlowe for Django 1.3, we can write the full working example as:

settings.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'supress_unreadable_post': {
            '()': 'common.logging.SuppressUnreadablePost',
        }
    },
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
            'filters': ['supress_unreadable_post'],
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
    }
}

common/logging.py

import sys, traceback

class SuppressUnreadablePost(object):
    def filter(self, record):
        _, exception, tb = sys.exc_info()
        if isinstance(exception, IOError):
            for _, _, function, _ in traceback.extract_tb(tb):
                if function == '_get_raw_post_data':
                    return False
        return True
  • 1
    This wasnt working for me. BUT! Turned out the problem was that I used sentry and raven, and the latter registered a handler to the get_request_exception signal. This path just skipped python logging (thus the filter), and wrote directly to sentry... – Vajk Hermecz Dec 27 '13 at 15:00
2

You should be able to write a Middleware to catch the exception and you can then "silence" those specific exceptions.

https://docs.djangoproject.com/en/2.2/topics/http/middleware/

Nemo
  • 2,441
  • 2
  • 29
  • 63
Brian Luft
  • 1,153
  • 8
  • 12
  • 2
    This will work for IOErrors that occur inside of view functions. What can you do for IOErrors outside of view function? e.g. when streaming a response back to the client e.g. return HttpResponse(open('large_text_file.txt')) – Eloff Oct 13 '11 at 21:46
  • updating this post with updated django documentation links. https://docs.djangoproject.com/en/1.10/topics/http/middleware/#process-exception – lyncas Dec 30 '16 at 21:29
2

In django 1.3 and up, you can use a logging filter class to suppress the exceptions which you aren't interested in. Here's the logging filter class I'm using to narrowly suppress IOError exceptions raised from _get_raw_post_data():

import sys, traceback
class _SuppressUnreadablePost(object):
    def filter(self, record):
        _, exception, tb = sys.exc_info()
        if isinstance(exception, IOError):
            for _, _, function, _ in traceback.extract_tb(tb):
                if function == '_get_raw_post_data':
                    return False
        return True

In Django 1.4, you will be able to do away with most of the complexity and suppress the new exception class UnreadablePostError. (See this patch).

dlowe
  • 726
  • 4
  • 9