2013-05-20 9 views
16

mam skonfigurowane seler pracować z mojej aplikacji django przy użyciu instrukcje daemonization (http://docs.celeryproject.org/en/latest/tutorials/daemonizing.html#daemonizing)Jak wyjątki występujące w zadaniu Django selera

Oto moje zadanie badanie

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

muszę log sposób poznania, że ​​to zadanie (debugger) nie powiodło się z powodu wyjątku. Plik logowania Selera wypisuje dziennik logger.info ("running debugger"), ale nie rejestruje wyjątku. Czy czegoś brakuje, czy też powinienem znaleźć jakieś nieudane zadania w inny sposób?

+1

Czego chcesz od Seler? Nie mogłem się zawiesić jak aplikacja na komputer. Możesz użyć dwóch prostych sposobów. 1. Użyj funkcji backendu i zaznacz zadanie jako falled. 2. Owiń cały kod w selera, aby wypróbować wyjątek. – Rustem

+3

@Rustem Chciałbym, aby Seler wychwycił wyjątki i zapisał je w pliku dziennika zamiast pozornie połknąć je ... –

Odpowiedz

1

Użyj modułu traceback, aby przechwycić ślad jako ciąg i wysłać go do programu rejestrującego.

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

fwif, logarytm python może zawierać ślad z powrotem na dowolnym poziomie. wszystko, co musisz zrobić, to dodać exc_info = 1 do połączenia. na przykład logger.info ("coś nie powiodło się b/c innej rzeczy", exc_info = 1) – user2399268

6

Możesz zajrzeć 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") 

z dokumentacji dla python logging module:

Logger.exception (MSG, * args)

Loguje komunikat z poziomem ERROR na tym loggerze. Argumenty są interpretowane jak dla debug(). Informacje o wyjątku są dodawane do komunikatu rejestrowania. Ta metoda powinna być wywoływana tylko z procedury obsługi wyjątku.

+1

Trzymaj się, spodziewałbym się, że coś będzie zalogowane w dzienniku robota, przynajmniej dla każdego zadania, które się nie powiedzie ... –

3

Pytanie:

Chciałbym Seler złapać wyjątki i zapisać je w pliku dziennika zamiast widocznie ich połykania ...

Aktualnym top Odpowiedź tutaj jest tak dla celów profesjonalnego rozwiązania. Wielu deweloperów pythonów będzie uważało błąd zbiorczy za uchybiając na podstawie przypadku czerwoną flagę. Rozsądnym awersja do tego było dobrze sformułowana w komentarzu:

Hang On, będę oczekiwać tam być coś rejestrowane w dzienniku pracowników, przynajmniej dla każdego zadania, która nie ...

Seler łapie wyjątek, po prostu nie robi tego, co OP chciał z nim zrobić (przechowuje go w backend wyniku). Poniższy punkt widzenia jest najlepszy, jaki internet ma do zaoferowania w tym problemie. Jest trochę przestarzały, ale zanotuj liczbę widelców i gwiazd.

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

Istotą bierze przypadek awarii i robi coś niestandardowego z nim. To jest nadzbiór problemu OP. Oto, jak dostosować rozwiązanie w celu zarejestrowania wyjątku.

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) 

trzeba jeszcze, aby sprawdzić, czy wszystkie zadania dziedziczą z tej klasy zadań, a sedno pokazuje, jak to zrobić, jeśli używasz @task dekorator (z base=LogErrorsTask kwarg).

Zaletą tego rozwiązania jest nie zagnieżdżanie kodu w dodatkowych kontekstach try-except. To jest niedozwolone na ścieżce kodu błędu, której już używa seler.

0

Można również zastąpić seler aplikację, aby uniknąć dodawania base kwarg każdemu @app.task dekoratora:

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__)