Django 1.10、python 3.5 and celery 4.1.0を使用しています。セロリタスクの情報をファイルに記録しようとしています。セロリのドキュメント-
from celery.utils.log import get_task_logger
logger = get_task_logger(__name__)
タスク内のメッセージを記録しようとしました-
logger.info(message)
デフォルトのロガーにログを記録すると思っていました。しかし、そうではありませんでした。だから私は「セロリ。タスク」という名前の専用ロガーを設定に追加しました(ドキュメントから理解できるように):
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'Django.utils.log.RequireDebugFalse',
},
'require_debug_true': {
'()': 'Django.utils.log.RequireDebugTrue',
},
'require_test_false': {
'()': 'myapp.utils.classes.logging.RequireTestFalse',
},
'suppress_deprecated': {
'()': 'myapp.utils.classes.logging.SuppressDeprecated'
}
},
'handlers': {
'console': {
'level': 'INFO',
'class': 'logging.StreamHandler',
'formatter': 'json',
'filters': ['suppress_deprecated']
},
'celery_file': {
'level': 'INFO',
'class': 'myapp.utils.classes.logging.SBRotatingFileHandler',
'maxBytes': 1024 * 1024 * 200, # 200 MB
'backupCount': 10,
'formatter': 'json',
'filename': BASE_DIR + '/../log/celery.log',
}
},
'loggers': {
'Django': {
'handlers': ['console', 'file'],
'level': LOG_LEVEL,
'propagate': True,
},
'celery.task': {
'handlers': ['console', 'celery_file'],
'level': 'INFO',
'propagate': True,
},
}
しかし、celery.logファイルにもデフォルトのログファイルにもないセロリタスクのログはまだ表示されません。
セロリワーカーを '-f'で開始する場合のみ-そのファイルにログを書き込みます。
編集:私は 'after_setup_task_logger'を使用してcelery.taskロガーハンドラーを更新し、logging.config(設定内)に存在するハンドラーを使用しようとして失敗しました。私は以下を試しました:
@celery.signals.after_setup_task_logger.connect
def after_setup_logging(logger, **kwargs):
logging_settings = settings.LOGGING
celery_handler = logging_settings['handlers']['celery_file']
logger.addHandler(celery_handler)
しかし、それはうまくいきません。私は得ています
AttributeError: 'dict' object has no attribute 'createLock'
これは、ハンドラーが適切に作成されなかったことを意味します。そこで、「ログ」オブジェクトからハンドラを取得してみました。しかし、logging._handlersとlogging._handlersListの両方にハンドラーがありません。
更新:それが最終的に私のために働いたものです:
def create_celery_logger_handler(logger, propagate):
# 209715200 is 1024 * 1024 * 200 or 200 MB, same as in settings
celery_handler = RotatingFileHandler(
settings.CELERY_LOG_FILE,
maxBytes=209715200,
backupCount=10
)
celery_formatter = jsonlogger.JsonFormatter(settings.LOGGING['formatters']['json']['format'])
celery_handler.setFormatter(celery_formatter)
logger.addHandler(celery_handler)
logger.logLevel = settings.LOG_LEVEL
logger.propagate = propagate
@celery.signals.after_setup_task_logger.connect
def after_setup_celery_task_logger(logger, **kwargs):
""" This function sets the 'celery.task' logger handler and formatter """
create_celery_logger_handler(logger, True)
@celery.signals.after_setup_logger.connect
def after_setup_celery_logger(logger, **kwargs):
""" This function sets the 'celery' logger handler and formatter """
create_celery_logger_handler(logger, False)
価値があるのは、これがセロリを設定して私のDjangoロギング設定を使用する方法です。
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
from celery.signals import setup_logging
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('Django_SETTINGS_MODULE', 'app.settings')
app = Celery('app')
# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('Django.conf:settings', namespace='CELERY')
@setup_logging.connect
def config_loggers(*args, **kwags):
from logging.config import dictConfig
from Django.conf import settings
dictConfig(settings.LOGGING)
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()
それがそれだけでした-その変更後、私のDjango=ログ設定はセロリで機能しました。これには、ログメッセージをスラックに送信するように設定したログも含まれます。
デフォルトでは、セロリは リセットハンドラー on celery.task
ロガー、 worker_Hijack_root_logger
オプション 。または、このロガーを after_setup_task_logger シグナルで再構成することもできます。セロリに setup_logging シグナルでロガーを構成させないでください。
from celery.signals import setup_logging
@setup_logging.connect()
def config_loggers(*args, **kwargs):
from logging.config import dictConfig
dictConfig(app.config['LOGGING_CONFIG'])
私のログがルートロガーに伝播されなかった理由を理解しようとして今朝のログをいじっていました。@ georgexshが言ったように、シーリーはルートロガーをハイジャックしています。これが私のロガー設定です:
'loggers': {
'Django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
'cal': {
'handlers': ['general'],
'level': 'INFO',
'propagate': True,
},
'': {
'handlers': ['gelf'],
'level': 'INFO',
}
}
そしてCELERYD_Hijack_ROOT_LOGGER = False
設定で。
すべてのセロリログは、通常の場所ではなく、graylog(ルートで定義)に移動します。