Pregunta Cómo registrar excepciones que ocurren en una tarea de apio Django


Configuré apio para trabajar con mi aplicación django usando sus instrucciones de demonización (http://docs.celeryproject.org/en/latest/tutorials/daemonizing.html#daemonizing)

Aquí está mi tarea de prueba

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

Necesito una forma de saber que esta tarea (depurador) falló debido a la excepción. El archivo de registro de Aplery imprime el registro logger.info ("depurador en ejecución"), pero no registra la excepción. ¿Me estoy perdiendo algo, o se supone que debo encontrar las tareas fallidas de alguna otra manera?


18
2018-05-20 21:01


origen


Respuestas:


Puedes mirar Apio Guía del usuario:

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

De la documentación para módulo de registro de python:

Logger.exception (msg, * args)

Registra un mensaje con nivel ERROR en este registrador. Los argumentos se interpretan como para debug (). La información de excepción se agrega al mensaje de registro. Este método solo debe invocarse desde un manejador de excepciones.


6
2018-02-24 15:46



La pregunta:

Me gustaría que Aplery capture excepciones y las escriba en un archivo de registro en lugar de aparentemente tragárselas ...

La respuesta actual actual aquí es regular para propósitos de una solución profesional. Muchos desarrolladores de Python considerarán el error general capturando, caso por caso, una bandera roja. Una razonable aversión a esto estaba bien articulada en un comentario:

Espera, espero que haya algo registrado en el registro de trabajadores, como mínimo, por cada tarea que falla ...

Apio atrapa la excepción, simplemente no está haciendo lo que el OP quería que hiciera con él (lo almacena en el backend de resultados). La siguiente idea es lo mejor que Internet tiene para ofrecer sobre este problema. Está un poco anticuado, pero tenga en cuenta el número de horquillas y estrellas.

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

Lo esencial es tomar el caso de falla y hacer algo personalizado con él. Este es un superconjunto del problema del OP. A continuación se explica cómo ajustar la solución en la esencia para registrar la excepción.

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)

Aún deberá asegurarse de que todas sus tareas hereden de esta clase de tareas, y la esencia muestra cómo hacerlo si está utilizando el @task decorador (con el base=LogErrorsTask kwarg).

El beneficio de esta solución es no anidar su código en ningún contexto adicional de prueba-excepto. Esto está a cuestas en la ruta del código de falla que el apio ya está usando.


6
2017-07-26 17:01



Use el módulo de rastreo para capturar el rastreo como una cadena y enviarlo al registrador.

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

1
2018-06-25 19:39



También puede anular la aplicación de apio, para evitar agregar base kwarg a cada @app.task decorador:

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

0
2018-01-19 11:04