tutorial tasks run how python django logging celery django-celery

tasks - python celery crontab



Mejores prácticas de Django Apio Logging (3)

Intento que el registro de Aplery funcione con Django . Tengo la configuración de inicio de sesión en settings.py para ir a la consola (eso funciona bien ya que estoy alojando en Heroku ). En la parte superior de cada módulo, tengo:

import logging logger = logging.getLogger(__name__)

Y en my tasks.py, tengo:

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

Eso funciona bien para registrar llamadas desde una tarea y obtengo un resultado como este:

2012-11-13T18:05:38+00:00 app[worker.1]: [2012-11-13 18:05:38,527: INFO/PoolWorker-2] Syc feed is starting

Pero si esa tarea llama a un método en otro módulo, por ejemplo, un método queryset , obtengo entradas de registro duplicadas, por ejemplo

2012-11-13T18:00:51+00:00 app[worker.1]: [INFO] utils.generic_importers.ftp_processor process(): File xxx.csv already imported. Not downloaded 2012-11-13T18:00:51+00:00 app[worker.1]: [2012-11-13 18:00:51,736: INFO/PoolWorker-6] File xxx.csv already imported. Not downloaded

Creo que podría usar

CELERY_HIJACK_ROOT_LOGGER = False

simplemente usar el registro de Django pero esto no funcionó cuando lo probé e incluso si lo hiciera funcionar, perdería el "PoolWorker-6" que quiero. (Por cierto, no puedo encontrar la forma de mostrar el nombre de la tarea en la entrada del registro de Apio, ya que los documentos parecen indicar que debería).

Sospecho que me estoy perdiendo algo simple aquí.


Cuando su registrador se inicializó al comienzo de "otro módulo", lo vincula a otro registrador. Que manejan tus mensajes Puede ser un registrador de raíz, o generalmente lo veo en los proyectos de Django - registrador con nombre '''' .

La mejor manera aquí, es anular tu configuración de registro:

LOGGING = { ''version'': 1, ''disable_existing_loggers'': True, ''formatters'': { ''simple'': { ''format'': ''%(levelname)s %(message)s'', ''datefmt'': ''%y %b %d, %H:%M:%S'', }, }, ''handlers'': { ''console'': { ''level'': ''DEBUG'', ''class'': ''logging.StreamHandler'', ''formatter'': ''simple'' }, ''celery'': { ''level'': ''DEBUG'', ''class'': ''logging.handlers.RotatingFileHandler'', ''filename'': ''celery.log'', ''formatter'': ''simple'', ''maxBytes'': 1024 * 1024 * 100, # 100 mb }, }, ''loggers'': { ''celery'': { ''handlers'': [''celery'', ''console''], ''level'': ''DEBUG'', }, } } from logging.config import dictConfig dictConfig(LOGGING)

En este caso, supongo que debería funcionar como usted supone.

PS dictConfig agregado en Python2.7 +.


Es preocupante que Celery interfiera con el registrador de raíz (que no es la mejor práctica y no se puede controlar por completo), pero no deshabilita los registradores personalizados de su aplicación de ninguna manera, así que use sus propios nombres de manejador y defina su propio comportamiento en vez que tratar de solucionar este problema con Apio. [Me gusta mantener el registro de mi aplicación separado de todos modos]. Puede usar manejadores separados o lo mismo para el código Django y las tareas de Apio, solo necesita definirlos en su configuración de Django LOGGING. Agregue args de formato para módulo, nombre de archivo y nombre de proceso a su formateador para la cordura, para ayudarlo a distinguir dónde se originan los mensajes.

[esto supone que ha configurado un controlador para ''yourapp'' en el valor de la configuración de LOGGING que apunta a un Appender - aunque parece que ya sabe esto].

views.py

log = logging.getLogger(''yourapp'') def view_fun(): log.info(''about to call a task'') yourtask.delay()

tasks.py

log = logging.getLogger(''yourapp'') @task def yourtask(): log.info(''doing task'')

Para el registro que genera Apio, use las banderas de apio --log archivo para enviar la salida de apio (por ejemplo, inicio de trabajador, tarea iniciada, tarea fallida) a un lugar separado si así lo desea. O use la otra respuesta aquí que envía el registrador de "apio" a un archivo de su elección.

Nota: No usaría RotatingFileHandlers: no son compatibles con aplicaciones multiproceso. La rotación de registros desde otra herramienta como logrotate es más segura, lo mismo ocurre con el registro desde Django, suponiendo que tiene múltiples procesos allí, o los mismos archivos de registro se comparten con los trabajadores de apio. Si usa una solución de varios servidores, probablemente quiera iniciar sesión en algún lugar centralizado de todos modos.


Para solucionar el problema de registro duplicado, lo que funcionó para mí es establecer la configuración de propagar en falso al declarar mi configuración. DIGA DE OTOÑO

LOGGING = { ''version'': 1, ''disable_existing_loggers'': False, ''handlers'': { ''console'': { ''level'': ''DEBUG'', ''class'': ''logging.StreamHandler'', ''formatter'': ''verbose'' }, }, ''formatters'': { ''verbose'': { ''format'': ''%(asctime)s %(levelname)s module=%(module)s, '' ''process_id=%(process)d, %(message)s'' } }, ''loggers'': { ''my_app1'': { ''handlers'': [''console''], ''level'': ''DEBUG'', ''propagate'': False #this will do the trick }, ''celery'': { ''handlers'': [''console''], ''level'': ''DEBUG'', ''propagate'': True }, } }

digamos que el diseño de tu proyecto django se ve así:
mi proyecto/
- tasks.py
- email.py

y digamos que una de sus tareas hace una llamada a alguna función en email.py; el registro ocurrirá en email.py y luego ese registro se propagará al ''padre'', que en este caso pasa a ser su tarea de apio. Por lo tanto, doble registro. Pero al establecer propagar en False para un registrador en particular significa que para ese registrador / aplicación, sus registros no se propagarán al padre, por lo tanto, no habrá un registro "doble". Por defecto, ''propagar'' se establece en True

Aquí hay un enlace a la sección django docs sobre cosas de padres / hijos madereros