1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_METRICS_REPORTER_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_METRICS_REPORTER_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include "app_info.h" 21*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 22*795d594fSAndroid Build Coastguard Worker #include "base/message_queue.h" 23*795d594fSAndroid Build Coastguard Worker #include "base/metrics/metrics.h" 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker #pragma clang diagnostic push 26*795d594fSAndroid Build Coastguard Worker #pragma clang diagnostic error "-Wconversion" 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 29*795d594fSAndroid Build Coastguard Worker namespace metrics { 30*795d594fSAndroid Build Coastguard Worker 31*795d594fSAndroid Build Coastguard Worker /** 32*795d594fSAndroid Build Coastguard Worker * Encapsulates the specification of the metric reporting periods. 33*795d594fSAndroid Build Coastguard Worker * 34*795d594fSAndroid Build Coastguard Worker * The period spec follows the following regex: "(S,)?(\d+,)*\*?" 35*795d594fSAndroid Build Coastguard Worker * with the following semantics: 36*795d594fSAndroid Build Coastguard Worker * "S" - will only report at startup. 37*795d594fSAndroid Build Coastguard Worker * 38*795d594fSAndroid Build Coastguard Worker * "S,1,1" - will report startup, than 1 second later, then another 39*795d594fSAndroid Build Coastguard Worker * second later. 40*795d594fSAndroid Build Coastguard Worker * 41*795d594fSAndroid Build Coastguard Worker * "S,1,2,4 " - will report at Startup time, then 1 seconds later, 42*795d594fSAndroid Build Coastguard Worker * then 2, then finally 4 seconds later. After that, the 43*795d594fSAndroid Build Coastguard Worker * reporting will stop. 44*795d594fSAndroid Build Coastguard Worker * 45*795d594fSAndroid Build Coastguard Worker * "S,1,2,4,*" - same as above, but after the final 4s period, the 46*795d594fSAndroid Build Coastguard Worker * reporting will continue every other 4s. 47*795d594fSAndroid Build Coastguard Worker * '*' is an indication we should report continuously 48*795d594fSAndroid Build Coastguard Worker * every N seconds, where N is the last period. 49*795d594fSAndroid Build Coastguard Worker * 50*795d594fSAndroid Build Coastguard Worker * "2,*" - will report every 2 seconds 51*795d594fSAndroid Build Coastguard Worker * 52*795d594fSAndroid Build Coastguard Worker * Note that "", "*", or "S,*" are not valid specs, and 'S' can only occur 53*795d594fSAndroid Build Coastguard Worker * in the beginning. 54*795d594fSAndroid Build Coastguard Worker */ 55*795d594fSAndroid Build Coastguard Worker struct ReportingPeriodSpec { 56*795d594fSAndroid Build Coastguard Worker static std::optional<ReportingPeriodSpec> Parse( 57*795d594fSAndroid Build Coastguard Worker const std::string& spec_str, std::string* error_msg); 58*795d594fSAndroid Build Coastguard Worker 59*795d594fSAndroid Build Coastguard Worker // The original spec. 60*795d594fSAndroid Build Coastguard Worker std::string spec; 61*795d594fSAndroid Build Coastguard Worker // The intervals when we should report. 62*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> periods_seconds; 63*795d594fSAndroid Build Coastguard Worker // Whether or not the reporting is continuous (contains a '*'). 64*795d594fSAndroid Build Coastguard Worker bool continuous_reporting{false}; 65*795d594fSAndroid Build Coastguard Worker // Whether or not the reporting should start after startup event (starts with an 'S'). 66*795d594fSAndroid Build Coastguard Worker bool report_startup_first{false}; 67*795d594fSAndroid Build Coastguard Worker }; 68*795d594fSAndroid Build Coastguard Worker 69*795d594fSAndroid Build Coastguard Worker // Defines the set of options for how metrics reporting happens. 70*795d594fSAndroid Build Coastguard Worker struct ReportingConfig { 71*795d594fSAndroid Build Coastguard Worker static ReportingConfig FromFlags(bool is_system_server = false); 72*795d594fSAndroid Build Coastguard Worker 73*795d594fSAndroid Build Coastguard Worker // Causes metrics to be written to the log, which makes them show up in logcat. 74*795d594fSAndroid Build Coastguard Worker bool dump_to_logcat{false}; 75*795d594fSAndroid Build Coastguard Worker 76*795d594fSAndroid Build Coastguard Worker // Causes metrics to be written to statsd. 77*795d594fSAndroid Build Coastguard Worker bool dump_to_statsd{false}; 78*795d594fSAndroid Build Coastguard Worker 79*795d594fSAndroid Build Coastguard Worker // If set, provides a file name to enable metrics logging to a file. 80*795d594fSAndroid Build Coastguard Worker std::optional<std::string> dump_to_file; 81*795d594fSAndroid Build Coastguard Worker 82*795d594fSAndroid Build Coastguard Worker // Provides the desired output format for metrics written to a file. 83*795d594fSAndroid Build Coastguard Worker std::string metrics_format; 84*795d594fSAndroid Build Coastguard Worker 85*795d594fSAndroid Build Coastguard Worker // The reporting period configuration. 86*795d594fSAndroid Build Coastguard Worker std::optional<ReportingPeriodSpec> period_spec; 87*795d594fSAndroid Build Coastguard Worker 88*795d594fSAndroid Build Coastguard Worker // The mods that should report metrics. Together with reporting_num_mods, they 89*795d594fSAndroid Build Coastguard Worker // dictate what percentage of the runtime execution will report metrics. 90*795d594fSAndroid Build Coastguard Worker // If the `session_id (a random number) % reporting_num_mods < reporting_mods` 91*795d594fSAndroid Build Coastguard Worker // then the runtime session will report metrics. 92*795d594fSAndroid Build Coastguard Worker uint32_t reporting_mods{0}; 93*795d594fSAndroid Build Coastguard Worker uint32_t reporting_num_mods{100}; 94*795d594fSAndroid Build Coastguard Worker }; 95*795d594fSAndroid Build Coastguard Worker 96*795d594fSAndroid Build Coastguard Worker // MetricsReporter handles periodically reporting ART metrics. 97*795d594fSAndroid Build Coastguard Worker class MetricsReporter { 98*795d594fSAndroid Build Coastguard Worker public: 99*795d594fSAndroid Build Coastguard Worker // Creates a MetricsReporter instance that matches the options selected in ReportingConfig. 100*795d594fSAndroid Build Coastguard Worker static std::unique_ptr<MetricsReporter> Create(const ReportingConfig& config, Runtime* runtime); 101*795d594fSAndroid Build Coastguard Worker 102*795d594fSAndroid Build Coastguard Worker virtual ~MetricsReporter(); 103*795d594fSAndroid Build Coastguard Worker 104*795d594fSAndroid Build Coastguard Worker // Creates and runs the background reporting thread. 105*795d594fSAndroid Build Coastguard Worker // 106*795d594fSAndroid Build Coastguard Worker // Does nothing if the reporting config does not have any outputs enabled. 107*795d594fSAndroid Build Coastguard Worker // 108*795d594fSAndroid Build Coastguard Worker // Returns true if the thread was started, false otherwise. 109*795d594fSAndroid Build Coastguard Worker bool MaybeStartBackgroundThread(SessionData session_data); 110*795d594fSAndroid Build Coastguard Worker 111*795d594fSAndroid Build Coastguard Worker // Sends a request to the background thread to shutdown. 112*795d594fSAndroid Build Coastguard Worker void MaybeStopBackgroundThread(); 113*795d594fSAndroid Build Coastguard Worker 114*795d594fSAndroid Build Coastguard Worker // Causes metrics to be reported so we can see a snapshot of the metrics after app startup 115*795d594fSAndroid Build Coastguard Worker // completes. 116*795d594fSAndroid Build Coastguard Worker void NotifyStartupCompleted(); 117*795d594fSAndroid Build Coastguard Worker 118*795d594fSAndroid Build Coastguard Worker // Notifies the reporter that the app info was updated. This is used to detect / infer 119*795d594fSAndroid Build Coastguard Worker // the compiler filter / reason of primary apks. 120*795d594fSAndroid Build Coastguard Worker void NotifyAppInfoUpdated(AppInfo* app_info); 121*795d594fSAndroid Build Coastguard Worker 122*795d594fSAndroid Build Coastguard Worker // Requests a metrics report 123*795d594fSAndroid Build Coastguard Worker // 124*795d594fSAndroid Build Coastguard Worker // If synchronous is set to true, this function will block until the report has completed. 125*795d594fSAndroid Build Coastguard Worker void RequestMetricsReport(bool synchronous = true); 126*795d594fSAndroid Build Coastguard Worker 127*795d594fSAndroid Build Coastguard Worker // Reloads the metrics config from the given value. 128*795d594fSAndroid Build Coastguard Worker // Can only be called before starting the background thread. 129*795d594fSAndroid Build Coastguard Worker void ReloadConfig(const ReportingConfig& config); 130*795d594fSAndroid Build Coastguard Worker 131*795d594fSAndroid Build Coastguard Worker void SetCompilationInfo(CompilationReason compilation_reason, 132*795d594fSAndroid Build Coastguard Worker CompilerFilterReporting compiler_filter); 133*795d594fSAndroid Build Coastguard Worker 134*795d594fSAndroid Build Coastguard Worker static constexpr const char* kBackgroundThreadName = "Metrics Background Reporting Thread"; 135*795d594fSAndroid Build Coastguard Worker 136*795d594fSAndroid Build Coastguard Worker protected: 137*795d594fSAndroid Build Coastguard Worker // Returns the metrics to be reported. 138*795d594fSAndroid Build Coastguard Worker // This exists only for testing purposes so that we can verify reporting with minimum 139*795d594fSAndroid Build Coastguard Worker // runtime interference. 140*795d594fSAndroid Build Coastguard Worker virtual ArtMetrics* GetMetrics(); 141*795d594fSAndroid Build Coastguard Worker 142*795d594fSAndroid Build Coastguard Worker MetricsReporter(const ReportingConfig& config, Runtime* runtime); 143*795d594fSAndroid Build Coastguard Worker 144*795d594fSAndroid Build Coastguard Worker private: 145*795d594fSAndroid Build Coastguard Worker // Whether or not we should reporting metrics according to the sampling rate. 146*795d594fSAndroid Build Coastguard Worker bool IsMetricsReportingEnabled(const SessionData& session_data) const; 147*795d594fSAndroid Build Coastguard Worker 148*795d594fSAndroid Build Coastguard Worker // The background reporting thread main loop. 149*795d594fSAndroid Build Coastguard Worker void BackgroundThreadRun(); 150*795d594fSAndroid Build Coastguard Worker 151*795d594fSAndroid Build Coastguard Worker // Calls messages_.SetTimeout if needed. 152*795d594fSAndroid Build Coastguard Worker void MaybeResetTimeout(); 153*795d594fSAndroid Build Coastguard Worker 154*795d594fSAndroid Build Coastguard Worker // Outputs the current state of the metrics to the destination set by config_. 155*795d594fSAndroid Build Coastguard Worker void ReportMetrics(); 156*795d594fSAndroid Build Coastguard Worker 157*795d594fSAndroid Build Coastguard Worker // Updates the session data in all the backends. 158*795d594fSAndroid Build Coastguard Worker void UpdateSessionInBackends(); 159*795d594fSAndroid Build Coastguard Worker 160*795d594fSAndroid Build Coastguard Worker // Whether or not we should wait for startup before reporting for the first time. 161*795d594fSAndroid Build Coastguard Worker bool ShouldReportAtStartup() const; 162*795d594fSAndroid Build Coastguard Worker 163*795d594fSAndroid Build Coastguard Worker // Whether or not we should continue reporting (either because we still 164*795d594fSAndroid Build Coastguard Worker // have periods to report, or because we are in continuous mode). 165*795d594fSAndroid Build Coastguard Worker bool ShouldContinueReporting() const; 166*795d594fSAndroid Build Coastguard Worker 167*795d594fSAndroid Build Coastguard Worker // Returns the next reporting period. 168*795d594fSAndroid Build Coastguard Worker // Must be called only if ShouldContinueReporting() is true. 169*795d594fSAndroid Build Coastguard Worker uint32_t GetNextPeriodSeconds(); 170*795d594fSAndroid Build Coastguard Worker 171*795d594fSAndroid Build Coastguard Worker ReportingConfig config_; 172*795d594fSAndroid Build Coastguard Worker Runtime* runtime_; 173*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<MetricsBackend>> backends_; 174*795d594fSAndroid Build Coastguard Worker std::optional<std::thread> thread_; 175*795d594fSAndroid Build Coastguard Worker // Whether or not we reported the startup event. 176*795d594fSAndroid Build Coastguard Worker bool startup_reported_; 177*795d594fSAndroid Build Coastguard Worker // The index into period_spec.periods_seconds which tells the next delay in 178*795d594fSAndroid Build Coastguard Worker // seconds for the next reporting. 179*795d594fSAndroid Build Coastguard Worker uint32_t report_interval_index_; 180*795d594fSAndroid Build Coastguard Worker 181*795d594fSAndroid Build Coastguard Worker // A message indicating that the reporting thread should shut down. 182*795d594fSAndroid Build Coastguard Worker struct ShutdownRequestedMessage {}; 183*795d594fSAndroid Build Coastguard Worker 184*795d594fSAndroid Build Coastguard Worker // A message indicating that app startup has completed. 185*795d594fSAndroid Build Coastguard Worker struct StartupCompletedMessage {}; 186*795d594fSAndroid Build Coastguard Worker 187*795d594fSAndroid Build Coastguard Worker // A message requesting an explicit metrics report. 188*795d594fSAndroid Build Coastguard Worker // 189*795d594fSAndroid Build Coastguard Worker // The synchronous field specifies whether the reporting thread will send a message back when 190*795d594fSAndroid Build Coastguard Worker // reporting is complete. 191*795d594fSAndroid Build Coastguard Worker struct RequestMetricsReportMessage { 192*795d594fSAndroid Build Coastguard Worker bool synchronous; 193*795d594fSAndroid Build Coastguard Worker }; 194*795d594fSAndroid Build Coastguard Worker 195*795d594fSAndroid Build Coastguard Worker struct CompilationInfoMessage { 196*795d594fSAndroid Build Coastguard Worker CompilationReason compilation_reason; 197*795d594fSAndroid Build Coastguard Worker CompilerFilterReporting compiler_filter; 198*795d594fSAndroid Build Coastguard Worker }; 199*795d594fSAndroid Build Coastguard Worker 200*795d594fSAndroid Build Coastguard Worker MessageQueue<ShutdownRequestedMessage, 201*795d594fSAndroid Build Coastguard Worker StartupCompletedMessage, 202*795d594fSAndroid Build Coastguard Worker RequestMetricsReportMessage, 203*795d594fSAndroid Build Coastguard Worker CompilationInfoMessage> 204*795d594fSAndroid Build Coastguard Worker messages_; 205*795d594fSAndroid Build Coastguard Worker 206*795d594fSAndroid Build Coastguard Worker // A message indicating a requested report has been finished. 207*795d594fSAndroid Build Coastguard Worker struct ReportCompletedMessage {}; 208*795d594fSAndroid Build Coastguard Worker 209*795d594fSAndroid Build Coastguard Worker MessageQueue<ReportCompletedMessage> thread_to_host_messages_; 210*795d594fSAndroid Build Coastguard Worker 211*795d594fSAndroid Build Coastguard Worker SessionData session_data_{}; 212*795d594fSAndroid Build Coastguard Worker bool session_started_{false}; 213*795d594fSAndroid Build Coastguard Worker 214*795d594fSAndroid Build Coastguard Worker friend class MetricsReporterTest; 215*795d594fSAndroid Build Coastguard Worker }; 216*795d594fSAndroid Build Coastguard Worker 217*795d594fSAndroid Build Coastguard Worker } // namespace metrics 218*795d594fSAndroid Build Coastguard Worker } // namespace art 219*795d594fSAndroid Build Coastguard Worker 220*795d594fSAndroid Build Coastguard Worker #pragma clang diagnostic pop // -Wconversion 221*795d594fSAndroid Build Coastguard Worker 222*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_METRICS_REPORTER_H_ 223