python - django.request 记录器没有传播到根?

标签 python django logging

使用 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.requestpropagate = 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/

相关文章:

python - 如何向 django app python 模块添加属性?

java - 在没有maven的多模块J2EE Web项目中配置log4j2

python - 如何在logging.ini文件中使用django设置?

python - 如何在python上捕获ffmpeg连接错误

python - 无需下载视频即可捕获 YouTube 视频以供进一步处理

python - 需要 pythonic 方式来安排带有参数的一次性作业

pythonic方式打印数据库中的列条件(psql)

django - 使用 Django Simple History 创建历史记录的问题

python - django - 自定义管理搜索的最简单方法

ruby-on-rails - 如何使用默认的 Rails 记录器记录 Ruby 异常的整个回溯?