uWSGI异步函数不了解Django的日志记录设置

时间:2015-02-23 21:29:18

标签: python django logging uwsgi

我们正在使用uWSGI来为我们的Django应用程序提供服务。我们还利用uWSGI的骡子和假脱机系统定期运行作业,并在请求/响应周期之外异步执行某些任务。

处理HTTP请求的uWSGI部分使用Django logging configuration就好了。但是,在使用uWSGI的cronmulefunc功能时,通常根本不会配置记录器 - 您将调用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!")

这似乎是一个可怕的解决方法。

1 个答案:

答案 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版本中可以更明确地获得此行为。