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 #include "statsd.h"
18
19 #include "arch/instruction_set.h"
20 #include "base/compiler_filter.h"
21 #include "base/metrics/metrics.h"
22 #include "statslog_art.h"
23
24 #pragma clang diagnostic push
25 #pragma clang diagnostic error "-Wconversion"
26
27 namespace art {
28 namespace metrics {
29
30 namespace {
31
32 // EncodeDatumId returns a std::optional that provides a enum value from atoms.proto if the datum is
33 // one that we support logging to statsd. The list of datums that ART collects is a superset of what
34 // we report to statsd. Therefore, we only have mappings for the DatumIds that statsd recognizes.
35 // Also it must be noted that histograms are not handled yet by statsd yet.
36 //
37 // Other code can use whether the result of this function has a value to decide whether to report
38 // the atom to statsd.
39 //
40 // To report additional measurements to statsd, first add an entry in atoms.proto and then add an
41 // entry to this function as well.
EncodeDatumId(DatumId datum_id)42 constexpr std::optional<int32_t> EncodeDatumId(DatumId datum_id) {
43 switch (datum_id) {
44 case DatumId::kClassVerificationTotalTime:
45 return std::make_optional(
46 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_CLASS_VERIFICATION_TIME_COUNTER_MICROS);
47 case DatumId::kJitMethodCompileTotalTime:
48 return std::make_optional(
49 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_JIT_METHOD_COMPILE_TIME_MICROS);
50 case DatumId::kClassLoadingTotalTime:
51 return std::make_optional(
52 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_CLASS_LOADING_TIME_COUNTER_MICROS);
53 case DatumId::kClassVerificationCount:
54 return std::make_optional(
55 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_CLASS_VERIFICATION_COUNT);
56 case DatumId::kWorldStopTimeDuringGCAvg:
57 return std::make_optional(
58 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_WORLD_STOP_TIME_AVG_MICROS);
59 case DatumId::kYoungGcCount:
60 return std::make_optional(
61 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_YOUNG_GENERATION_COLLECTION_COUNT);
62 case DatumId::kFullGcCount:
63 return std::make_optional(
64 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_FULL_HEAP_COLLECTION_COUNT);
65 case DatumId::kTotalBytesAllocated:
66 return std::make_optional(
67 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_TOTAL_BYTES_ALLOCATED);
68 case DatumId::kYoungGcCollectionTime:
69 return std::make_optional(
70 statsd::
71 ART_DATUM_REPORTED__KIND__ART_DATUM_GC_YOUNG_GENERATION_COLLECTION_TIME_HISTO_MILLIS);
72 case DatumId::kFullGcCollectionTime:
73 return std::make_optional(
74 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_FULL_HEAP_COLLECTION_TIME_HISTO_MILLIS);
75 case DatumId::kYoungGcThroughput:
76 return std::make_optional(
77 statsd::
78 ART_DATUM_REPORTED__KIND__ART_DATUM_GC_YOUNG_GENERATION_COLLECTION_THROUGHPUT_HISTO_MB_PER_SEC);
79 case DatumId::kFullGcThroughput:
80 return std::make_optional(
81 statsd::
82 ART_DATUM_REPORTED__KIND__ART_DATUM_GC_FULL_HEAP_COLLECTION_THROUGHPUT_HISTO_MB_PER_SEC);
83 case DatumId::kJitMethodCompileCount:
84 return std::make_optional(
85 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_JIT_METHOD_COMPILE_COUNT);
86 case DatumId::kYoungGcTracingThroughput:
87 return std::make_optional(
88 statsd::
89 ART_DATUM_REPORTED__KIND__ART_DATUM_GC_YOUNG_GENERATION_TRACING_THROUGHPUT_HISTO_MB_PER_SEC);
90 case DatumId::kFullGcTracingThroughput:
91 return std::make_optional(
92 statsd::
93 ART_DATUM_REPORTED__KIND__ART_DATUM_GC_FULL_HEAP_TRACING_THROUGHPUT_HISTO_MB_PER_SEC);
94 case DatumId::kTotalGcCollectionTime:
95 return std::make_optional(
96 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_TOTAL_COLLECTION_TIME_MS);
97 case DatumId::kYoungGcThroughputAvg:
98 return std::make_optional(
99 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_YOUNG_GENERATION_COLLECTION_THROUGHPUT_AVG_MB_PER_SEC);
100 case DatumId::kFullGcThroughputAvg:
101 return std::make_optional(
102 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_FULL_HEAP_COLLECTION_THROUGHPUT_AVG_MB_PER_SEC);
103 case DatumId::kYoungGcTracingThroughputAvg:
104 return std::make_optional(
105 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_YOUNG_GENERATION_TRACING_THROUGHPUT_AVG_MB_PER_SEC);
106 case DatumId::kFullGcTracingThroughputAvg:
107 return std::make_optional(
108 statsd::ART_DATUM_REPORTED__KIND__ART_DATUM_GC_FULL_HEAP_TRACING_THROUGHPUT_AVG_MB_PER_SEC);
109 }
110 }
111
EncodeCompileFilter(CompilerFilterReporting filter)112 constexpr int32_t EncodeCompileFilter(CompilerFilterReporting filter) {
113 switch (filter) {
114 case CompilerFilterReporting::kAssumeVerified:
115 return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_ASSUMED_VERIFIED;
116 case CompilerFilterReporting::kExtract:
117 return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EXTRACT;
118 case CompilerFilterReporting::kVerify:
119 return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_VERIFY;
120 case CompilerFilterReporting::kSpaceProfile:
121 return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPACE_PROFILE;
122 case CompilerFilterReporting::kSpace:
123 return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPACE;
124 case CompilerFilterReporting::kSpeedProfile:
125 return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPEED_PROFILE;
126 case CompilerFilterReporting::kSpeed:
127 return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_SPEED;
128 case CompilerFilterReporting::kEverythingProfile:
129 return statsd::
130 ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EVERYTHING_PROFILE;
131 case CompilerFilterReporting::kEverything:
132 return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_EVERYTHING;
133 case CompilerFilterReporting::kError:
134 return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_ERROR;
135 case CompilerFilterReporting::kUnknown:
136 return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_UNKNOWN;
137 case CompilerFilterReporting::kRunFromApk:
138 return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK;
139 case CompilerFilterReporting::kRunFromApkFallback:
140 return statsd::ART_DATUM_REPORTED__COMPILE_FILTER__ART_COMPILATION_FILTER_FAKE_RUN_FROM_APK_FALLBACK;
141 }
142 }
143
EncodeCompilationReason(CompilationReason reason)144 constexpr int32_t EncodeCompilationReason(CompilationReason reason) {
145 switch (reason) {
146 case CompilationReason::kUnknown:
147 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_UNKNOWN;
148 case CompilationReason::kABOTA:
149 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_AB_OTA;
150 case CompilationReason::kBgDexopt:
151 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_BG_DEXOPT;
152 case CompilationReason::kError:
153 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_ERROR;
154 case CompilationReason::kFirstBoot:
155 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_FIRST_BOOT;
156 case CompilationReason::kInactive:
157 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INACTIVE;
158 case CompilationReason::kInstall:
159 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL;
160 case CompilationReason::kInstallWithDexMetadata:
161 return statsd::
162 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_WITH_DEX_METADATA;
163 case CompilationReason::kShared:
164 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_SHARED;
165 case CompilationReason::kPostBoot:
166 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_POST_BOOT;
167 case CompilationReason::kInstallBulk:
168 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK;
169 case CompilationReason::kInstallBulkSecondary:
170 return statsd::
171 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY;
172 case CompilationReason::kInstallBulkDowngraded:
173 return statsd::
174 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_DOWNGRADED;
175 case CompilationReason::kInstallBulkSecondaryDowngraded:
176 return statsd::
177 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED;
178 case CompilationReason::kBootAfterOTA:
179 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_BOOT_AFTER_OTA;
180 case CompilationReason::kInstallFast:
181 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INSTALL_FAST;
182 case CompilationReason::kPrebuilt:
183 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_PREBUILT;
184 case CompilationReason::kCmdLine:
185 return statsd::ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_CMDLINE;
186 }
187 }
188
EncodeInstructionSet(InstructionSet isa)189 constexpr int32_t EncodeInstructionSet(InstructionSet isa) {
190 switch (isa) {
191 case InstructionSet::kArm:
192 // Fall-through.
193 case InstructionSet::kThumb2:
194 return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_ARM;
195 case InstructionSet::kArm64:
196 return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_ARM64;
197 case InstructionSet::kX86:
198 return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_X86;
199 case InstructionSet::kX86_64:
200 return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_X86_64;
201 case InstructionSet::kNone:
202 return statsd::ART_DATUM_REPORTED__ISA__ART_ISA_UNKNOWN;
203 }
204 }
205
206 class StatsdBackend : public MetricsBackend {
207 public:
BeginOrUpdateSession(const SessionData & session_data)208 void BeginOrUpdateSession(const SessionData& session_data) override {
209 session_data_ = session_data;
210 }
211
212 protected:
BeginReport(uint64_t timestamp_since_start_ms)213 void BeginReport(uint64_t timestamp_since_start_ms) override {
214 current_timestamp_ = static_cast<int64_t>(timestamp_since_start_ms);
215 }
216
ReportCounter(DatumId counter_type,uint64_t value)217 void ReportCounter(DatumId counter_type, uint64_t value) override {
218 std::optional<int32_t> datum_id = EncodeDatumId(counter_type);
219 if (datum_id.has_value()) {
220 statsd::stats_write(
221 statsd::ART_DATUM_REPORTED,
222 session_data_.session_id,
223 session_data_.uid,
224 EncodeCompileFilter(session_data_.compiler_filter),
225 EncodeCompilationReason(session_data_.compilation_reason),
226 current_timestamp_,
227 /*thread_type=*/0, // TODO: collect and report thread type (0 means UNKNOWN, but that
228 // constant is not present in all branches)
229 datum_id.value(),
230 static_cast<int64_t>(value),
231 statsd::ART_DATUM_REPORTED__DEX_METADATA_TYPE__ART_DEX_METADATA_TYPE_UNKNOWN,
232 statsd::ART_DATUM_REPORTED__APK_TYPE__ART_APK_TYPE_UNKNOWN,
233 EncodeInstructionSet(kRuntimeISA));
234 }
235 }
236
ReportHistogram(DatumId,int64_t,int64_t,const std::vector<uint32_t> &)237 void ReportHistogram(DatumId /*histogram_type*/,
238 int64_t /*low_value*/,
239 int64_t /*high_value*/,
240 const std::vector<uint32_t>& /*buckets*/) override {
241 // TODO: implement this once ArtDatumReported in atoms.proto supports histograms.
242 LOG_STREAM(DEBUG) << "Attempting to write histogram to statsd. This is not supported yet.";
243 }
244
EndReport()245 void EndReport() override {}
246
247 private:
248 SessionData session_data_;
249 // The timestamp provided to the last call to BeginReport
250 int64_t current_timestamp_;
251 };
252
253 } // namespace
254
CreateStatsdBackend()255 std::unique_ptr<MetricsBackend> CreateStatsdBackend() { return std::make_unique<StatsdBackend>(); }
256
257 } // namespace metrics
258 } // namespace art
259
260 #pragma clang diagnostic pop // -Wconversion
261