1# Copyright 2024, The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""MetricsAgent is a singleton class that collects metrics for optimized build.""" 16 17from enum import Enum 18import time 19import metrics_pb2 20import os 21import logging 22 23 24class MetricsAgent: 25 _SOONG_METRICS_PATH = 'logs/soong_metrics' 26 _DIST_DIR = 'DIST_DIR' 27 _instance = None 28 29 def __init__(self): 30 raise RuntimeError( 31 'MetricsAgent cannot be instantialized, use instance() instead' 32 ) 33 34 @classmethod 35 def instance(cls): 36 if not cls._instance: 37 cls._instance = cls.__new__(cls) 38 cls._instance._proto = metrics_pb2.OptimizedBuildMetrics() 39 cls._instance._init_proto() 40 cls._instance._target_results = dict() 41 42 return cls._instance 43 44 def _init_proto(self): 45 self._proto.analysis_perf.name = 'Optimized build analysis time.' 46 self._proto.packaging_perf.name = 'Optimized build total packaging time.' 47 48 def analysis_start(self): 49 self._proto.analysis_perf.start_time = time.time_ns() 50 51 def analysis_end(self): 52 self._proto.analysis_perf.real_time = ( 53 time.time_ns() - self._proto.analysis_perf.start_time 54 ) 55 56 def packaging_start(self): 57 self._proto.packaging_perf.start_time = time.time_ns() 58 59 def packaging_end(self): 60 self._proto.packaging_perf.real_time = ( 61 time.time_ns() - self._proto.packaging_perf.start_time 62 ) 63 64 def report_optimized_target(self, name: str): 65 target_result = metrics_pb2.OptimizedBuildMetrics.TargetOptimizationResult() 66 target_result.name = name 67 target_result.optimized = True 68 self._target_results[name] = target_result 69 70 def report_unoptimized_target(self, name: str, optimization_rationale: str): 71 target_result = metrics_pb2.OptimizedBuildMetrics.TargetOptimizationResult() 72 target_result.name = name 73 target_result.optimization_rationale = optimization_rationale 74 target_result.optimized = False 75 self._target_results[name] = target_result 76 77 def target_packaging_start(self, name: str): 78 target_result = self._target_results.get(name) 79 target_result.packaging_perf.start_time = time.time_ns() 80 self._target_results[name] = target_result 81 82 def target_packaging_end(self, name: str): 83 target_result = self._target_results.get(name) 84 target_result.packaging_perf.real_time = ( 85 time.time_ns() - target_result.packaging_perf.start_time 86 ) 87 88 def add_target_artifact( 89 self, 90 target_name: str, 91 artifact_name: str, 92 size: int, 93 included_modules: set[str], 94 ): 95 target_result = self.target_results.get(target_name) 96 artifact = ( 97 metrics_pb2.OptimizedBuildMetrics.TargetOptimizationResult.OutputArtifact() 98 ) 99 artifact.name = artifact_name 100 artifact.size = size 101 for module in included_modules: 102 artifact.included_modules.add(module) 103 target_result.output_artifacts.add(artifact) 104 105 def end_reporting(self): 106 for target_result in self._target_results.values(): 107 self._proto.target_result.append(target_result) 108 soong_metrics_proto = metrics_pb2.MetricsBase() 109 # Read in existing metrics that should have been written out by the soong 110 # build command so that we don't overwrite them. 111 with open(os.path.join(os.environ[self._DIST_DIR], self._SOONG_METRICS_PATH), 'rb') as f: 112 soong_metrics_proto.ParseFromString(f.read()) 113 soong_metrics_proto.optimized_build_metrics.CopyFrom(self._proto) 114 logging.info(soong_metrics_proto) 115 with open(os.path.join(os.environ[self._DIST_DIR], self._SOONG_METRICS_PATH), 'wb') as f: 116 f.write(soong_metrics_proto.SerializeToString()) 117