def get_thread_tree(including_this=True):
from .logging import THREAD_LOGGING_CONTEXT
from .bunch import Bunch
tree = {}
dead_threads = set()
contexts = {}
stacks = {}
def add_to_tree(thread):
contexts[thread.ident] = THREAD_LOGGING_CONTEXT.flatten(thread.uuid)
parent = get_thread_parent(thread)
if isinstance(parent, DeadThread) and parent not in dead_threads:
dead_threads.add(parent)
add_to_tree(parent)
tree.setdefault(parent, []).append(thread)
for thread in threading.enumerate():
add_to_tree(thread)
current_ident = threading.current_thread().ident
main_ident = threading.main_thread().ident
for thread_ident, frame in iter_thread_frames():
if not including_this and thread_ident == current_ident:
formatted = " <this frame>"
else:
# show the entire stack if it's this thread, don't skip ('after_module') anything
show_all = thread_ident in (current_ident, main_ident)
formatted = format_thread_stack(frame, skip_modules=[] if show_all else _BOOTSTRAPPERS) if frame else ''
stacks[thread_ident] = formatted, time.time()
def add_thread(parent_thread, parent):
for thread in sorted(tree[parent_thread], key=lambda thread: thread.name):
ident = thread.ident or 0
stack, ts = stacks.get(ident, ("", 0))
context = contexts.get(ident, {})
context_line = ", ".join("%s: %s" % (k, context[k]) for k in "host context".split() if context.get(k))
this = Bunch(
name=thread.name,
daemon="[D]" if getattr(thread, "daemon", False) else "",
ident=ident,
context_line="({})".format(context_line) if context_line else "",
stack=stack,
timestamp=ts,
children=[],
)
parent.children.append(this)
if thread in tree:
add_thread(thread, this)
return parent
return add_thread(None, Bunch(children=[]))
评论列表
文章目录