1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_ODREFRESH_ODR_METRICS_H_ 18 #define ART_ODREFRESH_ODR_METRICS_H_ 19 20 #include <chrono> 21 #include <cstdint> 22 #include <iosfwd> 23 #include <optional> 24 #include <string> 25 26 #include "base/macros.h" 27 #include "exec_utils.h" 28 #include "odr_metrics_record.h" 29 30 namespace art { 31 namespace odrefresh { 32 33 class OdrMetrics final { 34 public: 35 // Enumeration used to track the latest stage reached running odrefresh. 36 // 37 // These values mirror those in OdrefreshReported::Stage in 38 // frameworks/proto_logging/atoms/art/odrefresh_extension_atoms.proto. 39 // NB There are gaps between the values in case an additional stages are introduced. 40 enum class Stage : uint8_t { 41 kUnknown = 0, 42 kCheck = 10, 43 kPreparation = 20, 44 kPrimaryBootClasspath = 30, 45 kSecondaryBootClasspath = 40, 46 kSystemServerClasspath = 50, 47 kComplete = 60, 48 }; 49 50 // Enumeration describing the overall status, processing stops on the first error discovered. 51 // 52 // These values mirror those in OdrefreshReported::Status in 53 // frameworks/proto_logging/atoms/art/odrefresh_extension_atoms.proto. 54 enum class Status : uint8_t { 55 kUnknown = 0, 56 kOK = 1, 57 kNoSpace = 2, 58 kIoError = 3, 59 kDex2OatError = 4, 60 // Value 5 was kTimeLimitExceeded, but has been removed in favour of 61 // reporting the exit code for Dex2Oat (set to ExecResult::kTimedOut) 62 kStagingFailed = 6, 63 kInstallFailed = 7, 64 // Failed to access the dalvik-cache directory due to lack of permission. 65 kDalvikCachePermissionDenied = 8, 66 }; 67 68 // Enumeration describing the cause of compilation (if any) in odrefresh. 69 // 70 // These values mirror those in OdrefreshReported::Trigger in 71 // frameworks/proto_logging/atoms/art/odrefresh_extension_atoms.proto. 72 enum class Trigger : uint8_t { 73 kUnknown = 0, 74 kApexVersionMismatch = 1, 75 kDexFilesChanged = 2, 76 kMissingArtifacts = 3, 77 }; 78 79 // Enumeration describing the type of boot classpath compilation in odrefresh. 80 // 81 // These values mirror those in OdrefreshReported::BcpCompilationType in 82 // frameworks/proto_logging/atoms/art/odrefresh_extension_atoms.proto. 83 enum class BcpCompilationType : uint8_t { 84 kUnknown = 0, 85 // Compiles for both the primary boot image and the mainline extension. 86 kPrimaryAndMainline = 1, 87 // Only compiles for the mainline extension. 88 kMainline = 2, 89 }; 90 91 explicit OdrMetrics(const std::string& cache_directory, 92 const std::string& metrics_file = kOdrefreshMetricsFile); 93 ~OdrMetrics(); 94 95 // Enables/disables metrics writing. SetEnabled(bool value)96 void SetEnabled(bool value) { enabled_ = value; } 97 98 // Gets the ART APEX that metrics are being collected on behalf of. GetArtApexVersion()99 int64_t GetArtApexVersion() const { return art_apex_version_; } 100 101 // Sets the ART APEX that metrics are being collected on behalf of. SetArtApexVersion(int64_t version)102 void SetArtApexVersion(int64_t version) { art_apex_version_ = version; } 103 104 // Gets the ART APEX last update time in milliseconds. GetArtApexLastUpdateMillis()105 int64_t GetArtApexLastUpdateMillis() const { return art_apex_last_update_millis_; } 106 107 // Sets the ART APEX last update time in milliseconds. SetArtApexLastUpdateMillis(int64_t last_update_millis)108 void SetArtApexLastUpdateMillis(int64_t last_update_millis) { 109 art_apex_last_update_millis_ = last_update_millis; 110 } 111 112 // Gets the trigger for metrics collection. The trigger is the reason why odrefresh considers 113 // compilation necessary. GetTrigger()114 Trigger GetTrigger() const { return trigger_; } 115 116 // Sets the trigger for metrics collection. The trigger is the reason why odrefresh considers 117 // compilation necessary. Only call this method if compilation is necessary as the presence 118 // of a trigger means we will try to record and upload metrics. SetTrigger(const Trigger trigger)119 void SetTrigger(const Trigger trigger) { trigger_ = trigger; } 120 121 // Sets the execution status of the current odrefresh processing stage. SetStatus(const Status status)122 void SetStatus(const Status status) { status_ = status; } 123 124 // Sets the current odrefresh processing stage. SetStage(Stage stage)125 void SetStage(Stage stage) { stage_ = stage; } 126 127 // Sets the result of the current dex2oat invocation. 128 void SetDex2OatResult(Stage stage, 129 int64_t compilation_time, 130 const std::optional<ExecResult>& dex2oat_result); 131 132 // Sets the BCP compilation type. 133 void SetBcpCompilationType(Stage stage, BcpCompilationType type); 134 135 // Captures the current free space as the end free space. 136 void CaptureSpaceFreeEnd(); 137 138 // Records metrics into an OdrMetricsRecord. 139 OdrMetricsRecord ToRecord() const; 140 141 private: 142 OdrMetrics(const OdrMetrics&) = delete; 143 OdrMetrics operator=(const OdrMetrics&) = delete; 144 145 static int32_t GetFreeSpaceMiB(const std::string& path); 146 static void WriteToFile(const std::string& path, const OdrMetrics* metrics); 147 148 static OdrMetricsRecord::Dex2OatExecResult 149 ConvertExecResult(const std::optional<ExecResult>& result); 150 151 const std::string cache_directory_; 152 const std::string metrics_file_; 153 154 bool enabled_ = false; 155 156 int64_t art_apex_version_ = 0; 157 int64_t art_apex_last_update_millis_ = 0; 158 Trigger trigger_ = Trigger::kUnknown; 159 Stage stage_ = Stage::kUnknown; 160 Status status_ = Status::kUnknown; 161 162 int32_t cache_space_free_start_mib_ = 0; 163 int32_t cache_space_free_end_mib_ = 0; 164 165 // The total time spent on compiling primary BCP. 166 int32_t primary_bcp_compilation_millis_ = 0; 167 168 // The result of the dex2oat invocation for compiling primary BCP, or `std::nullopt` if dex2oat is 169 // not invoked. 170 std::optional<ExecResult> primary_bcp_dex2oat_result_; 171 172 BcpCompilationType primary_bcp_compilation_type_ = BcpCompilationType::kUnknown; 173 174 // The total time spent on compiling secondary BCP. 175 int32_t secondary_bcp_compilation_millis_ = 0; 176 177 // The result of the dex2oat invocation for compiling secondary BCP, or `std::nullopt` if dex2oat 178 // is not invoked. 179 std::optional<ExecResult> secondary_bcp_dex2oat_result_; 180 181 BcpCompilationType secondary_bcp_compilation_type_ = BcpCompilationType::kUnknown; 182 183 // The total time spent on compiling system server. 184 int32_t system_server_compilation_millis_ = 0; 185 186 // The result of the last dex2oat invocation for compiling system server, or `std::nullopt` if 187 // dex2oat is not invoked. 188 std::optional<ExecResult> system_server_dex2oat_result_; 189 }; 190 191 // Generated ostream operators. 192 std::ostream& operator<<(std::ostream& os, OdrMetrics::Status status); 193 std::ostream& operator<<(std::ostream& os, OdrMetrics::Stage stage); 194 std::ostream& operator<<(std::ostream& os, OdrMetrics::Trigger trigger); 195 196 } // namespace odrefresh 197 } // namespace art 198 199 #endif // ART_ODREFRESH_ODR_METRICS_H_ 200