github.com/noironetworks/cilium-net@v1.6.12/contrib/scripts/consolidate_go_stacktrace.py (about) 1 #!/usr/bin/env python 2 3 # consolidate_go_stacktrace.py collapses a go stacktrace by uniqueing each 4 # stack. Addresses, goroutine ID and goroutine ages are ignored when determining 5 # uniqeness. A sample of each unique trace is printed 6 7 import re,sys,collections 8 9 def get_stacks(f): 10 """ 11 get_stacks parses file f and yields all lines in go stackrace as one array 12 """ 13 accum = [] 14 for line in f: 15 line = line.rstrip() 16 if line.startswith("goroutine"): 17 yield accum 18 accum = [] 19 else: 20 accum.append(line) 21 22 # Regexes used to find and remove addresses, ids and age 23 strip_addresses = re.compile(r"0x[0-9a-fA-F]+") 24 strip_goroutine_id = re.compile(r"goroutine [0-9]+") 25 strip_goroutine_time = re.compile(r", [0-9]+ minutes") 26 def strip_stack(stack): 27 """ 28 strip_stack replaces addresses, goroutine IDs and ages with a fixed sentinel 29 """ 30 stack = [strip_addresses.sub("0x?", l) for l in stack] 31 stack = [strip_goroutine_id.sub("?", l) for l in stack] 32 stack = [strip_goroutine_time.sub("", l) for l in stack] 33 return stack 34 35 def get_hashable_stack_value(stack): 36 """ 37 get_hashable_stack_value transforms stack (and array of strings) into 38 something that can be used as a map key 39 """ 40 return "".join(strip_stack(stack)) 41 42 def print_usage(): 43 print """usage: {} [-h | path/to/file] 44 -h: This help. 45 path/to/file: Read and parse file with go stacktraces 46 "-" or no params: Read and parse stdin""".format(sys.argv[0]) 47 48 if __name__ == "__main__": 49 # Handle arguments. We only support a file path, or stdin on "-" or no 50 # parameter 51 infile = sys.argv[1] if len(sys.argv) > 1 else "" 52 if infile in ["-h", "help"]: 53 print_usage() 54 sys.exit(0) 55 elif infile in ["-", "", None]: 56 f = sys.stdin 57 else: 58 f = open(infile) 59 60 # collect stacktraces into groups, each keyed by a version of the stack 61 # where unwanted fields have been made into sentinels 62 consolidated = collections.defaultdict(list) 63 for stack in get_stacks(f): 64 h = get_hashable_stack_value(stack) 65 consolidated[h].append(stack) 66 67 # print count of each unique stack, and a sample, sorted by frequency 68 print "{} unique stack traces".format(len(consolidated)) 69 for stack in sorted(consolidated.values(), cmp=lambda a,b: len(a)-len(b), reverse=True): 70 print "{} occurences. Sample stack trace:".format(len(stack)) 71 print "\n".join(stack[0]) 72 73 if f != sys.stdin: 74 f.close()