| #!/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() |