django.request记录器不传播到根? [英] django.request logger not propagated to root?

查看:102
本文介绍了django.request记录器不传播到根?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Django 1.5.1:

  DEBUG = False 

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

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

 错误2013-11-29 13:33:23,102 base内部服务器错误:/ comment / ******* / 
追溯(最近的最后一次呼叫):
...
文件***** / comments / views.py,第10行,在帖子
1/0
ZeroDivisionError:整数除或模数为零
警告2013-11 -29 13:33:23,103 csrf禁止(CSRF cookie未设置):/ comment / ****** /
[29 / Nov / 2013 13:33:23]POST / comment / ** **** / HTTP / 1.0500 27

但是如果行留下评论,打印到控制台,只需:

  [29 / Nov / 2013 13:33:23]POST / comment / ** **** / HTTP / 1.0500 27 

我以为如果 django .request 记录器未配置,它会传播到根记录器,将所有内容打印到控制台。



我没有找到任何信息 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

 #Django的默认日志记录。这将向每个
#HTTP 500错误的网站管理员发送一封电子邮件。根据DEBUG,所有其他日志记录都被发送到
#控制台(DEBUG = True),或者通过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',
$,
},
'处理程序':{
'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 =无
LOGGING = {...}#无论你想要什么,因为你已经有

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

更新〜2015年3月:Django有澄清他们的文件


如果LOGGING dictConfig中的disable_existing_loggers键设置为
为True,则所有日志记录器的默认
配置将被禁用。禁用记录器与
删除不同;记录器仍然存在,但会静默地丢弃
任何记录到它,甚至不将条目传播到父
记录器。所以你应该非常小心使用
'disable_existing_loggers':True;这可能不是你想要的
相反,您可以将disable_existing_loggers设置为False并重新定义
某些或全部默认记录器;或者您可以将LOGGING_CONFIG设置为
无并自行处理日志记录。


对于后代和细节:强>解释?我认为大部分的混乱都归结为Django的穷人说明 disable_existing_loggers ,这表示当True,默认配置被完全覆盖。在你自己的答案中,你发现这是不正确的;发生了什么事情,Django已经配置的现有记录器已被禁用不被替换。



Python日志记录文档更好地解释(加重点):


disable_existing_loggers - 如果指定为False,则在执行此调用时存在
的记录器将单独存放。默认值为True,因为
这可以以向后兼容的方式启用旧的行为。 $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $

$
$ b

基于Django文档,我们认为,使用我自己的LOGGING配置覆盖默认值,而我不指定的任何东西将起泡。我也跳过了这个期望。我们期望的行为是沿着 replace_existing_loggers 的行(这不是一件真实的事情)。相反,Django记录器是关闭不会冒泡起来。



我们需要防止这些Django记录器的设置首先,这里的Django 文档是更有帮助:


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



注意:将LOGGING_CONFIG设置为无只意味着配置
进程被禁用,而不是自己记录。如果禁用
配置过程,Django仍然会进行日志记录调用,将
退回到定义的任何默认日志行为。


Django仍然会使用它的记录器,但是由于它们没有被配置处理(然后被禁用),所以这些记录器将按预期的方式起泡。以上设置的简单测试:

  manage.py shell 
>>>导入日志
>>>> logging.warning('root logger')
警告2014-03-11 13:35:08,832根根记录器
>>> l = logging.getLogger('django.request')
>>> l.warning('request logger')
警告2014-03-11 13:38:22,000 django.request request logger
>>> l.propagate,l.disabled
(1,0)


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

If I uncomment the commented lines and call a view which has 1/0, the traceback is printed to the console:

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

But if the lines stay commented, no traceback is printed to the console, just:

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

I thought if django.request logger is not configured, it would propagate to the root logger, which prints everything to console.

I didn't find any information that django.request is special.

Why it doesn't work?

Here I read:

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.

In 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'],
        },
    }
}

So by default django.request has propagate = False. But In my case I have 'disable_existing_loggers': True.

解决方案

The solution is to prevent Django from configuring logging and handle it ourselves. Fortunately this is easy. In settings.py:

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

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

UPDATE ~March 2015: Django has clarified their 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.

For posterity and detail: The explanation? Most of the confusion I think comes down to Django's poor explanation of disable_existing_loggers, which says that when True, "the default configuration is completely overridden". In your own answer you discovered that is not correct; what's happening is that the existing loggers, which Django already configures, are disabled not replaced.

The Python logging documentation explains it better (emphasis added):

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.

Based on Django docs we think, "override the defaults with my own LOGGING configuration and anything I don't specify will bubble up". I've tripped over this expectation as well. The behavior we expect is along the lines of replace_existing_loggers (which isn't a real thing). Instead the Django loggers are shut up not bubbled up.

We need to prevent the setup of these Django loggers in the first place and here the Django docs are more helpful:

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 will still use its loggers but since they are not handled (and then disabled) by the configuration, those loggers will bubble up as expected. A simple test with the above settings:

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)

这篇关于django.request记录器不传播到根?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆