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