/* * Copyright (C) 2021 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. */ #ifndef ART_ODREFRESH_ODR_METRICS_H_ #define ART_ODREFRESH_ODR_METRICS_H_ #include #include #include #include #include #include "base/macros.h" #include "odr_metrics_record.h" namespace art { namespace odrefresh { class OdrMetrics final { public: // Enumeration used to track the latest stage reached running odrefresh. // // These values mirror those in OdrefreshReported::Stage in frameworks/proto_logging/atoms.proto. // NB There are gaps between the values in case an additional stages are introduced. enum class Stage : uint8_t { kUnknown = 0, kCheck = 10, kPreparation = 20, kPrimaryBootClasspath = 30, kSecondaryBootClasspath = 40, kSystemServerClasspath = 50, kComplete = 60, }; // Enumeration describing the overall status, processing stops on the first error discovered. // // These values mirror those in OdrefreshReported::Status in frameworks/proto_logging/atoms.proto. enum class Status : uint8_t { kUnknown = 0, kOK = 1, kNoSpace = 2, kIoError = 3, kDex2OatError = 4, kTimeLimitExceeded = 5, kStagingFailed = 6, kInstallFailed = 7, }; // Enumeration describing the cause of compilation (if any) in odrefresh. // // These values mirror those in OdrefreshReported::Trigger in // frameworks/proto_logging/atoms.proto. enum class Trigger : uint8_t { kUnknown = 0, kApexVersionMismatch = 1, kDexFilesChanged = 2, kMissingArtifacts = 3, }; explicit OdrMetrics(const std::string& cache_directory, const std::string& metrics_file = kOdrefreshMetricsFile); ~OdrMetrics(); // Gets the ART APEX that metrics are being collected on behalf of. int64_t GetArtApexVersion() const { return art_apex_version_; } // Sets the ART APEX that metrics are being collected on behalf of. void SetArtApexVersion(int64_t version) { art_apex_version_ = version; } // Gets the ART APEX last update time in milliseconds. int64_t GetArtApexLastUpdateMillis() const { return art_apex_last_update_millis_; } // Sets the ART APEX last update time in milliseconds. void SetArtApexLastUpdateMillis(int64_t last_update_millis) { art_apex_last_update_millis_ = last_update_millis; } // Gets the trigger for metrics collection. The trigger is the reason why odrefresh considers // compilation necessary. Trigger GetTrigger() const { return trigger_.has_value() ? trigger_.value() : Trigger::kUnknown; } // Sets the trigger for metrics collection. The trigger is the reason why odrefresh considers // compilation necessary. Only call this method if compilation is necessary as the presence // of a trigger means we will try to record and upload metrics. void SetTrigger(const Trigger trigger) { trigger_ = trigger; } // Sets the execution status of the current odrefresh processing stage. void SetStatus(const Status status) { status_ = status; } // Sets the current odrefresh processing stage. void SetStage(Stage stage); // Record metrics into an OdrMetricsRecord. // returns true on success, false if instance is not valid (because the trigger value is not set). bool ToRecord(/*out*/OdrMetricsRecord* record) const; private: OdrMetrics(const OdrMetrics&) = delete; OdrMetrics operator=(const OdrMetrics&) = delete; static int32_t GetFreeSpaceMiB(const std::string& path); static void WriteToFile(const std::string& path, const OdrMetrics* metrics); void SetCompilationTime(int32_t seconds); const std::string cache_directory_; const std::string metrics_file_; int64_t art_apex_version_ = 0; int64_t art_apex_last_update_millis_ = 0; std::optional trigger_ = {}; // metrics are only logged if compilation is triggered. Stage stage_ = Stage::kUnknown; Status status_ = Status::kUnknown; int32_t primary_bcp_compilation_seconds_ = 0; int32_t secondary_bcp_compilation_seconds_ = 0; int32_t system_server_compilation_seconds_ = 0; int32_t cache_space_free_start_mib_ = 0; int32_t cache_space_free_end_mib_ = 0; friend class ScopedOdrCompilationTimer; }; // Timer used to measure compilation time (in seconds). Automatically associates the time recorded // with the current stage of the metrics used. class ScopedOdrCompilationTimer final { public: explicit ScopedOdrCompilationTimer(OdrMetrics& metrics) : metrics_(metrics), start_(std::chrono::steady_clock::now()) {} ~ScopedOdrCompilationTimer() { auto elapsed_time = std::chrono::steady_clock::now() - start_; auto elapsed_seconds = std::chrono::duration_cast(elapsed_time); metrics_.SetCompilationTime(static_cast(elapsed_seconds.count())); } private: OdrMetrics& metrics_; std::chrono::time_point start_; DISALLOW_ALLOCATION(); }; // Generated ostream operators. std::ostream& operator<<(std::ostream& os, OdrMetrics::Status status); std::ostream& operator<<(std::ostream& os, OdrMetrics::Stage stage); std::ostream& operator<<(std::ostream& os, OdrMetrics::Trigger trigger); } // namespace odrefresh } // namespace art #endif // ART_ODREFRESH_ODR_METRICS_H_