Как регистрироваться в журнале celery вне задач celery (внутри представления django)?

Представьте конечную точку в проекте django

def my_view(request, my_id):
    if is_request_valid(request):
        logger = logging.getLogger('celery.task')
        logger.info('Starting a task for a thing with ID %i', my_id)
        my_cool_task.apply_async()

Теперь, согласно документам celery, это может войти в журнал, поскольку

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

Но логгер "celery.task" работает только внутри задачи. Поэтому в представлении этот лог уйдет в никуда.

Кроме того, я играл с установкой некоторой переменной логирования внутри settings.py, а затем переназначил логирование сельдерея. Я играл с CELERY_WORKER_HIJACK_ROOT_LOGGER, но даже когда я использую корневой логгер, журналы не появляются в консоли. Не помогает и использование getLogger("celery").

Это кажется простым делом, но я целый день пытаюсь это сделать, пожалуйста, помогите.

UPD: Я видел пост на reddit с той же проблемой, но там нет ответов

Итак, как следует из вопроса, взломать логгер сельдерея невозможно.

Однако есть несколько обходных путей:

  1. Создайте задачу для ведения журнала, например
from celery.utils.log import get_task_logger

@shared_task
def log_stuff(level, message, *args, **kwargs):
    get_task_logger().log(level, message, *args, **kwargs)

Однако это грязно по многим причинам: в основном потому, что ваш журнал будет выполнен, когда рабочий доберется до него, и это просто превратится в беспорядок.

  1. Зайдите в тот же файл. Зайдите в файл your_projects_name/settings.py, определите переменную LOGGING, например:
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False, 
    'formatters': {
        'simple': {
            'format': '[%(levelname)s] %(message)s',
        },
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {
            'level': 'INFO',
            # with rotating handlers you can configure max size and other stuff
            'class': 'logging.FileHandler',
            'formatter': 'simple',
            'filename': 'my_log.log',
        },
    # that's the most interesting part
    'loggers':
        'django': {
            'handlers': ['file', 'console'],
            'level': 'INFO',
        },
        'celery': {
            'handlers': ['file', 'console'],
            'level': 'INFO',
        },
}

Примечание: ваша конфигурация протоколирования должна быть более сложной.

Теперь никаких дополнительных действий не требуется, учитывая настройку django celery по умолчанию из документации, и что ваша версия django - 4.2.11, а celery - 5.3.6 - на более старых версиях вы можете захотеть поиграть с celery.signals.setup_logging.

2-ое замечание: потоки настроены для отдельных процессов django и celery: вы не увидите их все в одном месте

  1. Рассмотрите возможность использования таких инструментов, как logstash, sentry, graypy, new relic - они соберут все журналы в одном месте. Я не пробовал ни один из них, но это то, что также используется.

Наконец, конечно, это может работать с чем угодно, не обязательно только с django.

Вернуться на верх