Skip to content

Instantly share code, notes, and snippets.

@iambibhas
Last active August 16, 2020 13:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iambibhas/e0ee436d307b257087d2b79f04212b43 to your computer and use it in GitHub Desktop.
Save iambibhas/e0ee436d307b257087d2b79f04212b43 to your computer and use it in GitHub Desktop.
Takes a profile file, a method name and depth, and shows you the chain of callers of the method
import pstats
import re
import sys
from io import StringIO
"""
E.g.
python pstats-chain.py GET.foobar.com.testurl.46689ms.1597427246.prof 'time.sleep' 10
"""
pattern = re.compile(r"\/.*")
prof_file = sys.argv[1]
start_method = sys.argv[2]
max_depth = int(sys.argv[3])
class PstatsChainHandler:
def __init__(self, prof_file, max_depth=5) -> None:
self.prof_file = prof_file
self.max_depth = max_depth
self.depth_count = 0
def find_caller(self, method):
stream = StringIO()
stats = pstats.Stats(self.prof_file, stream=stream)
stats.sort_stats("time", "calls")
stats.print_callers(method)
lines = stream.getvalue().splitlines()
if len(lines) < 6:
print("there are no valid caller details")
for caller in lines[5:-2]:
try:
_, caller_deets = caller.split("<-")
matches = re.findall(pattern, caller_deets)
if matches:
match = re.sub(r"\(\w+\)", "", matches[0])
print(match)
self.depth_count += 1
if self.depth_count <= self.max_depth:
self.find_caller(match)
except ValueError:
return
handler = PstatsChainHandler(prof_file=prof_file, max_depth=max_depth)
handler.find_caller(start_method)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment