【问题标题】:Celery+Django -- How to log non-task moduleCelery+Django -- 如何记录非任务模块
【发布时间】:2015-12-25 01:28:49
【问题描述】:

目前,我的 Django+Docker-Compose 项目可以使用 Celery 制作主要的上传功能,insertIntoDatabase,这是一个在后台正常运行的异步任务。我使用名为 worker 的 Docker 容器运行 Celery,我可以在控制台中看到它的日志。但是,通常在 insertIntoDatabase 中有效的日志记录现在不再发生。

views.py开始上传:

from .tasks import db_ins_task
...
db_ins_task.delay(datapoints, user, description) # datapoints is a list of dictionaries, user and description are simple strings

而任务在tasks.py中是这样定义的:

@app.task()
def db_ins_task(datapoints, user, description):
    from utils.db.databaseinserter import insertIntoDatabase
    insertIntoDatabase(datapoints, user, description)

所以在databaseinserter.py 中,以下日志记录不再起作用:

logger = logging.getLogger('myapp.databaseinserter')
...
def insertIntoDatabase(datapoints, user, description):
    # do the database insertion work
    ...
    logger.info("This upload took %.3g seconds", elapsed_time) 

最后的信息日志应该转到我在settings.py 中配置的日志文件。现在insertIntoDatabase 是从任务调用而不是直接调用的,此类信息日志不再出现在正确的日志文件中。我的项目中存在的所有其他日志记录仍然可以正常工作。我应该怎么做才能使日志记录再次工作?

为了进一步参考,这里是 celery.py 的一部分,位于名为 taskman 的单独应用程序中:

from __future__ import absolute_import
import os
from django.apps import AppConfig
from celery import Celery, Task

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproj.settings')

from django.conf import settings

app = Celery('myproj')
class CeleryConfig(AppConfig):
    name = 'taskman'
    verbose_name = 'Celery Config'

    def ready(self):
        app.config_from_object('django.conf:settings')
        app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

这是settings.py中日志记录设置的相关部分:

LOGGING = {
    ...
    'handlers' = {
    ...
        'dbinsfile': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'maxBytes':LOG_LIMIT,
            'backupCount':10,
            'filename':'logs/insvals.log',
            'formatter':'values',
        },
    ...

    },
    'formatters' = {
    ...
        'values': {
            'format':'>>> [%(asctime)s.%(msecs)03d] %(levelname)s: %(message)s',
            'datefmt':"%Y/%m/%d %H:%M:%S",
        },
    ...
    },
    'loggers' = {
    ...
        'myapp.databaseinserter': {
            'handlers':['dbinsfile'],
            'level':'DEBUG',
            'propagate':False,
        },
    ...
    }
}

编辑: 我认为问题在于 Celery 似乎在劫持根级记录器或类似的东西。我已经尝试过CELERYD_HIJACK_ROOT_LOGGER = False,但不幸的是它并没有改变任何东西。我还尝试将以下内容添加到settings.py

from celery.signals import setup_logging
@setup_logging.connect
def logging_prevent_celery_hijack(loglevel, logfile, format, colorize, **kwargs):
    import logging.config
    logging.config.dictConfig(LOGGING)

在信号和日志记录方面遵循 Celery 文档,但这似乎也没有效果。

【问题讨论】:

  • “不再有效” 是什么意思?如果代码是从您的 Django 项目中调用的(例如在视图中),它可以工作,但如果从任务中调用,那么它就不起作用?您的工作人员如何配置日志记录?
  • “不再有效”意味着我在insertIntoDatabase 中输入的日志语句不再发生。我以前直接调用函数,但现在我调用调用函数的任务。所有日志记录都在settings.py 中按照 Django 文档进行配置。
  • 对,那么我将如何在 Celery 应用程序中处理这个问题?我在一个名为taskman 的应用程序中有celery.py,我将它设置为使用我的Django 设置,该设置目前正在运行。我还需要做什么才能使工作人员基本上可以执行与原始功能相同的日志记录?
  • 我发现使用AppConfig 实例调用Celery 的配置函数很不寻常。我的celery.py 的最高范围内一直有app.config_from_object()app.autodiscover_tasks()。但我无法确定到底出了什么问题。
  • 您找到解决方案了吗?我有完全相同的问题

标签: python django celery


【解决方案1】:

来自the official document

from celery.utils.log import get_task_logger

logger = get_task_logger(__name__)

如果logger.xxxx()被Celery worker在函数内部调用,则使用Celery配置的logger;否则,它将是手动配置的。该行为与函数所属的位置无关。

【讨论】:

    猜你喜欢
    • 2019-01-04
    • 2017-01-12
    • 2018-09-22
    • 2018-08-13
    • 2018-11-13
    • 2019-11-08
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    相关资源
    最近更新 更多