ansible.cfg文件劫持了我的django项目日志文件输出路径



我有一个奇怪的django日志文件输出问题,我在我的django1.11.11项目中使用了ansible 2.5.0模块,就像这个from ansible.plugins.callback import CallbackBase一样,而/etc/ansible/ansible.cfg文件中的log_path设置实际上对我的django项目日志文件输出生效,就像劫持:

# /etc/ansible/ansible.cfg file
# logging is off by default unless this path is defined
# if so defined, consider logrotate
log_path = /var/log/ansible.log

我所有的django日志输出到/var/log/ansible.log,这是一个非常奇怪的

# /var/log/ansible.log
2019-01-07 17:49:22,271 django.server "GET /docs/ HTTP/1.1" 200 1391207
2019-01-07 17:49:23,262 django.server "GET /docs/schema.js HTTP/1.1" 200 111440 

我确实在django设置中设置了LOGGING,django的设置也生效了,输出如下:

# /var/log/django_debug.log
"GET /docs/ HTTP/1.1" 200 1391207
"GET /docs/schema.js HTTP/1.1" 200 111440

它将是同一django项目的两个日志文件,位于我在django设置中定义的相同日志级别:

# django settings.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'INFO',
'class': 'logging.FileHandler',
'filename': '/var/log/django_debug.log',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'INFO',
'propagate': True,
},
},
}

您是否将Ansible作为Python模块导入?

TLDR:当您将Ansible作为模块导入时,Ansible库中的记录器实例会首先实例化,并且您最终会使用Ansible的记录器,除非您将disable_existing_loggers设置为True

为什么会发生这种情况

Python日志记录是一个单例,这意味着在给定的进程中,只有一个记录器对象可以存在于内存中。

库(如Ansible)也可以在内部使用记录器。在我的案例中,Ansible的记录器是在Ansible全局范围中的某个地方实例化的。https://github.com/ansible/ansible/blob/devel/lib/ansible/utils/display.py#L65

当您导入库时,记录器已经实例化,所以您自己的记录器将继承现有的日志处理程序,并且您最终将日志写入两个日志文件。

如何防止这种情况发生

请尝试将disable_existing_loggers设置切换为True

Django日志文档:https://docs.djangoproject.com/en/2.1/topics/logging/#configuring-记录

Python记录器本身的类似设置:https://docs.python.org/3/library/logging.config.html?highlight=disable_existing_loggers#logging.config.fileConfig

我的案例需要注意的一点是:我使用了logging.handlers.WatchedFileHandler,它似乎默认继承了以前的记录器。

如果这解决了您的问题,请提供反馈!

最新更新