带日志的芹菜

Celery with Logbook

我正在努力组装一个系统,该系统通过 RabbitMQ 进行日志记录(并最终写入数据库)。我发现 Logbook 库有一个 MessageQueueHandler(和 RabbitMQHandler),它将 python 写入消息队列。这似乎很好用。但是,当我尝试使用具有相关任务的 Celery 工作人员来消化这些消息时,我收到了未知消息警告,然后它在不阅读的情况下删除了该消息:

[2015-06-16 15:59:06,688: WARNING/MainProcess] Received and deleted unknown message. Wrong destination?!?

邮件正文的完整内容为:

body: {u'thread_name': u'MainThread', u'extra': {}, u'process': 11784, u'module': u'__main__', u'heavy_init
ialized': True, u'information_pulled': True, u'exception_message': None, u'message': u'test', u'exception_name': None, u'frame_correction': 0, u'filen
ame': u'<input>', u'lineno': 2, u'kwargs': {}, u'msg': u'test', u'channel': u'__main__', u'args': [], u'func_name': u'<module>', u'process_name': u'Ma
inProcess', u'formatted_exception': None, u'thread': 12904, u'level': 2, u'greenlet': 12904, u'time': u'2015-06-16T15:59:06.989000Z'} (502b)
{content_type:u'application/json' content_encoding:u'utf-8'
  delivery_info:{'consumer_tag': u'5', 'redelivered': False, 'routing_key': u'logging', 'delivery_tag': 1, 'exchange': u'logging'} headers={}}

我认为发生这种情况的原因有两个。一是消息中的json不是Python格式,所以里面有Null(而不是None)和true(而不是True)之类的值。我认为这可能失败的第二个原因是因为消息是通过 Logbook 而不是通过 Celery 任务(将与工作人员关联)发送到交换器(并路由到队列)。

有没有办法结合这两种技术,使 Logbook MessageQueueHandler 可以写入消息队列,而 Celery worker 可以从该队列中读取?

编辑添加: 这是 celery worker 用来从日志队列中获取消息的 tasks.py 函数,该日志队列是从 Logbook 的 RabbitMQHandler class:

填充的
@shared_task
def digest_logs(logging_queue_data):
    for k,v in logging_queue_data.iteritems():
        print k, v
    completion_indicator = 'Complete'
    return completion_indicator

对运行工人的celery命令如下:

celery -A proj.tasks worker --loglevel=debug -Q logging

您已将 celery 配置为侦听日志消息发送到的队列。 Celery 希望它们是其内部格式的任务消息(即指定任务 运行)。

解决方案是为 celery 和 logbook 设置单独的队列。我建议使用 celery 的默认队列——即像这样启动 worker:

celery -A proj.tasks worker -Q celery

然后你的 celery 任务将不得不从 logging 队列中读取 - 在你需要使用可用库之一的任务中(librabbitmqamqppuka...) 从 logging 队列中读取日志消息。

为此,我最终使用 Kombu 而不是 Celery 编写了一个 worker,因为有了 Kombu 库,编写消息的代码也不必是侦听消息的代码(换句话说,你不需要'必须在消息队列的两侧具有相同的代码)。所以最后并没有真正使用 Celery 的好方法。