codekingpro/portable-devtools
115k
1import asyncio2import gc3import linecache4import os5import platform6import signal7import sys8import threading9import traceback10from collections import Counter11from contextlib import redirect_stdout12 13from OpenSSL import SSL14 15from mitmproxy import version16from mitmproxy.utils import asyncio_utils17 18 19def dump_system_info():20 mitmproxy_version = version.get_dev_version()21 openssl_version: str | bytes = SSL.SSLeay_version(SSL.SSLEAY_VERSION)22 if isinstance(openssl_version, bytes):23 openssl_version = openssl_version.decode()24 25 data = [26 f"Mitmproxy: {mitmproxy_version}",27 f"Python: {platform.python_version()}",28 f"OpenSSL: {openssl_version}",29 f"Platform: {platform.platform()}",30 ]31 return "\n".join(data)32 33 34def dump_info(signal=None, frame=None, file=sys.stdout): # pragma: no cover35 with redirect_stdout(file):36 print("****************************************************")37 print("Summary")38 print("=======")39 40 try:41 import psutil42 except ModuleNotFoundError:43 print("(psutil not installed, skipping some debug info)")44 else:45 p = psutil.Process()46 print("num threads: ", p.num_threads())47 if hasattr(p, "num_fds"):48 print("num fds: ", p.num_fds())49 print("memory: ", p.memory_info())50 51 print()52 print("Files")53 print("=====")54 for i in p.open_files():55 print(i)56 57 print()58 print("Connections")59 print("===========")60 for i in p.connections():61 print(i)62 63 print()64 print("Threads")65 print("=======")66 bthreads = []67 for i in threading.enumerate():68 if hasattr(i, "_threadinfo"):69 bthreads.append(i)70 else:71 print(i.name)72 bthreads.sort(key=lambda x: getattr(x, "_thread_started", 0))73 for i in bthreads:74 print(i._threadinfo())75 76 print()77 print("Memory")78 print("======")79 gc.collect()80 objs = Counter(str(type(i)) for i in gc.get_objects())81 82 for cls, count in objs.most_common(20):83 print(f"{count} {cls}")84 85 print()86 print("Memory (mitmproxy only)")87 print("=======================")88 mitm_objs = Counter({k: v for k, v in objs.items() if "mitmproxy" in k})89 for cls, count in mitm_objs.most_common(20):90 print(f"{count} {cls}")91 92 try:93 asyncio.get_running_loop()94 except RuntimeError:95 pass96 else:97 print()98 print("Tasks")99 print("=======")100 for task in asyncio.all_tasks():101 f = task.get_stack(limit=1)[0]102 line = linecache.getline(103 f.f_code.co_filename, f.f_lineno, f.f_globals104 ).strip()105 line = f"{line} # at {os.path.basename(f.f_code.co_filename)}:{f.f_lineno}"106 print(f"{asyncio_utils.task_repr(task)}\n {line}")107 108 print("****************************************************")109 110 if os.getenv("MITMPROXY_DEBUG_EXIT"): # pragma: no cover111 sys.exit(1)112 113 114def dump_stacks(signal=None, frame=None, file=sys.stdout):115 id2name = {th.ident: th.name for th in threading.enumerate()}116 code = []117 for threadId, stack in sys._current_frames().items():118 code.append("\n# Thread: %s(%d)" % (id2name.get(threadId, ""), threadId))119 for filename, lineno, name, line in traceback.extract_stack(stack):120 code.append('File: "%s", line %d, in %s' % (filename, lineno, name))121 if line:122 code.append(" %s" % (line.strip()))123 print("\n".join(code), file=file)124 if os.getenv("MITMPROXY_DEBUG_EXIT"): # pragma: no cover125 sys.exit(1)126 127 128def register_info_dumpers():129 if os.name != "nt": # pragma: windows no cover130 signal.signal(signal.SIGUSR1, dump_info) # type: ignore131 signal.signal(signal.SIGUSR2, dump_stacks) # type: ignore132 