我有一个这样的自定义过滤器:
proj/proj/log_utils/filters.py:
import logging
class OnlyThisSeverity(logging.Filter):
def filter(self, record):
print('levelname: {}'.format(record.levelname))
return record.levelno == logging.INFO
Django 设置看起来像这样:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'filters': {
'only_this_severity': {
'()': 'android_blend.log_utils.filters.OnlyThisSeverity',
}
},
'loggers': {
'my_app': {
'handlers': ('console',), # 'console'
'level': 'INFO',
'propagate': False,
'filters': ['only_this_severity']
},
}
}
在my_app/test.py
里面,我有一个这样的函数:
import logging
logger = logging.getLogger(__name__)
def handle(self, *args, **kwargs):
logger.info('Reporting info......')
logger.error('Reporting error......')
如果我的筛选器工作正常,我应该只在控制台中看到Reporting info
,而我看到两行。 所以问题是only_this_severity
过滤器被忽略了。 但是,如果我在console
处理程序定义中移动filters
,则实现了我的目标。我做错了什么?我希望过滤器工作 对于记录器my_app
,而不仅仅是在处理程序级别。 我的最终目标是改变日志记录库的自定义行为。也就是说,对于级别"X"的处理程序,我希望他们只尊重级别"X"的记录,而不是"X 及更高"的记录。
即使在记录器级别添加过滤器,您的过滤器似乎也能正常工作。
这是我当前的输出:
levelname: INFO
Reporting info......
levelname: ERROR
这显示了代码如何在两个日志操作中到达筛选器,但筛选错误记录。
我认为问题可能出在记录器层次结构中。当您将test.py
用作导入的模块时,您获得的不是'my_app'
记录器,而是不存在的'my_app.test'
。
发生这种情况时,核心将检索根记录器并将默认配置"传播"到名为'my_app.test'
的新记录器,并将其包含在日志层次结构中。此记录器没有启用您的过滤器。
尝试通过传递其名称来强制获取'my_app'
记录器:
import logging
logger = logging.getLogger('my_app')
def handle(self, *args, **kwargs):
logger.info('Reporting info......')
logger.error('Reporting error......')
或者,可以使用根记录器定义筛选器,然后让应用程序为您创建层次结构:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'filters': {
'only_this_severity': {
'()': 'android_blend.log_utils.filters.OnlyThisSeverity',
}
},
'loggers': {
'root': {
'handlers': ('console',), # 'console'
'level': 'INFO',
'filters': ['only_this_severity']
},
}
}
我个人喜欢这种方法,因为可以安全地调用
logger = logging.getLogger(__name__)
以显示(使用正确的格式化程序(您正在记录的模块。
从 https://docs.python-guide.org/writing/logging/
在库中实例化记录器的最佳做法是仅 使用
__name__
全局变量创建它们:日志记录模块 使用点表示法创建记录器的层次结构,因此使用__name__
确保没有名称冲突。