Django没有记录所有错误

时间:2015-06-09 14:55:33

标签: python django logging nginx mandrill

我在Django 1.8中设置了以下日志配置:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': normpath(join(DJANGO_ROOT, '../../logs', 'django.log')),
        },
    },
    'loggers': {
        '': {
            'handlers': ['file'],
            'propagate': True,
            'level': 'DEBUG',
        },
    },
}

此外,我还通过supervisord将sticout和sticr of gunicorn记录到两个单独的文件中。

我的问题是并非所有错误都出现在Django日志中。例如,有一种情况我在模型的保存函数中有一个简单的.get()查询,它在管理页面中引发了DoesNotExist异常。在任何Django日志中都没有显示此异常,我只能看到nginx日志中的500个POST请求。

当我尝试在本地计算机上使用调试模式时,它会生成详细的错误页面,但是如果我无法在本地计算机中重现错误怎么办?

为什么500个错误会在Django中无声地消失,我该如何解决?

//我知道Sentry能够报告此类异常错误,我正在寻找一种不涉及使用外部服务的方法。

2 个答案:

答案 0 :(得分:3)

我调试了这个案例,它是两件事的组合:

  1. 如果不指定SERVER_EMAIL,Django会从root@localhost发送管理员电子邮件。我使用的SMTP提供商(Mandrill)默默地阻止来自此类地址的所有电子邮件,因此我从未收到过电子邮件,也没有收到Mandrill的任何日志。
  2. 解决方案是将SERVER_EMAIL指定为真实地址,并使用mail_admins()测试管理员电子邮件发送。

    1. django.securitydjango.request记录器默认设置为不传播,因此我的根记录器''没有捕获它们。
    2. 解决方案是重新指定它们并将传播设置为True。这样他们既可以发送电子邮件,也可以在日志文件中看到。

      我的工作记录器配置如下:

      LOGGING = {
          'version': 1,
          'disable_existing_loggers': False,
          'handlers': {
              'file': {
                  'level': 'DEBUG',
                  'class': 'logging.FileHandler',
                  'filename': normpath(join(DJANGO_ROOT, '../../logs', 'django.log')),
                  'formatter': 'verbose',
              },
              'mail_admins': {
                  'level': 'ERROR',
                  'class': 'django.utils.log.AdminEmailHandler'
              }
          },
          'formatters': {
              'verbose': {
                  'format': '%(asctime)s %(levelname)-8s [%(name)s:%(lineno)s] %(message)s',
              },
          },
          'loggers': {
              '': {
                  'handlers': ['file'],
                  'level': 'DEBUG',
              },
              'django.request': {
                  'handlers': ['mail_admins'],
                  'level': 'ERROR',
                  'propagate': True,
              },
              'django.security': {
                  'handlers': ['mail_admins'],
                  'level': 'ERROR',
                  'propagate': True,
              },
          },
      }
      

答案 1 :(得分:0)

django.core.handlers.base.BaseHandler

中读取此代码
def handle_uncaught_exception(self, request, resolver, exc_info):
    """
    Processing for any otherwise uncaught exceptions (those that will
    generate HTTP 500 responses). Can be overridden by subclasses who want
    customised 500 handling.
    Be *very* careful when overriding this because the error could be
    caused by anything, so assuming something like the database is always
    available would be an error.
    """
    if settings.DEBUG_PROPAGATE_EXCEPTIONS:
        raise

    logger.error('Internal Server Error: %s', request.path,
        exc_info=exc_info,
        extra={
            'status_code': 500,
            'request': request
        }
    )

    if settings.DEBUG:
        return debug.technical_500_response(request, *exc_info)

    # If Http500 handler is not installed, re-raise last exception
    if resolver.urlconf_module is None:
        six.reraise(*exc_info)
    # Return an HttpResponse that displays a friendly error message.
    callback, param_dict = resolver.resolve_error_handler(500)
    return callback(request, **param_dict)

我看到了两种可能性:

  1. settings.DEBUG_PROPAGATE_EXCEPTIONSTrue
  2. 您对'loggers': { '': { ...的记录器的定义不适用于django级别的错误