How to monitor events from workers in a Celery-Django application?

前端 未结 2 1419
悲哀的现实
悲哀的现实 2020-12-28 19:54

According to the celery tutorial regarding real-time monitoring of celery workers, one can also programmatically capture the events produced by the workers and take action a

相关标签:
2条回答
  • 2020-12-28 20:07

    Beware of a couple of gotchas

    1. You need to set CELERY_SEND_EVENTS flag as true in your celery config.
    2. You can also set the event monitor in a new thread from your worker.

    Here is my implementation:

    class MonitorThread(object):
        def __init__(self, celery_app, interval=1):
            self.celery_app = celery_app
            self.interval = interval
    
            self.state = self.celery_app.events.State()
    
            self.thread = threading.Thread(target=self.run, args=())
            self.thread.daemon = True
            self.thread.start()
    
        def catchall(self, event):
            if event['type'] != 'worker-heartbeat':
                self.state.event(event)
    
            # logic here
    
        def run(self):
            while True:
                try:
                    with self.celery_app.connection() as connection:
                        recv = self.celery_app.events.Receiver(connection, handlers={
                            '*': self.catchall
                        })
                        recv.capture(limit=None, timeout=None, wakeup=True)
    
                except (KeyboardInterrupt, SystemExit):
                    raise
    
                except Exception:
                    # unable to capture
                    pass
    
                time.sleep(self.interval)
    
    if __name__ == '__main__':
        app = get_celery_app() # returns app
        MonitorThread(app)
        app.start()
    
    0 讨论(0)
  • 2020-12-28 20:09

    Ok, I found a way of doing this, though I am not sure that this is the solution, but it works for me. The monitor function basically connects directly to the broker and listens to different types of events. My code looks like this:

    from celery.events import EventReceiver
    from kombu import Connection as BrokerConnection
    
    def my_monitor:
        connection = BrokerConnection('amqp://guest:guest@localhost:5672//')
    
        def on_event(event):
            print "EVENT HAPPENED: ", event
    
        def on_task_failed(event):
            exception = event['exception']
            print "TASK FAILED!", event, " EXCEPTION: ", exception
    
        while True:
            try:
                with connection as conn:
                    recv = EventReceiver(conn,
                                     handlers={'task-failed' : on_task_failed,
                                               'task-succeeded' : on_event,
                                               'task-sent' : on_event,
                                               'task-received' : on_event,
                                               'task-revoked' : on_event,
                                               'task-started' : on_event,
                                               # OR: '*' : on_event
                                               })
                recv.capture(limit=None, timeout=None)
        except (KeyboardInterrupt, SystemExit):
            print "EXCEPTION KEYBOARD INTERRUPT"
            sys.exit()
    

    This is all. And I run this in a different process than the normal application, meaning that I create a child process of my celery application which only runs this function. HTH

    0 讨论(0)
提交回复
热议问题