Отправлять сообщения журнала из всех задач сельдерея в один файл

Мне интересно, как настроить более конкретную систему ведения журнала. Все мои задачи используют

logger = logging.getLogger(__name__)

как логгер для всего модуля.

Я хочу, чтобы сельдерей регистрировался на "celeryd.log" и мои задачи на "tasks.log", но я понятия не имел, как это сделать. Используя CELERYD_LOG_FILE из django-сельдерея, я могу маршрутизировать все связанные с сельдереем сообщения журнала в celeryd.log, но в моих задачах нет следов журнальных сообщений.

Ответ 1

Примечание. Этот ответ устарел от Celery 3.0, где теперь вы используете get_task_logger(), чтобы настроить свой логгер для каждой задачи, Подробнее см. раздел журнала в разделе Что нового в документе Celery 3.0.


Сельдерей имеет специальную поддержку для ведения журнала, для каждой задачи. См. Документация по объекту:

Вы можете использовать регистратор рабочих данных для добавления диагностического вывода в журнал работника:

@celery.task()
def add(x, y):
    logger = add.get_logger()
    logger.info("Adding %s + %s" % (x, y))
    return x + y

Доступно несколько уровней ведения журналов, и параметр loglevel рабочих определяется независимо от того, будут ли они записаны в файл журнала.

Конечно, вы также можете просто использовать печать, поскольку все, что написано на стандартном выводе /-err, будет также записывается в файл журнала.

Под капотом это все еще стандартный протокол протоколирования python. Вы можете установить параметр CELERYD_HIJACK_ROOT_LOGGER для False, чтобы разрешить работу вашей собственной настройки ведения журнала, в противном случае сельдерей настроит обработку для вас.

Однако для задач вызов .get_logger() позволяет вам настроить отдельный файл журнала для каждой отдельной задачи. Просто передайте аргумент logfile, и он отправит сообщения журнала в этот отдельный файл:

@celery.task()
def add(x, y):
    logger = add.get_logger(logfile='tasks.log')
    logger.info("Adding %s + %s" % (x, y))
    return x + y 

И последнее, но не менее важное: вы можете просто настроить пакет верхнего уровня в python logging module и предоставить ему обработчик файлов своя. Я бы установил это с помощью сигнала celery.signals.after_setup_task_logger; здесь я предполагаю, что все ваши модули живут в пакете под названием foo.tasks (как в foo.tasks.email и foo.tasks.scaling):

from celery.signals import after_setup_task_logger
import logging

def foo_tasks_setup_logging(**kw):
    logger = logging.getLogger('foo.tasks')
    if not logger.handlers:
        handler = logging.FileHandler('tasks.log')
        formatter = logging.Formatter(logging.BASIC_FORMAT) # you may want to customize this.
        handler.setFormatter(formatter)
        logger.addHandler(handler)
        logger.propagate = False

after_setup_task_logger.connect(foo_tasks_setup_logging)

Теперь любой регистратор, чье имя начинается с foo.tasks, будет иметь все сообщения, отправленные в tasks.log, а не в корневой журнал (который не видит ни одного из этих сообщений, потому что .propagate - False).

Ответ 2

Просто подсказка: у Сельдерея есть собственный обработчик регистрации:

from celery.utils.log import get_task_logger
logger = get_task_logger(__name__)

Кроме того, сельдерей регистрирует все выходные данные задачи. Подробнее в Документы Celery для ведения журнала задач