我们正在使用uWSGI来为我们的Django应用程序提供服务。我们还利用uWSGI的骡子和假脱机系统定期运行作业,并在请求/响应周期之外异步执行某些任务。
处理HTTP请求的uWSGI部分使用Django logging configuration就好了。但是,在使用uWSGI的cron
和mulefunc
功能时,通常根本不会配置记录器 - 您将调用log.error()和异常只是消失了。我们发现了一个奇怪的解决方法,我将在下面解释。
以下是settings.py
中的日志记录设置。 StreamHandler默认路由到stderr,因此我们应该看到任何级别为DEBUG且更高级别的日志都路由到stderr。
LOGGING = { 'version': 1, 'disable_existing_loggers': True, 'formatters': { 'verbose': { 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' }, }, 'handlers': { 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'verbose' } }, 'loggers': { '': { 'handlers': ['console'], 'level': 'NOTSET', } } }
以下是一个不起作用的例子:
from uwsgidecorators import mulefunc log = logging.getLogger(__name__) @timer(10, target="mule") def test_mule_logging(signum): log.error("You'll never see this message")
然而,有一个非常奇怪的解决方法。如果你导入Django的设置,并且访问它上面的一个键,那么记录器就会神奇地工作。例如:
from django.conf import settings getattr(settings, "doesntmatter", None) from uwsgidecorators import timer import logging log = logging.getLogger(__name__) @timer(10, target="mule") def test_mule_logging(signum): log.error("I WILL see this log!")
这似乎是一个可怕的解决方法。
答案 0 :(得分:0)
我认为你描述的行为是有道理的。
在普通工作者中,uwsgi加载一个WSGI应用程序,使django加载设置,并作为其中一部分配置全局Python日志记录系统。由django app运行并包含日志记录语句的库代码最终由日志记录配置处理(无需知道django存在或配置了日志记录系统)。
在mule中,uwsgi只运行您提供的代码,而不是为常规worker定义的wsgi模块/脚本,因此没有任何内容正在配置日志系统。骡子仍然在相同的环境中运行(uid,gid,chdir,virtualenv,pythonpath,像DJANGO_SETTINGS_MODULE这样的env vars),因此调用django.setup()
(或django.configure_settings
)将导入您的设置并配置全局日志记录系统(作为mule worker的Python进程的全局),修复日志记录调用。
最后一块拼图:django.conf.settings
模块是一个特殊的懒惰对象,因此在django完成自身配置之前可以通过各种模块导入它,并且延迟真正加载设置,直到某些东西试图访问模块属性。在具有django.setup()
的现代Django版本中可以更明确地获得此行为。