芹菜记录器配置

Posted

技术标签:

【中文标题】芹菜记录器配置【英文标题】:Celery logger configuration 【发布时间】:2018-06-25 16:00:34 【问题描述】:

我正在使用 Django 1.10、python 3.5 和 celery 4.1.0 我正在尝试将芹菜任务信息记录到文件中。所以我按照 celery 文档中的建议进行了尝试-

from celery.utils.log import get_task_logger

logger = get_task_logger(__name__)

并尝试在任务中记录一条消息 -

logger.info(message)

我希望它记录到我的默认记录器。但它没有。所以我在设置中添加了一个名为“celery.task”的专用记录器(我从文档中了解到):

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 文件和默认日志文件中看到来自 celery 任务的日志。

仅当使用 '-f' 启动 celery worker 时 - 它会将日志写入该文件 有什么想法吗?

编辑: 我正在尝试使用 '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)

【问题讨论】:

最后我混合了一些建议 好!除了我能做些什么来改进我的答案以使其被接受? 【参考方案1】:

不管怎样,这就是我配置 celery 以使用我的 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 日志记录设置适用于 celery,包括我设置的用于将日志消息发送到 slack 的日志记录。

【讨论】:

【参考方案2】:

默认情况下,celery 会在 celery.task 记录器上使用 reset handers,您可以使用 worker_hijack_root_logger option 禁用此行为。或者,您可以在 after_setup_task_logger 信号中重新配置此记录器,甚至不要让 celery 使用 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'])

【讨论】:

根据您添加的链接 - 我应该使用“celery.signals.setup_logging”信号。问题是我找不到任何实际使用它并覆盖 Celery 的日志文件和格式化程序的示例。 @user2880391 为什么不设置worker_hijack_root_logger = False,这是一个更明智的解决方案IMO。 @user2880391 我添加了一个使用 setup_logging 信号的示例。 我不想重新加载日志配置。配置已经存在。我想将处理程序从日志配置('celery_file')设置为 celery.task 记录器。它不起作用。用我的试用更新问题。 @user2880391 logger.addHandler 需要一个处理程序对象作为参数,你不应该给它一个 dict,dict 用于 dictConfig api。首先实例化“myapp.utils.classes.logging.SBRotatingFileHandler”。【参考方案3】:

今天早上我正在摆弄我的日志记录,试图弄清楚为什么我的日志没有传播到根记录器,结果正如@georgexsh 所说,celey 正在劫持根记录器,这是我的工作记录器配置:

'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

所有 celery 日志现在都将转到 graylog(在 root 中定义)而不是通常的位置。

【讨论】:

以上是关于芹菜记录器配置的主要内容,如果未能解决你的问题,请参考以下文章

芹菜从 Django 模块内部记录到文件

如何记录 Django 芹菜任务中发生的异常

从芹菜任务中获取芹菜工人的名字?

芹菜登录 Django

什么可能会延迟我的芹菜任务?

为啥找不到我的芹菜配置文件?