使用celery事件传输python日志记录

时间:2014-05-23 09:31:56

标签: python logging celery

我们使用celery作为一种自制的map-reduce工具,我们在多个worker上并行运行作业并等待结果。我们使用celery事件将worker上的python日志消息传送回客户端。我知道我们可以使用像sentry这样的日志聚合工具,但对我们来说这些日志消息会返回给客户端非常重要。问题是,如何在没有线程的情况下在客户端上注册芹菜事件监听器?另外,这是我们完全错了吗?它适用于我们,但也许有更好的方法。

我在github中创建了一个工作示例:

https://github.com/gijzelaerr/celerylog

以下是我们正在做的一个小小的解释。

在工人身上我们运行:

class TaskLogEmitter(logging.Handler):
    def __init__(self, celery_app, level=logging.NOTSET):
        self.celery_app = celery_app
        super(TaskLogEmitter, self).__init__(level=level)

    def emit(self, record):
        with self.celery_app.events.default_dispatcher() as d:
            d.send('task-log', msg=record.getMessage(), levelno=record.levelno,
                   pathname=record.pathname, lineno=record.lineno,
                   name=record.name,  exc_info=record.exc_info)

@after_setup_logger.connect
@after_setup_task_logger.connect
def setup_task_log_emitter(logger=None, **kwargs):
    """
    setup log handler
    """
    handler = TaskLogEmitter(celery_app)
    logger.addHandler(handler)

这将注册一个python日志处理程序并为每个日志记录发出一个celery事件。在客户端,我们有一个偶数监控功能:

def monitor_events(celery_app):
    def on_event(event):
        logger = logging.getLogger(event['name'])
        logger.log(event['levelno'],event.msg)

    with celery_app.connection() as conn:
        recv = celery_app.events.Receiver(conn, handlers={'task-log':
on_event})
        recv.capture(limit=None, timeout=None, wakeup=True)

我们从一个线程开始,否则它阻止:

def setup_event_listening(celery_app):
    thread = threading.Thread(target=monitor_events, args=[celery_app])
    thread.daemon = True
    thread.start()

0 个答案:

没有答案