使用 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
的 View ,则回溯将打印到控制台:
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
记录器没有配置,它会传播到根记录器,它将所有内容打印到控制台。
我没有发现任何 django.request
特殊的信息。
为什么它不起作用?
Here我读到:
Prior to Django 1.5, the LOGGING setting always overwrote the default Django logging configuration. From Django 1.5 forward, it is possible to get the project’s logging configuration merged with Django’s defaults, hence you can decide if you want to add to, or replace the existing configuration.
If the disable_existing_loggers key in the LOGGING dictConfig is set to True (which is the default) the default configuration is completely overridden. Alternatively you can redefine some or all of the loggers by setting disable_existing_loggers to 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.request
有 propagate = False
。但就我而言,我有 'disable_existing_loggers': True
。
最佳答案
解决办法是阻止Django配置日志,自己处理。幸运的是,这很容易。在 settings.py
中:
LOGGING_CONFIG = None
LOGGING = {...} # whatever you want, as you already have
import logging.config
logging.config.dictConfig(LOGGING)
更新 ~2015 年 3 月:Django 有 clarified他们的documentation :
If the disable_existing_loggers key in the LOGGING dictConfig is set to True then all loggers from the default configuration will be disabled. Disabled loggers are not the same as removed; the logger will still exist, but will silently discard anything logged to it, not even propagating entries to a parent logger. Thus you should be very careful using 'disable_existing_loggers': True; it’s probably not what you want. Instead, you can set disable_existing_loggers to False and redefine some or all of the default loggers; or you can set LOGGING_CONFIG to None and handle logging config yourself.
为了后代和细节:解释?我认为大部分的困惑归结为 Django 的可怜 explanation disable_existing_loggers
,它表示当为 True 时,“默认配置被完全覆盖”。在您自己的答案中,您发现这是不正确的;发生的情况是 Django 已经配置的现有记录器禁用没有被替换。
Python 日志记录 documentation更好地解释它(强调):
disable_existing_loggers – If specified as False, loggers which exist when this call is made are left alone. The default is True because this enables old behaviour in a backward-compatible way. This behaviour is to disable any existing loggers unless they or their ancestors are explicitly named in the logging configuration.
基于 Django 文档,我们认为“使用我自己的 LOGGING 配置覆盖默认值,我未指定的任何内容都会冒泡”。我也被这个期望绊倒了。我们期望的行为类似于 replace_existing_loggers(这不是真实的)。相反,Django 记录器是闭嘴而不是冒泡。
我们首先需要阻止设置这些 Django 记录器,这里是 Django docs更有帮助:
If you don’t want to configure logging at all (or you want to manually configure logging using your own approach), you can set LOGGING_CONFIG to None. This will disable the configuration process.
Note: Setting LOGGING_CONFIG to None only means that the configuration process is disabled, not logging itself. If you disable the configuration process, Django will still make logging calls, falling back to whatever default logging behavior is defined.
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)
关于python - django.request 记录器没有传播到根?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20282521/