Search code examples
pythontornado

is it possible to list all blocked tornado coroutines


I have a "gateway" app written in tornado using @tornado.gen.coroutine to transfer information from one handler to another. I'm trying to do some debugging/status testing. What I'd like to be able to do is enumerate all of the currently blocked/waiting coroutines that are live at a given moment. Is this information accessible somewhere in tornado?


Solution

  • No there isn't, but you could perhaps create your own decorator that wraps gen.coroutine, then updates a data structure when the coroutine begins.

    import weakref
    import functools
    
    from tornado import gen
    from tornado.ioloop import IOLoop
    
    all_coroutines = weakref.WeakKeyDictionary()
    
    
    def tracked_coroutine(fn):
        coro = gen.coroutine(fn)
    
        @functools.wraps(coro)
        def start(*args, **kwargs):
            future = coro(*args, **kwargs)
            all_coroutines[future] = str(fn)
            return future
    
        return start
    
    
    @tracked_coroutine
    def five_second_coroutine():
        yield gen.sleep(5)
    
    
    @tracked_coroutine
    def ten_second_coroutine():
        yield gen.sleep(10)
    
    
    @gen.coroutine
    def tracker():
        while True:
            running = list(all_coroutines.values()) 
            print(running)
            yield gen.sleep(1)
    
    
    loop = IOLoop.current()
    loop.spawn_callback(tracker)
    loop.spawn_callback(five_second_coroutine)
    loop.spawn_callback(ten_second_coroutine)
    loop.start()
    

    If you run this script for a few seconds you'll see two active coroutines, then one, then none.

    Note the warning in the docs about the dictionary changing size, you should catch "RuntimeError" in "tracker" to deal with that problem.

    This is a bit complex, you might get all you need much more simply by turning on Tornado's logging and using set_blocking_log_threshold.