xref: /aosp_15_r20/art/runtime/metrics/reporter.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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