1#!/usr/bin/python3 2 3# Copyright (C) 2022 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18"""Tool to parse CarWatchdog's performance stats dump. 19 20To build the parser script run: 21 m perf_stats_parser 22 23To parse a carwatchdog dump text file run: 24 perf_stats_parser -f <cw-dump>.txt -o cw_proto_out.pb 25 26To read a carwatchdog proto file as a json run: 27 perf_stats_parser -r <cw-proto-out>.pb -j 28""" 29 30import argparse 31import json 32import os 33import sys 34 35from . import carwatchdog_dump_parser 36from . import perf_stats_proto_utils 37 38 39def init_arguments() -> argparse.Namespace: 40 """Initializes the program arguments.""" 41 parser = argparse.ArgumentParser(description="Parses CarWatchdog's dump.") 42 parser.add_argument( 43 "-f", 44 "--file", 45 dest="file", 46 default="dump.txt", 47 help="File with the CarWatchdog dump", 48 ) 49 parser.add_argument( 50 "-o", 51 "--out", 52 dest="out", 53 help="protobuf binary with parsed performance stats", 54 ) 55 parser.add_argument( 56 "-b", 57 "--build", 58 dest="build", 59 help="File with Android device build information", 60 ) 61 parser.add_argument( 62 "-d", 63 "--device-out", 64 dest="device_out", 65 default="device_perf_stats.pb", 66 help="protobuf binary with build information", 67 ) 68 parser.add_argument( 69 "-p", 70 "--print", 71 dest="print", 72 action="store_true", 73 help=( 74 "prints the parsed performance data to the console " 75 "when out proto defined" 76 ), 77 ) 78 parser.add_argument( 79 "-r", 80 "--read", 81 dest="read_proto", 82 help=( 83 "Protobuf binary to be printed in console. If this " 84 "flag is set no other process is executed." 85 ), 86 ) 87 parser.add_argument( 88 "-D", 89 "--device-run", 90 dest="device_run", 91 action="store_true", 92 help=( 93 "Specifies that the proto to be read is a " 94 "DevicePerformanceStats proto. (Only checked if " 95 "-r is set)" 96 ), 97 ) 98 parser.add_argument( 99 "-j", 100 "--json", 101 dest="json", 102 action="store_true", 103 help="Generate a JSON file from the protobuf binary read.", 104 ) 105 106 return parser.parse_args() 107 108 109if __name__ == "__main__": 110 args = init_arguments() 111 112 if args.read_proto: 113 if not os.path.isfile(args.read_proto): 114 print("Error: Proto binary '%s' does not exist" % args.read_proto) 115 sys.exit(1) 116 if args.device_run: 117 performance_stats = ( 118 perf_stats_proto_utils.read_device_performance_stats_pb( 119 args.read_proto 120 ) 121 ) 122 else: 123 performance_stats = perf_stats_proto_utils.read_performance_stats_pb( 124 args.read_proto 125 ) 126 if performance_stats is None: 127 print(f"Error: Could not read '{args.read_proto}'") 128 sys.exit(1) 129 if args.json: 130 print(json.dumps(performance_stats.to_dict())) 131 else: 132 print(performance_stats) 133 sys.exit() 134 135 if not os.path.isfile(args.file): 136 print("Error: File '%s' does not exist" % args.file) 137 sys.exit(1) 138 139 with open(args.file, "r", encoding="UTF-8", errors="ignore") as f: 140 performance_stats = carwatchdog_dump_parser.parse_dump(f.read()) 141 142 build_info = None 143 if args.build: 144 build_info = carwatchdog_dump_parser.parse_build_info(args.build) 145 print(build_info) 146 147 if performance_stats.is_empty(): 148 print( 149 "Error: No performance stats were parsed. Make sure dump file" 150 " contains carwatchdog's dump text." 151 ) 152 sys.exit(1) 153 154 if (args.out or args.build) and perf_stats_proto_utils.write_pb( 155 performance_stats, args.out, build_info, args.device_out 156 ): 157 out_file = args.out if args.out else args.device_out 158 print("Output protobuf binary in:", out_file) 159 160 if args.print or not (args.out or args.build): 161 if args.json: 162 print(json.dumps(performance_stats.to_dict())) 163 sys.exit() 164 print(performance_stats) 165