[英]Custom Python logging formatter works with fileConfig but not with dictConfig?
我已经花了几个小时试图弄清楚为什么这两个日志配置,据我所知应该是 100% 相同的,不会导致相同的行为:
LOGGING_CONFIG = {
'version': 1,
'disable_existing_loggers': False,
'root': {
'handlers': ['console'],
'level': 'INFO',
},
'gunicorn.access': {
'level': 'INFO',
'handlers': ['access_console'],
'propagate': False,
'qualname': 'gunicorn.access',
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'stream': 'ext://sys.stderr',
'formatter': 'syslog',
},
'access_console': {
'class': 'logging.StreamHandler',
'stream': 'ext://sys.stdout',
'formatter': 'docker_access',
},
},
'formatters': {
'syslog': {
'()': 'citi.logging.DockerFormatter',
'fmt': 'SYSLOG %(asctime)s [%(levelname)s] %(name)s: %(message)s',
},
'docker_access': {
'()': 'citi.logging.DockerFormatter',
'fmt': 'GUNICORN_ACCESS %(asctime)s %(message)s',
},
},
}
[loggers]
keys=root,gunicorn.access
[handlers]
keys=console,access_console
[formatters]
keys=syslog,docker_access
[logger_root]
level=INFO
handlers=console
[logger_gunicorn.access]
level=INFO
handlers=access_console
propagate=0
qualname=gunicorn.access
[handler_console]
class=StreamHandler
formatter=syslog
args=(sys.stderr, )
[handler_access_console]
class=StreamHandler
formatter=docker_access
args=(sys.stdout, )
[formatter_syslog]
class=citi.logging.DockerFormatter
format=SYSLOG %(asctime)s [%(levelname)s] %(name)s: %(message)s
[formatter_docker_access]
class=citi.logging.DockerFormatter
format=GUNICORN_ACCESS %(asctime)s %(message)s
当我使用logging.config.fileConfig
并将包含第二个代码块的文件传递给它时,它工作正常。 gunicorn.access
记录器将其格式化程序更改为具有指定format
字符串的自定义DockerFormatter
类(它是logging.Formatter
的简单子类)。 访问日志如下所示:
GUNICORN_ACCESS 2021-07-16 18:59:56,454 172.18.0.1 - - "GET /citi/server-status HTTP/1.0" 200 11 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36" 11766
但是当我使用logging.config.dictConfig
并将它传递给顶部的 dict 时,除了自定义格式化程序之外的所有内容都可以工作。 格式化程序似乎仍然设置为 Gunicorn 提供的原始默认值(也许??)。 输出是:
172.18.0.1 - - "GET /citi/server-status HTTP/1.0" 200 11 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36" 7549
通过使用logging_tree
包,我可以知道gunicorn.access
的格式化程序在使用dictConfig
时是某种默认dictConfig
。 它应该是这样的:
o<--"gunicorn"
| Level NOTSET so inherits level INFO
| |
| o "gunicorn.access"
| | Level INFO
| | Propagate OFF
| | Handler Stream <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
| | Formatter <citi.logging.DockerFormatter object at 0x7f68240e7d90>
但它看起来像这样:
o<--"gunicorn"
| Level NOTSET so inherits level INFO
| |
| o "gunicorn.access"
| | Level INFO
| | Propagate OFF
| | Handler Stream <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
| | Formatter fmt='%(message)s' datefmt=None
在DockerFormatter
类的调用方式方面,我可以检测到的唯一区别是fileConfig
表单使用位置参数调用它,而dictConfig
使用(正确的)关键字参数调用它。
似乎正在发生的是格式化程序正在正确构造,但没有正确分配。 我不知道为什么。
最令人气愤的是,我实际上已经大大简化了我的日志配置。 在我的完整配置中,我设置了一个基于structlog
的自定义格式化程序,其配置方式与syslog
和docker_access
与DockerFormatter
配置方式DockerFormatter
,但它确实有效。 我很沮丧。 >_<
当然,我在离开办公室前的最后一次努力(迟到了几个小时......)确实有效。 事实证明,我对 Gunicorn 的默认设置保持原样是正确的,因为我完全错过了 dictConfig 字典中绝对必要的'loggers'
子词。
它应该是这样的:
LOGGING_CONFIG = {
'version': 1,
'disable_existing_loggers': False,
'root': {
'handlers': ['console'],
'level': 'INFO',
},
'loggers' {
'gunicorn.access': {
'level': 'INFO',
'handlers': ['access_console'],
'propagate': False,
'qualname': 'gunicorn.access',
},
}
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.