简体   繁体   English

Django未记录所有错误

[英]Django not logging all errors

I have the following logging config set up in Django 1.8: 我在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',
        },
    },
}

Moreover, I'm also logging the stdout and stderr of gunicorn into two separate files via supervisord. 此外,我还将通过管理员将gunicorn的stdout和stderr记录到两个单独的文件中。

My problem is that not all errors are showing up in Django logs. 我的问题是,并非所有错误都显示在Django日志中。 For example, there is a case when I had a simple .get() query in a model's save function, which raised a DoesNotExist exception in the admin page. 例如,在DoesNotExist情况下,我在模型的保存函数中有一个简单的.get()查询,这在管理页面中引发了DoesNotExist异常。 This exception did not show up at all in any Django log, all I could see was the 500 in the nginx log for a POST request. 这个异常在任何Django日志中都没有出现,我所能看到的只是nginx日志中有POST请求的500。

When I tried with debug mode in local machine, it produced the detailed error page, but what if I couldn't reproduce a bug in a local machine? 当我在本地计算机上尝试调试模式时,它会产生详细的错误页面,但是如果我无法在本地计算机上重现错误,该怎么办?

Why are 500 errors silently disappearing in Django and how can I fix it? 为什么Django中会自动消失500个错误,我该如何解决?

// I know that Sentry is able to report such exception errors, I'm looking for a way which doesn't involve using an external service. //我知道Sentry能够报告此类异常错误,我正在寻找一种不涉及使用外部服务的方法。

I debugged the case, it was a combination of two things: 我调试了一下,这是两件事的结合:

  1. Without specifying SERVER_EMAIL , Django sends admin emails from root@localhost . 在不指定SERVER_EMAIL ,Django从root@localhost发送管理电子邮件。 The SMTP provider I'm using (Mandrill) silently blocks all emails from such address, thus I never got the emails, nor any log at Mandrill. 我正在使用的SMTP提供程序(Mandrill)默默地阻止来自该地址的所有电子邮件,因此我从没收到过电子邮件,也没有在Mandrill上获得任何日志。

Solution was to specify SERVER_EMAIL to a real address and test admin email sending using mail_admins() . 解决方案是将SERVER_EMAIL指定为真实地址,并使用mail_admins()测试管理员发送的电子邮件。

  1. django.security and django.request loggers are set not to propagate by default, thus my root logger '' did not catch them. django.securitydjango.request记录器默认设置为不传播,因此我的root记录器''没有捕获到它们。

Solution was to re-specify them and set propagate to True. 解决方案是重新指定它们并将传播设置为True。 This way they both send emails and are visible in the log files as well. 这样,他们既可以发送电子邮件,也可以在日志文件中看到它们。

My working logger configuration is the following: 我的工作记录器配置如下:

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,
        },
    },
}

Reading this code from django.core.handlers.base.BaseHandler , 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)

I see 2 possibilities : 我看到两种可能性:

  1. settings.DEBUG_PROPAGATE_EXCEPTIONS is True settings.DEBUG_PROPAGATE_EXCEPTIONSTrue
  2. your defintion of the loggers with 'loggers': { '': { ... doesn't work for the errors catched at django level 您用'loggers': { '': { ...定义的记录'loggers': { '': { ...对于在django级别捕获的错误不起作用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM