summaryrefslogtreecommitdiff
path: root/perf_tools/progress_report.py
diff options
context:
space:
mode:
Diffstat (limited to 'perf_tools/progress_report.py')
-rwxr-xr-xperf_tools/progress_report.py159
1 files changed, 159 insertions, 0 deletions
diff --git a/perf_tools/progress_report.py b/perf_tools/progress_report.py
new file mode 100755
index 00000000..f6a1c430
--- /dev/null
+++ b/perf_tools/progress_report.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import argparse
+from datetime import datetime
+import yaml
+import os
+import report_pb2
+import sys
+import traceback
+
+# Usage: python3 progress_report.py --logcat logcat.txt --config config.yaml --output_dir report_dir
+#
+# logcat.txt should contain the "boot_progress_start" and "boot_progress_enable_screen"".
+# config.yaml contains all the keywords to be extracted.
+# report_dir will contain three generated files:
+#
+# timestamp_log.txt: contains the same content as logcat.txt, but the timestamp is replaced
+# with relative time with boot_progress_start time.
+#
+# report_proto.txt: contains the report for the events related to the keywords.
+#
+# report.txt: contains logcat messages corresponding to the events captured in report_proto.txt
+
+def init_arguments():
+ parser = argparse.ArgumentParser(
+ prog = 'progrocess_report.py',
+ description='Extract timing information and generate a report.')
+ parser.add_argument(
+ '--logcat', type=str, required=True,
+ help = 'logcat file name')
+ parser.add_argument(
+ '--config', type=str, required=True,
+ help = 'configuration file for keywords')
+ parser.add_argument(
+ '--output_dir', type= str, required=True,
+ help = 'directory name to store the generated files')
+ return parser.parse_args()
+
+# Find boot_progress_start line and boot_progress_enable_screen find the time difference
+# return the start time string
+def find_boot_progress_start_end(fp):
+ start = ""
+ end = ""
+ for line in fp:
+ if "boot_progress_start" in line:
+ start = line
+ if "boot_progress_enable_screen" in line and len(start):
+ end = line
+ break
+
+ missing_error = ""
+ if start == "":
+ missing_error = "******logcat file missing boot_progress_start\n"
+ elif end == "":
+ missing_error += "******logcat file missing boot_progress_end "
+ if missing_error != "":
+ sys.exit("Missing required message in the logcat:\n" + missing_error)
+ return [start, end]
+
+# TODO(b/262259622): passing a tuple of (startDate, endDate)
+def replace_timestamp_abs(line, timestamp_str, date_time_obj0):
+ index = line.find(" ", 6)
+ if index <= 0:
+ return line
+ substr0 = line[:index]
+ substr1 = line[index:]
+
+ try:
+ date_time_obj = datetime.strptime(substr0, '%m-%d %H:%M:%S.%f')
+ except ValueError:
+ return line
+
+ date_time_delta = date_time_obj - date_time_obj0
+ date_time_delta_str = str(date_time_delta)
+ return date_time_delta_str + substr1
+
+def in_time_range(start, end, line):
+ try:
+ current_time = datetime.strptime(line[:18], '%m-%d %H:%M:%S.%f')
+ except ValueError:
+ return False
+
+ if current_time >= start and current_time <= end:
+ return True
+
+ return False
+
+# Here is an example of event we would like extract:
+# 09-15 16:04:15.655 root 991 991 I boot_progress_preload_start: 5440
+# for each event, it is a tuple of(timestamp, event_name, timing)
+def extract_event(line, keywords):
+ words = line.split(" ")
+ for keyword in keywords:
+ if keyword in words[-2]:
+ return (words[0], words[-2], words[-1])
+ return ()
+
+def write_to_new_file(timestamps, keywords, logcat_fp, timestamp_fixed_logcat_fp, report_fp,
+ report_proto_fp):
+ start_timestamp_obj = datetime.strptime(timestamps[0][:18], '%m-%d %H:%M:%S.%f')
+ end_timestamp_obj = datetime.strptime(timestamps[1][:18], '%m-%d %H:%M:%S.%f')
+ report = report_pb2.Report()
+ for line in logcat_fp:
+ ts_fixed_line = replace_timestamp_abs(line, timestamps[0][:18], start_timestamp_obj)
+ timestamp_fixed_logcat_fp.write(ts_fixed_line)
+ if in_time_range(start_timestamp_obj, end_timestamp_obj, line):
+ event = extract_event(ts_fixed_line, keywords)
+ if len(event) == 0:
+ continue
+
+ report_fp.write(ts_fixed_line)
+ record = report.record.add()
+ record.timestamp = event[0]
+ record.event = event[1]
+ record.timing = int(event[2])
+ report_proto_fp.write(str(report))
+
+def main():
+ args = init_arguments()
+
+ keywords = []
+ with open(args.config, 'r') as file:
+ keywords = yaml.safe_load(file)
+
+ if not os.path.isdir(args.output_dir):
+ os.mkdir(args.output_dir)
+ timestamp_fixed_logcat_fp = open(os.path.join(args.output_dir, "timestamp_fixed_log.txt"), 'w')
+ report_fp = open(os.path.join(args.output_dir, "report.txt"), 'w')
+ report_proto_fp = open(os.path.join(args.output_dir, "report_proto.txt"), 'w')
+ try:
+ with open(args.logcat, 'r', errors = 'ignore') as logcat_fp:
+ timestamps = find_boot_progress_start_end(logcat_fp)
+ logcat_fp.seek(0)
+ write_to_new_file(timestamps, keywords, logcat_fp, timestamp_fixed_logcat_fp, report_fp, report_proto_fp)
+ except Exception as e:
+ traceresult = traceback.format_exc()
+ print("Caught an exception: {}".format(traceback.format_exc()))
+
+ timestamp_fixed_logcat_fp.close()
+ report_fp.close()
+ report_proto_fp.close()
+
+if __name__ == '__main__':
+ main()