title: Suppressing Django mod_wsgi IOErrors
body: <p>These IOErrors are fairly well known, as seen in other SO threads (see below), and can be caused by a user closing their browser mid-upload. For a discussion of why there is no simple solution, see <a href="http://groups.google.com/group/django-developers/browse_thread/thread/71cd0bbc76113ac8" rel="nofollow noreferrer">this django-developers thread</a>.</p>
  
  <p>I first tried the middleware option described in an answer to <a href="https://stackoverflow.com/questions/3823280/ioerror-request-data-read-error">this ioerror SO thread</a> (except in our case I would branch on the request uri). <em>It didn't work</em>: I could capture the response and see that as far as Django was concerned, there wasn't a file included in the post, and it was returning a 200 response with the validation error. <em>And yet</em>, I can still see the IOError in Apache's error log.</p>
  
  <p>Next we found <a href="https://code.djangoproject.com/ticket/10046#comment:20" rel="nofollow noreferrer">this discussion on a django bug</a> which suggests you should suppress this with a <strong>Logging</strong> filter. I tried attaching the filter to our custom logger, the root logger and 'django.request' ... I <em>still</em> can't see the IOError to suppress it! I can only see log messages associated with the failed validation of the form.</p>
  
  <p>Any suggestions?</p>
  
  <p>[ Edit: here is my setup ]</p>
  
  <p>In settings.py (mostly copied from Django's <code>conf/global_settings.py</code>):</p>
  
  <pre><code>DEBUG = False
  
  LOGGING = {
      'version': 1,
      'disable_existing_loggers': False,
      'filters': {
          'ioerrsquash': {
              '()': 'es.ioerr_filter.IOErrorFilter'
          }    },
      'handlers': {
              'mail_admins': {
              'level': 'ERROR',
              'class': 'django.utils.log.AdminEmailHandler',
              'filters': ['ioerrsquash']
          }
      },
      'loggers': {
          'django.request': {
              'handlers': ['mail_admins'],
              'level': 'ERROR',
              'propagate': True,
          },
          'wsgi.errors': { # added this logger after django.request failed
              'handlers': ['mail_admins'],
              'level': 'ERROR',
              'propagate': True,
         }
      }
  }
  </code></pre>
  
  <p>Content of ioerr_filter.py (obviously just for testing purposes):</p>
  
  <pre><code>import logging
  import sys
  from django.conf import settings
  
  class IOErrorFilter(logging.Filter):
      def filter(self, record):
          LOGF = "%s/BU_IOERR.log" % settings.LOG_FILE_DIR
          f = open(LOGF, 'a')
          f.write('... record\n')
          f.write(str(record))
          f.write('\n... exc_info\n')
          f.write(str(sys.exc_info()))
          f.write('\n...\n')
          return True
  </code></pre>