3

我们已将 django 配置为在触发任何错误或以上错误时向我们发送电子邮件。这是使用Django 中的标准 LOGGING配置完成的。我希望芹菜有同样的行为。我可以向我发送有关异常 ( [CELERY_SEND_TASK_ERROR_EMAILS][2]) 的电子邮件,但我想要任何已定义级别的电子邮件 - 巧合的是错误及以上。

例如,在任何 django 文件中,我们都可以这样做。

log = logging.getLogger(__name__)
log.error("Oh No!")

瞧,假设在设置中设置了以下内容,它将向我们发送一封电子邮件。

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'standard': {
            'format': "[%(asctime)s] %(levelname)s [%(name)s.%(funcName)s:%(lineno)d] %(message)s",
            'datefmt': "%d/%b/%Y %H:%M:%S"
        },
    },
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
            'include_html': True,
        },
    },
    'loggers': {
        '': {
            'handlers': ['logfile', 'mail_admins'],
            'level': os.environ.get('DEBUG_LEVEL', 'ERROR'),
        },
    }
}

为了清楚起见,我这样称呼芹菜。

../bin/python manage.py celeryd --settings=DJANGO_SETTINGS_MODULE \
    --broker=amqp://RABBITMQ_USER:RABBITMQ_PASSWORD@localhost:5672/axis \
    --beat --events --pidfile=/home/var/celeryd.pid \
    --logfile=/home/logs/celeryd.log \
    --loglevel=WARNING > /dev/null 2>&1

以及必要的芹菜相关设置。

CELERY_SEND_EVENTS = True
CELERY_TRACK_STARTED = True
CELERYD_CONCURRENCY = 2
CELERYD_TASK_TIME_LIMIT = 60 * 60 * 2    # Kill anything longer than 2 hours
CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 2
CELERYBEAT_SCHEDULER = "djcelery.schedulers.DatabaseScheduler"
CELERY_SEND_TASK_ERROR_EMAILS = True
CELERY_MAX_PREPARING = 600 

最后是一个基本的测试用例,我觉得应该发送两封电子邮件。一个用于错误,另一个用于异常..

from django.contrib.auth.models import User

import celery
from celery.schedules import crontab
from celery.utils.serialization import UnpickleableExceptionWrapper
from celery.utils.log import get_task_logger

log = get_task_logger(__name__)

@periodic_task(run_every=datetime.timedelta(minutes=5))
def noise_test(**kwargs):
    log.info("Info NOISE TEST")
    log.warning("Warning NOISE TEST")
    log.error("Error NOISE TEST")

    try:
        User.objects.get(id=9999999)
    except Exception as err:
        from celery import current_app
        err.args = list(err.args) + ["Crap"]
        raise UnpickleableExceptionWrapper(
            err.__class__.__module__, err.__class__.__name__, err.args)
4

1 回答 1

2

我正在寻找改进这一点并获得更深层次的理解(@asksol)的方法,但这就是我想出的。

这个片段可以放在任何*.tasks.py文件夹中,因为它是全局的并且会被拾取。

from celery.signals import after_setup_task_logger
def setup_logging(**kwargs):
    """
      Handler names is a list of handlers from your settings.py you want to 
      attach to this
    """

    handler_names = ['mail_admins']

    import logging.config
    from django.conf import settings
    logging.config.dictConfig(settings.LOGGING)

    logger = kwargs.get('logger')

    handlers = [x for x in logging.root.handlers if x.name in handler_names]
    for handler in handlers:
        logger.addHandler(handler)
        logger.setLevel(handler.level)
        logger.propagate = False

after_setup_task_logger.connect(setup_logging)

让电子邮件流动!!

夫妻注意事项:

  • mail_admins对应于绑定settings.LOGGING.handlers了魔法类的 。django.utils.log.AdminEmailHandler
  • 确保您禁用DEBUG电子邮件不会飞如果DEBUG = True
  • 确保您设置CELERY_SEND_TASK_ERROR_EMAILS = not DEBUG
  • 确保您的调用者将日志记录级别设置为 <= 您要捕获的级别。
  • 真正酷的是,在上面的示例中,您想要准确记录异常执行此操作。

尝试这个..

@celery.task()
def dummy_test(**kwargs):

    log = dummy_test.get_logger()
    if settings.DEBUG:
        log.setLevel(logging.DEBUG)

    log.debug("Debug DUMMY TEST")
    log.info("Info DUMMY TEST")
    log.warning("Warning DUMMY TEST")
    log.error("Error DUMMY TEST")
    log.critical("Critical DUMMY TEST")

    try:
        User.objects.get(id=9999999)
    except Exception as err:
        log.exception(err)
        raise

现在异常将通过一封漂亮的电子邮件发送。并且每条消息都会被打印出来..

于 2013-09-13T18:18:16.883 回答