84 votes

Django Celery Logging Best Practice

Je vais essayer d'obtenir le Céleri journalisation de travail avec Django. J'ai journalisation set-up en settings.py aller à la console (qui fonctionne très bien comme je suis d'hébergement à Heroku). En haut de chaque module, j'ai:

import logging
logger = logging.getLogger(__name__)

Et dans mon tasks.py, j'ai:

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

Cela fonctionne bien pour la journalisation des appels à partir d'une tâche et j'ai sortie comme ceci:

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

Mais si cette tâche, puis appelle une méthode d'un autre module, par exemple un queryset méthode, je obtenir un double des entrées de journal, par exemple

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

Je pense que je pourrais utiliser

CELERY_HIJACK_ROOT_LOGGER = False

simplement utiliser l' Django de journalisation mais cela ne fonctionne pas quand je l'ai essayé et même si j'arrivais à le faire fonctionner, je perdrais l' "PoolWorker-6" peu qui je veux. (D'ailleurs, je ne peux pas comprendre comment obtenir le nom de la tâche à afficher dans le journal d'entrée de Céleri, que la documentation semble indiquer qu'elle devrait le faire http://docs.celeryproject.org/en/master/configuration.html?highlight=celeryd_task_log_format#std:setting-CELERYD_TASK_LOG_FORMAT).

Je pense que je suis absent quelque chose de simple ici... toute aide serait grandement appréciée.

86voto

Rustem Points 1008

Lorsque votre enregistreur est initialisé au début de "un autre module", il se connecte à un autre enregistreur. Qui gèrent vos messages. Il peut s’agir de l’enregistreur racine ou généralement, je vois dans les projets Django - enregistreur portant le nom ''.

Le meilleur moyen ici, est de surcharger votre configuration de journalisation,

 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)
 

Dans ce cas, je suppose que cela devrait fonctionner comme vous le supposez.

PS dictConfig ajouté dans Python2.7 +.

9voto

Lincoln B Points 1214

Il est troublant de constater que le Céleri interfère avec la racine de l'exploitant (qui n'est pas le plus pratique et ne peut pas être totalement contrôlé), mais il ne permet pas de désactiver votre application personnalisée de bûcherons en quelque sorte, afin d'utiliser votre propre gestionnaire de noms et de définir votre propre comportement, plutôt que d'essayer de résoudre ce problème avec le Céleri. [Je tiens à garder mes journalisation de l'application séparée de toute façon). Vous pourriez utiliser des gestionnaires ou même pour Django code et le Céleri tâches, vous avez juste besoin de les définir dans votre Django JOURNALISATION config. Ajouter une mise en forme des arguments pour le module, le nom de fichier, et processName à votre formateur pour la santé mentale, pour vous aider à distinguer où les messages sont originaires.

[cela suppose que vous avez de l'installation d'un gestionnaire pour 'yourapp" dans les paramètres d'enregistrement de la valeur à un Appender - on dirait que vous êtes conscient de ce que].

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

Pour l'enregistrement de Céleri génère - utiliser le celeryd drapeaux --logfile pour envoyer le Céleri sortie (par exemple, un travailleur de l'init, a commencé la tâche, la tâche a échoué) à un autre endroit si vous le souhaitez. Ou, utilisez l'autre réponse ici qui envoie le 'céleri' logger dans un fichier de votre choix.

Note: je ne voudrais pas utiliser RotatingFileHandlers - ils ne sont pas pris en charge pour des processus multiples applications. La rotation des journaux à partir d'un autre outil comme logrotate est plus sûr, en va de même avec la coupe de bois de Django en supposant que vous avez de multiples processus, ou même les fichiers journaux sont partagés avec le céleri travailleurs. Si votre utilisation d'un multi-solution de serveur, vous voudrez probablement de se connecter quelque part de toute façon centralisée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X