2013-05-20 2 views
16

Я настроил сельдерей работать с моим Джанго приложением, используя свои инструкции daemonization (http://docs.celeryproject.org/en/latest/tutorials/daemonizing.html#daemonizing)Как войти исключения, возникающие в задаче Джанго сельдерея

Вот моего тестового задание

@periodic_task(run_every=timedelta(seconds=10)) 
def debugger(): 
    logger.info("Running debugger") 
    raise Exception('Failed') 

Мне нужна способ узнать, что эта задача (отладчик) не удалась из-за исключения. Журнал регистрации сельдерей печатает журнал logger.info («работает отладчик»), но он не регистрирует исключение. Я что-то упускаю, или я должен найти неудачные задачи каким-то другим способом?

+1

Что хотят от сельдерея? Я не мог сбой, как настольное приложение. Вы можете использовать два простых способа. 1. Используйте бэкэнда результата и отметьте задачу как падающую. 2. Заверните весь свой код в сельдерее, чтобы попытаться исключить. – Rustem

+3

@Rustem Я бы хотел, чтобы сельдерей поймал исключения и записал их в файл журнала, вместо того, чтобы, по-видимому, проглотить их ... –

ответ

1

Используйте модуль трассировки, чтобы захватить трассировку в виде строки и отправить ее в регистратор.

try: 
    ... 
except: 
    import traceback 
    logger.info(traceback.format_exc()) 
+3

fwif, python logger может включать трассировку на любом уровне. все, что вам нужно сделать, это добавить exc_info = 1 в вызов. например logger.info («что-то не удалось b/c другой вещи», exc_info = 1) – user2399268

6

Вы можете посмотреть на Celery User Guide:

from celery.utils.log import get_task_logger 

logger = get_task_logger(__name__) 

@app.task 
def div(): 
    try: 
     1/0 
    except ZeroDivisionError: 
     logger.exception("Task error") 

Из документации python logging module:

Logger.exception (МСГ, * арг)

Записывает сообщение с уровнем ERROR на этом регистраторе. Аргументы интерпретируются как для debug(). Информация об исключении добавляется в сообщение регистрации. Этот метод следует вызывать только из обработчика исключений.

+1

Подождите, я ожидаю, что в рабочем журнале будет что-то зарегистрированное, по крайней мере, для каждой задачи, которая не работает ... –

3

Вопрос:

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

В настоящее время верхняя ответ здесь так для целей профессионального решения. Многие разработчики python будут рассматривать скрытую ошибку при каждом случае на красном флаге. Разумное отвращение к этому было хорошо сформулировано в комментарии:

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

Сельдерей действительно ломает исключение, он просто не делает то, что OP хочет от него сделать (он хранит его в исходном файле результата). Следующий пример - лучший интернет, который может предложить по этой проблеме. Это немного датировано, но обратите внимание на количество вилок и звезд.

https://gist.github.com/darklow/c70a8d1147f05be877c3

Суть принимает случай отказа и делать что-то обычай с ним. Это надмножество проблемы OP. Вот как настроить решение в gist для регистрации исключения.

import logging 

logger = logging.getLogger('your.desired.logger') 


class LogErrorsTask(Task): 
    def on_failure(self, exc, task_id, args, kwargs, einfo): 
     logger.exception('Celery task failure!!!1', exc_info=exc) 
     super(LogErrorsTask, self).on_failure(exc, task_id, args, kwargs, einfo) 

Вы все равно должны убедиться, что все ваши задачи наследуют от этого класса задач, а суть показывает, как это сделать, если вы используете @task декоратор (с base=LogErrorsTask kwarg).

Преимущество этого решения состоит в том, чтобы не встраивать ваш код в какие-либо дополнительные контексты, отличные от try. Это согласуется с кодом кода отказа, который сельдерей уже использует.

0

Вы также можете переопределить сельдерея приложение, чтобы избежать добавления base kwarg к каждому @app.task декоратора:

import logging 
from celery import Celery, Task 

logger = logging.getLogger(__name__) 

class LoggingTask(Task): 
    def on_failure(self, exc, task_id, args, kwargs, einfo): 
     logger.exception('Task failed: %s' % exc, exc_info=exc) 
     super(LoggingTask, self).on_failure(exc, task_id, args, kwargs, einfo) 

class LoggingCelery(Celery): 
    def task(self, *args, **kwargs): 
     kwargs.setdefault('base', LoggingTask) 
     return super(LoggingCelery, self).task(*args, **kwargs) 

app = LoggingCelery(__name__)