|
| 1 | +import sys |
| 2 | +import json |
| 3 | + |
| 4 | +file = sys.argv[1] |
| 5 | + |
| 6 | + |
| 7 | +def main(): |
| 8 | + # read traces |
| 9 | + traces = list(read_file()) |
| 10 | + |
| 11 | + # separate threads |
| 12 | + thread_traces = separate_threads(traces) |
| 13 | + |
| 14 | + # make tree for every thread |
| 15 | + root = TraceNode('<root>') |
| 16 | + for thread_id, traces in thread_traces: |
| 17 | + t = make_tree(str(thread_id), traces) |
| 18 | + root.add(t) |
| 19 | + |
| 20 | + # output as xmind |
| 21 | + print(xmind(root)) |
| 22 | + |
| 23 | + |
| 24 | +def xmind(node): |
| 25 | + return '\n'.join(xmind_lines(node)) |
| 26 | + |
| 27 | + |
| 28 | +def xmind_lines(node): |
| 29 | + lines = [] |
| 30 | + lines.append(node.text) |
| 31 | + for e in node.children: |
| 32 | + for line in xmind_lines(e): |
| 33 | + lines.append('\t' + line) |
| 34 | + return lines |
| 35 | + |
| 36 | + |
| 37 | +def make_tree(name, traces): |
| 38 | + root = TraceNode(name) |
| 39 | + if not traces: return root |
| 40 | + target_depth = traces[0].depth |
| 41 | + next_level = [] |
| 42 | + for e in traces: |
| 43 | + if e.direction == 'in': continue |
| 44 | + if e.depth != target_depth: |
| 45 | + next_level.append(e) |
| 46 | + continue |
| 47 | + if e.depth == target_depth: |
| 48 | + name = simple_method_name(e.clazz, e.method) |
| 49 | + node = make_tree(name, next_level) |
| 50 | + root.add(node) |
| 51 | + next_level = [] |
| 52 | + continue |
| 53 | + return root |
| 54 | + |
| 55 | + |
| 56 | +def simple_method_name(full_class, method_name): |
| 57 | + dot = full_class.rindex('.') |
| 58 | + simple_class = full_class[dot + 1:] |
| 59 | + if '$' not in simple_class: return simple_class + '.' + method_name |
| 60 | + dollar = simple_class.rindex('$') |
| 61 | + nest_class = simple_class[dollar + 1:] |
| 62 | + return nest_class + '.' + method_name |
| 63 | + |
| 64 | + |
| 65 | +def separate_threads(traces): |
| 66 | + # all threads |
| 67 | + threads = [] |
| 68 | + for e in traces: |
| 69 | + if e.thread not in threads: |
| 70 | + threads.append(e.thread) |
| 71 | + |
| 72 | + # every thread: |
| 73 | + result = [] |
| 74 | + for e in threads: |
| 75 | + thread_traces = [] |
| 76 | + for e2 in traces: |
| 77 | + if e2.thread == e: |
| 78 | + thread_traces.append(e2) |
| 79 | + result.append((e, thread_traces)) |
| 80 | + return result |
| 81 | + |
| 82 | + |
| 83 | +def read_file(): |
| 84 | + with open(file) as f: |
| 85 | + for e in f: |
| 86 | + e = e.strip() |
| 87 | + if not e: continue |
| 88 | + yield parse_trace(e) |
| 89 | + |
| 90 | + |
| 91 | +def parse_trace(trace): |
| 92 | + trace = json.loads(trace) |
| 93 | + result = Trace() |
| 94 | + result.time = trace['@timestamp'] |
| 95 | + result.method = trace['method'] |
| 96 | + result.clazz = trace['class'] |
| 97 | + result.depth = trace['depth'] |
| 98 | + result.thread = trace['thread'] |
| 99 | + result.direction = trace['direction'] |
| 100 | + return result |
| 101 | + |
| 102 | + |
| 103 | +class Trace: |
| 104 | + direction = None |
| 105 | + thread = None |
| 106 | + depth = None |
| 107 | + clazz = None |
| 108 | + method = None |
| 109 | + time = None |
| 110 | + |
| 111 | + |
| 112 | +class TraceNode: |
| 113 | + def __init__(self, text): |
| 114 | + self.text = text |
| 115 | + self.children = [] |
| 116 | + |
| 117 | + def add(self, node): |
| 118 | + self.children.append(node) |
| 119 | + |
| 120 | + |
| 121 | +main() |
0 commit comments