blob: 35d26112e3b7a31f0ac26b2f5a374739dde75b57 [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())