def _describe(node, parent):
    name, logger, children = node
    is_placeholder = isinstance(logger, logging.PlaceHolder)
    if is_placeholder:
        yield '<--[%s]' % name
    else:
        parent_is_correct = (parent is None) or (logger.parent is parent)
        if not logger.propagate:
            arrow = '   '
        elif parent_is_correct:
            arrow = '<--'
        else:
            arrow = ' !-'
        yield '%s"%s"' % (arrow, name)
        if not parent_is_correct:
            if logger.parent is None:
                yield ('   Broken .parent is None, so messages stop here')
            else:
                yield ('   Broken .parent redirects messages to %r instead'
                       % (logger.parent.name,))
        if logger.level == logging.NOTSET:
            yield '   Level NOTSET so inherits level ' + logging.getLevelName(
                logger.getEffectiveLevel())
        else:
            yield '   Level ' + logging.getLevelName(logger.level)
        if not logger.propagate:
            yield '   Propagate OFF'
        if logger.disabled:
            yield '   Disabled'
        for f in getattr(logger, 'filters', ()):
            yield '   Filter %s' % describe_filter(f)
        for h in getattr(logger, 'handlers', ()):
            g = describe_handler(h)
            yield '   Handler %s' % next(g)
            for line in g:
                yield '   ' + line
    if children:
        if not is_placeholder:
            parent = logger
        last_child = children[-1]
        for child in children:
            g = _describe(child, parent)
            yield '   |'
            yield '   o' + next(g)
            if child is last_child:
                prefix = '    '
            else:
                prefix = '   |'
            for line in g:
                yield prefix + line