小编典典

django.request记录器未传播到root?

python

使用Django 1.5.1:

DEBUG = False

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(message)s'
        },
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose',
        },
    },
    'loggers': {
        # root logger
        '': {
            'handlers': ['console'],
        },
        #'django.request': {
        #    'handlers': ['console'],
        #    'level': 'DEBUG',
        #    'propagate': False,
        #},
    }
}

如果我取消注释行,并调用一个具有的视图1/0,则将回溯打印到控制台:

ERROR 2013-11-29 13:33:23,102 base Internal Server Error: /comment/*******/
Traceback (most recent call last):
  ...
  File "*****/comments/views.py", line 10, in post
    1/0
ZeroDivisionError: integer division or modulo by zero
WARNING 2013-11-29 13:33:23,103 csrf Forbidden (CSRF cookie not set.): /comment/******/
[29/Nov/2013 13:33:23] "POST /comment/******/ HTTP/1.0" 500 27

但是,如果这些行保持注释状态,则不会向控制台打印回溯信息,只是:

[29/Nov/2013 13:33:23] "POST /comment/******/ HTTP/1.0" 500 27

我以为如果django.request未配置logger,它将传播到root logger,后者将所有内容打印到控制台。

我没有发现任何django.request特别的信息。

为什么不起作用?

在这里我读到:

在Django 1.5之前,LOGGING设置始终会覆盖默认的Django日志记录配置。从Django
1.5开始,可以将项目的日志记录配置与Django的默认配置合并,因此您可以决定是否要添加或替换现有配置。

如果LOGGING
dictConfig中的disable_existing_loggers键设置为True(默认设置),则默认配置将被完全覆盖。另外,您可以通过将disable_existing_loggers设置为False来重新定义部分或全部记录器。

django/utils/log.py

# Default logging for Django. This sends an email to the site admins on every
# HTTP 500 error. Depending on DEBUG, all other log records are either sent to
# the console (DEBUG=True) or discarded by mean of the NullHandler (DEBUG=False).
DEFAULT_LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse',
        },
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {
        'console':{
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
        },
        'null': {
            'class': 'django.utils.log.NullHandler',
        },
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        }
    },
    'loggers': {
        'django': {
            'handlers': ['console'],
        },
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': False,
        },
        'py.warnings': {
            'handlers': ['console'],
        },
    }
}

所以默认django.requestpropagate = False。但是就我而言'disable_existing_loggers': True


阅读 168

收藏
2021-01-20

共1个答案

小编典典

解决方案是防止Django配置日志记录并自行处理。幸运的是,这很容易。在settings.py

LOGGING_CONFIG = None
LOGGING = {...}  # whatever you want, as you already have

import logging.config
logging.config.dictConfig(LOGGING)

2015年3月更新
:Django已澄清文档

如果将LOGGING
dictConfig中的disable_existing_loggers键设置为True,则将禁用默认配置中的所有记录器。禁用的记录器与已删除的记录器不同;记录器仍将存在,但会静默丢弃记录到该记录器的所有内容,甚至不会将条目传播到父记录器。因此,使用’disable_existing_loggers’应该非常小心。这可能不是您想要的。相反,您可以将disable_existing_loggers设置为False,然后重新定义一些或所有默认记录器。或者您可以将LOGGING_CONFIG设置为None并自己处理日志记录配置。

对于后代和细节:
解释?我认为大多数混淆都归因于Django对的拙劣解释disable_existing_loggers,即解释为True时,“默认配置被完全覆盖”。在您自己的答案中,您发现这是不正确的;发生的事情是Django已配置的现有记录器被 禁用
而不是替换。

Python日志记录文档对其进行了更好的解释(添加了重点):

disable_existing_loggers
–如果指定为False,则在进行此调用时存在的记录器将被保留。默认值为True,因为它以向后兼容的方式启用了旧的行为。此行为是要 禁用
所有现有记录器,除非它们或它们的祖先在记录配置中明确命名。

根据Django文档,我们认为“用我自己的LOGGING配置覆盖默认值,任何我未指定的内容都会 冒出来 ”。我也超出了这个期望。我们期望的行为与
replace_existing_loggers相似 (这不是真品)。取而代之的是,Django记录器被 关闭, 没有 冒泡

首先,我们需要阻止这些Django记录器的设置,在这里Django文档更加有用:

如果您根本不想配置日志记录(或者想使用自己的方法手动配置日志记录),可以将LOGGING_CONFIG设置为None。这将禁用配置过程。

注意:将LOGGING_CONFIG设置为None仅表示禁用配置过程,而不记录自身。如果禁用配置过程,则Django仍会进行日志记录调用,而回退到已定义的默认日志记录行为。

Django仍将使用其记录器,但是由于配置未对其进行处理(然后禁用),因此这些记录器将按预期方式冒泡。使用上述设置的简单测试:

manage.py shell
>>> import logging
>>> logging.warning('root logger')
WARNING 2014-03-11 13:35:08,832 root root logger
>>> l = logging.getLogger('django.request')
>>> l.warning('request logger')
WARNING 2014-03-11 13:38:22,000 django.request request logger
>>> l.propagate, l.disabled
(1, 0)
2021-01-20