blob: 3921781cd9ddac872cd09332902e89a03e8c0617 [file] [log] [blame]
#!/usr/bin/env fuchsia-vendored-python
# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
import json
import os
import re
import sys
def main():
parser = argparse.ArgumentParser(
description="Turn a log and a regex into a JSON weighted tree.")
parser.add_argument(
"--infile",
type=argparse.FileType("r"),
required=True,
help="Input text file with lines to be processed",
)
parser.add_argument(
"--outfile",
type=argparse.FileType("w"),
required=True,
help="Output JSON file")
parser.add_argument(
"--regex",
required=True,
help="Regex whose first capture group will be used to get tree paths",
)
parser.add_argument(
"--root", required=True, help="Name of root node in the tree")
args = parser.parse_args()
# Initialize the tree at the root node.
# Use a map for children for fast lookup.
root = {"name": args.root, "children": {}}
# Process input lines
regex = re.compile(args.regex)
for line in args.infile.readlines():
m = regex.match(line)
if m:
path = os.path.normpath(m.group(1)).split(os.path.sep)
node = root
# Traverse the tree, possibly creating nodes along the path, until
# arriving at the leaf
for part in path[:-1]:
node = node["children"].setdefault(
part, {
"name": part,
"children": {}
})
# Create or update leaf node
leaf = node["children"].setdefault(
path[-1], {
"name": path[-1],
"value": 0
})
leaf["value"] += 1
# Transform tree into output format.
# Use a list for children for presentation such as with d3js.
output = {"name": args.root, "children": []}
def add_children(parent, children):
add_to = parent["children"]
for name, child in children.items():
if "children" in child:
new_child = {"name": name, "children": []}
add_children(new_child, child["children"])
else:
new_child = child
add_to.append(new_child)
add_children(output, root["children"])
# Write output
json.dump(output, args.outfile)
return 0
if __name__ == "__main__":
sys.exit(main())