|  | #!/usr/bin/env python3 | 
|  | # Copyright (c) 2021 Intel Corporation | 
|  | # | 
|  | # SPDX-License-Identifier: Apache-2.0 | 
|  |  | 
|  | from anytree.importer import DictImporter | 
|  | from anytree import PreOrderIter | 
|  | from anytree.search  import find | 
|  | importer = DictImporter() | 
|  | from datetime import datetime | 
|  | from dateutil.relativedelta import relativedelta | 
|  | import os | 
|  | import json | 
|  | from git import Repo | 
|  | from git.exc import BadName | 
|  |  | 
|  | from influxdb import InfluxDBClient | 
|  | import glob | 
|  | import argparse | 
|  | from tabulate import tabulate | 
|  |  | 
|  | TODAY = datetime.utcnow() | 
|  | two_mon_rel = relativedelta(months=4) | 
|  |  | 
|  | influx_dsn = 'influxdb://localhost:8086/footprint_tracking' | 
|  |  | 
|  | def create_event(data, board, feature, commit, current_time, typ, application): | 
|  | footprint_data = [] | 
|  | client = InfluxDBClient.from_dsn(influx_dsn) | 
|  | client.create_database('footprint_tracking') | 
|  | for d in data.keys(): | 
|  | footprint_data.append({ | 
|  | "measurement": d, | 
|  | "tags": { | 
|  | "board": board, | 
|  | "commit": commit, | 
|  | "application": application, | 
|  | "type": typ, | 
|  | "feature": feature | 
|  | }, | 
|  | "time": current_time, | 
|  | "fields": { | 
|  | "value": data[d] | 
|  | } | 
|  | }) | 
|  |  | 
|  | client.write_points(footprint_data, time_precision='s', database='footprint_tracking') | 
|  |  | 
|  |  | 
|  | def parse_args(): | 
|  | global args | 
|  | parser = argparse.ArgumentParser( | 
|  | description=__doc__, | 
|  | formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False) | 
|  |  | 
|  | parser.add_argument("-d", "--data", help="Data Directory") | 
|  | parser.add_argument("-y", "--dryrun", action="store_true", help="Dry run, do not upload to database") | 
|  | parser.add_argument("-z", "--zephyr-base", help="Zephyr tree") | 
|  | parser.add_argument("-f", "--file", help="JSON file with footprint data") | 
|  | args = parser.parse_args() | 
|  |  | 
|  |  | 
|  | def parse_file(json_file): | 
|  |  | 
|  | with open(json_file, "r") as fp: | 
|  | contents = json.load(fp) | 
|  | root = importer.import_(contents['symbols']) | 
|  |  | 
|  | zr = find(root, lambda node: node.name == 'ZEPHYR_BASE') | 
|  | ws = find(root, lambda node: node.name == 'WORKSPACE') | 
|  |  | 
|  | data = {} | 
|  | if zr and ws: | 
|  | trees = [zr, ws] | 
|  | else: | 
|  | trees = [root] | 
|  |  | 
|  | for node in PreOrderIter(root, maxlevel=2): | 
|  | if node.name not in ['WORKSPACE', 'ZEPHYR_BASE']: | 
|  | if node.name in ['Root', 'Symbols']: | 
|  | data['all'] = node.size | 
|  | else: | 
|  | data[node.name] = node.size | 
|  |  | 
|  | for t in trees: | 
|  | root = t.name | 
|  | for node in PreOrderIter(t, maxlevel=2): | 
|  | if node.name == root: | 
|  | continue | 
|  | comp = node.name | 
|  | if comp in ['Root', 'Symbols']: | 
|  | data['all'] = node.size | 
|  | else: | 
|  | data[comp] = node.size | 
|  |  | 
|  | return data | 
|  |  | 
|  | def process_files(data_dir, zephyr_base, dry_run): | 
|  | repo = Repo(zephyr_base) | 
|  |  | 
|  | for hash in os.listdir(f'{data_dir}'): | 
|  | if not dry_run: | 
|  | client = InfluxDBClient.from_dsn(influx_dsn) | 
|  | result = client.query(f"select * from kernel where commit = '{hash}';") | 
|  | if result: | 
|  | print(f"Skipping {hash}...") | 
|  | continue | 
|  | print(f"Importing {hash}...") | 
|  | for file in glob.glob(f"{args.data}/{hash}/**/*json", recursive=True): | 
|  | file_data = file.split("/") | 
|  | json_file = os.path.basename(file) | 
|  | if 'ram' in json_file: | 
|  | typ = 'ram' | 
|  | else: | 
|  | typ = 'rom' | 
|  | commit = file_data[1] | 
|  | app = file_data[2] | 
|  | feature = file_data[3] | 
|  | board = file_data[4] | 
|  |  | 
|  | data = parse_file(file) | 
|  |  | 
|  | try: | 
|  | gitcommit = repo.commit(f'{commit}') | 
|  | current_time = gitcommit.committed_datetime | 
|  | except BadName: | 
|  | cidx = commit.find('-g') + 2 | 
|  | gitcommit = repo.commit(f'{commit[cidx:]}') | 
|  | current_time = gitcommit.committed_datetime | 
|  |  | 
|  | print(current_time) | 
|  |  | 
|  | if not dry_run: | 
|  | create_event(data, board, feature, commit, current_time, typ, app) | 
|  |  | 
|  | def main(): | 
|  | parse_args() | 
|  |  | 
|  | if args.data and args.zephyr_base: | 
|  | process_files(args.data, args.zephyr_base, args.dryrun) | 
|  |  | 
|  | if args.file: | 
|  | data = parse_file(args.file) | 
|  | items = [] | 
|  | for component,value in data.items(): | 
|  | items.append([component,value]) | 
|  |  | 
|  | table = tabulate(items, headers=['Component', 'Size'], tablefmt='orgtbl') | 
|  | print(table) | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | main() |