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 "odr_metrics_record.h" 28 29 namespace art { 30 namespace odrefresh { 31 32 class OdrMetrics final { 33 public: 34 // Enumeration used to track the latest stage reached running odrefresh. 35 // 36 // These values mirror those in OdrefreshReported::Stage in frameworks/proto_logging/atoms.proto. 37 // NB There are gaps between the values in case an additional stages are introduced. 38 enum class Stage : uint8_t { 39 kUnknown = 0, 40 kCheck = 10, 41 kPreparation = 20, 42 kPrimaryBootClasspath = 30, 43 kSecondaryBootClasspath = 40, 44 kSystemServerClasspath = 50, 45 kComplete = 60, 46 }; 47 48 // Enumeration describing the overall status, processing stops on the first error discovered. 49 // 50 // These values mirror those in OdrefreshReported::Status in frameworks/proto_logging/atoms.proto. 51 enum class Status : uint8_t { 52 kUnknown = 0, 53 kOK = 1, 54 kNoSpace = 2, 55 kIoError = 3, 56 kDex2OatError = 4, 57 kTimeLimitExceeded = 5, 58 kStagingFailed = 6, 59 kInstallFailed = 7, 60 }; 61 62 // Enumeration describing the cause of compilation (if any) in odrefresh. 63 // 64 // These values mirror those in OdrefreshReported::Trigger in 65 // frameworks/proto_logging/atoms.proto. 66 enum class Trigger : uint8_t { 67 kUnknown = 0, 68 kApexVersionMismatch = 1, 69 kDexFilesChanged = 2, 70 kMissingArtifacts = 3, 71 }; 72 73 explicit OdrMetrics(const std::string& cache_directory, 74 const std::string& metrics_file = kOdrefreshMetricsFile); 75 ~OdrMetrics(); 76 77 // Gets the ART APEX that metrics are being collected on behalf of. GetArtApexVersion()78 int64_t GetArtApexVersion() const { 79 return art_apex_version_; 80 } 81 82 // Sets the ART APEX that metrics are being collected on behalf of. SetArtApexVersion(int64_t version)83 void SetArtApexVersion(int64_t version) { 84 art_apex_version_ = version; 85 } 86 87 // Gets the ART APEX last update time in milliseconds. GetArtApexLastUpdateMillis()88 int64_t GetArtApexLastUpdateMillis() const { 89 return art_apex_last_update_millis_; 90 } 91 92 // Sets the ART APEX last update time in milliseconds. SetArtApexLastUpdateMillis(int64_t last_update_millis)93 void SetArtApexLastUpdateMillis(int64_t last_update_millis) { 94 art_apex_last_update_millis_ = last_update_millis; 95 } 96 97 // Gets the trigger for metrics collection. The trigger is the reason why odrefresh considers 98 // compilation necessary. GetTrigger()99 Trigger GetTrigger() const { 100 return trigger_.has_value() ? trigger_.value() : Trigger::kUnknown; 101 } 102 103 // Sets the trigger for metrics collection. The trigger is the reason why odrefresh considers 104 // compilation necessary. Only call this method if compilation is necessary as the presence 105 // of a trigger means we will try to record and upload metrics. SetTrigger(const Trigger trigger)106 void SetTrigger(const Trigger trigger) { 107 trigger_ = trigger; 108 } 109 110 // Sets the execution status of the current odrefresh processing stage. SetStatus(const Status status)111 void SetStatus(const Status status) { 112 status_ = status; 113 } 114 115 // Sets the current odrefresh processing stage. 116 void SetStage(Stage stage); 117 118 // Record metrics into an OdrMetricsRecord. 119 // returns true on success, false if instance is not valid (because the trigger value is not set). 120 bool ToRecord(/*out*/OdrMetricsRecord* record) const; 121 122 private: 123 OdrMetrics(const OdrMetrics&) = delete; 124 OdrMetrics operator=(const OdrMetrics&) = delete; 125 126 static int32_t GetFreeSpaceMiB(const std::string& path); 127 static void WriteToFile(const std::string& path, const OdrMetrics* metrics); 128 129 void SetCompilationTime(int32_t seconds); 130 131 const std::string cache_directory_; 132 const std::string metrics_file_; 133 134 int64_t art_apex_version_ = 0; 135 int64_t art_apex_last_update_millis_ = 0; 136 std::optional<Trigger> trigger_ = {}; // metrics are only logged if compilation is triggered. 137 Stage stage_ = Stage::kUnknown; 138 Status status_ = Status::kUnknown; 139 140 int32_t primary_bcp_compilation_seconds_ = 0; 141 int32_t secondary_bcp_compilation_seconds_ = 0; 142 int32_t system_server_compilation_seconds_ = 0; 143 int32_t cache_space_free_start_mib_ = 0; 144 int32_t cache_space_free_end_mib_ = 0; 145 146 friend class ScopedOdrCompilationTimer; 147 }; 148 149 // Timer used to measure compilation time (in seconds). Automatically associates the time recorded 150 // with the current stage of the metrics used. 151 class ScopedOdrCompilationTimer final { 152 public: ScopedOdrCompilationTimer(OdrMetrics & metrics)153 explicit ScopedOdrCompilationTimer(OdrMetrics& metrics) : 154 metrics_(metrics), start_(std::chrono::steady_clock::now()) {} 155 ~ScopedOdrCompilationTimer()156 ~ScopedOdrCompilationTimer() { 157 auto elapsed_time = std::chrono::steady_clock::now() - start_; 158 auto elapsed_seconds = std::chrono::duration_cast<std::chrono::seconds>(elapsed_time); 159 metrics_.SetCompilationTime(static_cast<int32_t>(elapsed_seconds.count())); 160 } 161 162 private: 163 OdrMetrics& metrics_; 164 std::chrono::time_point<std::chrono::steady_clock> start_; 165 166 DISALLOW_ALLOCATION(); 167 }; 168 169 // Generated ostream operators. 170 std::ostream& operator<<(std::ostream& os, OdrMetrics::Status status); 171 std::ostream& operator<<(std::ostream& os, OdrMetrics::Stage stage); 172 std::ostream& operator<<(std::ostream& os, OdrMetrics::Trigger trigger); 173 174 } // namespace odrefresh 175 } // namespace art 176 177 #endif // ART_ODREFRESH_ODR_METRICS_H_ 178