blob: b8ebcbf96015b753b1cd78d940767c27d76bb92b [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2014 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//
David Zeuthen33bae492014-02-25 16:16:18 -080016
17#include "update_engine/metrics.h"
18
19#include <string>
20
21#include <base/logging.h>
Alex Deymoa2591792015-11-17 00:39:40 -030022#include <metrics/metrics_library.h>
David Zeuthen33bae492014-02-25 16:16:18 -080023
Alex Deymo39910dc2015-11-09 17:04:30 -080024#include "update_engine/common/clock_interface.h"
25#include "update_engine/common/constants.h"
26#include "update_engine/common/prefs_interface.h"
27#include "update_engine/common/utils.h"
Alex Deymoa2591792015-11-17 00:39:40 -030028#include "update_engine/metrics_utils.h"
David Zeuthen33bae492014-02-25 16:16:18 -080029#include "update_engine/system_state.h"
David Zeuthen33bae492014-02-25 16:16:18 -080030
31using std::string;
32
33namespace chromeos_update_engine {
34
35namespace metrics {
36
37// UpdateEngine.Daily.* metrics.
38const char kMetricDailyOSAgeDays[] = "UpdateEngine.Daily.OSAgeDays";
39
40// UpdateEngine.Check.* metrics.
41const char kMetricCheckDownloadErrorCode[] =
42 "UpdateEngine.Check.DownloadErrorCode";
43const char kMetricCheckReaction[] = "UpdateEngine.Check.Reaction";
44const char kMetricCheckResult[] = "UpdateEngine.Check.Result";
45const char kMetricCheckTimeSinceLastCheckMinutes[] =
46 "UpdateEngine.Check.TimeSinceLastCheckMinutes";
47const char kMetricCheckTimeSinceLastCheckUptimeMinutes[] =
48 "UpdateEngine.Check.TimeSinceLastCheckUptimeMinutes";
49
50// UpdateEngine.Attempt.* metrics.
51const char kMetricAttemptNumber[] = "UpdateEngine.Attempt.Number";
52const char kMetricAttemptPayloadType[] =
53 "UpdateEngine.Attempt.PayloadType";
54const char kMetricAttemptPayloadSizeMiB[] =
55 "UpdateEngine.Attempt.PayloadSizeMiB";
David Zeuthenb281f072014-04-02 10:20:19 -070056const char kMetricAttemptConnectionType[] =
57 "UpdateEngine.Attempt.ConnectionType";
David Zeuthen33bae492014-02-25 16:16:18 -080058const char kMetricAttemptDurationMinutes[] =
59 "UpdateEngine.Attempt.DurationMinutes";
60const char kMetricAttemptDurationUptimeMinutes[] =
61 "UpdateEngine.Attempt.DurationUptimeMinutes";
62const char kMetricAttemptTimeSinceLastAttemptMinutes[] =
63 "UpdateEngine.Attempt.TimeSinceLastAttemptMinutes";
64const char kMetricAttemptTimeSinceLastAttemptUptimeMinutes[] =
65 "UpdateEngine.Attempt.TimeSinceLastAttemptUptimeMinutes";
David Zeuthen33bae492014-02-25 16:16:18 -080066const char kMetricAttemptPayloadBytesDownloadedMiB[] =
67 "UpdateEngine.Attempt.PayloadBytesDownloadedMiB";
68const char kMetricAttemptPayloadDownloadSpeedKBps[] =
69 "UpdateEngine.Attempt.PayloadDownloadSpeedKBps";
70const char kMetricAttemptDownloadSource[] =
71 "UpdateEngine.Attempt.DownloadSource";
72const char kMetricAttemptResult[] =
73 "UpdateEngine.Attempt.Result";
74const char kMetricAttemptInternalErrorCode[] =
75 "UpdateEngine.Attempt.InternalErrorCode";
76const char kMetricAttemptDownloadErrorCode[] =
77 "UpdateEngine.Attempt.DownloadErrorCode";
78
79// UpdateEngine.SuccessfulUpdate.* metrics.
80const char kMetricSuccessfulUpdateAttemptCount[] =
81 "UpdateEngine.SuccessfulUpdate.AttemptCount";
82const char kMetricSuccessfulUpdateBytesDownloadedMiB[] =
83 "UpdateEngine.SuccessfulUpdate.BytesDownloadedMiB";
84const char kMetricSuccessfulUpdateDownloadOverheadPercentage[] =
85 "UpdateEngine.SuccessfulUpdate.DownloadOverheadPercentage";
86const char kMetricSuccessfulUpdateDownloadSourcesUsed[] =
87 "UpdateEngine.SuccessfulUpdate.DownloadSourcesUsed";
88const char kMetricSuccessfulUpdatePayloadType[] =
89 "UpdateEngine.SuccessfulUpdate.PayloadType";
90const char kMetricSuccessfulUpdatePayloadSizeMiB[] =
91 "UpdateEngine.SuccessfulUpdate.PayloadSizeMiB";
92const char kMetricSuccessfulUpdateRebootCount[] =
93 "UpdateEngine.SuccessfulUpdate.RebootCount";
94const char kMetricSuccessfulUpdateTotalDurationMinutes[] =
95 "UpdateEngine.SuccessfulUpdate.TotalDurationMinutes";
96const char kMetricSuccessfulUpdateUpdatesAbandonedCount[] =
97 "UpdateEngine.SuccessfulUpdate.UpdatesAbandonedCount";
98const char kMetricSuccessfulUpdateUrlSwitchCount[] =
99 "UpdateEngine.SuccessfulUpdate.UrlSwitchCount";
100
David Zeuthen96197df2014-04-16 12:22:39 -0700101// UpdateEngine.Rollback.* metric.
102const char kMetricRollbackResult[] = "UpdateEngine.Rollback.Result";
103
David Zeuthen33bae492014-02-25 16:16:18 -0800104// UpdateEngine.* metrics.
105const char kMetricFailedUpdateCount[] = "UpdateEngine.FailedUpdateCount";
106const char kMetricInstallDateProvisioningSource[] =
107 "UpdateEngine.InstallDateProvisioningSource";
108const char kMetricTimeToRebootMinutes[] =
109 "UpdateEngine.TimeToRebootMinutes";
110
111void ReportDailyMetrics(SystemState *system_state,
112 base::TimeDelta os_age) {
113 string metric = metrics::kMetricDailyOSAgeDays;
114 LOG(INFO) << "Uploading " << utils::FormatTimeDelta(os_age)
115 << " for metric " << metric;
116 system_state->metrics_lib()->SendToUMA(
117 metric,
118 static_cast<int>(os_age.InDays()),
119 0, // min: 0 days
120 6*30, // max: 6 months (approx)
121 50); // num_buckets
122}
123
124void ReportUpdateCheckMetrics(SystemState *system_state,
125 CheckResult result,
126 CheckReaction reaction,
127 DownloadErrorCode download_error_code) {
128 string metric;
129 int value;
130 int max_value;
131
132 if (result != metrics::CheckResult::kUnset) {
133 metric = metrics::kMetricCheckResult;
134 value = static_cast<int>(result);
135 max_value = static_cast<int>(metrics::CheckResult::kNumConstants) - 1;
136 LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
137 system_state->metrics_lib()->SendEnumToUMA(metric, value, max_value);
138 }
139 if (reaction != metrics::CheckReaction::kUnset) {
140 metric = metrics::kMetricCheckReaction;
141 value = static_cast<int>(reaction);
142 max_value = static_cast<int>(metrics::CheckReaction::kNumConstants) - 1;
143 LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
144 system_state->metrics_lib()->SendEnumToUMA(metric, value, max_value);
145 }
146 if (download_error_code != metrics::DownloadErrorCode::kUnset) {
147 metric = metrics::kMetricCheckDownloadErrorCode;
148 value = static_cast<int>(download_error_code);
David Zeuthenc0dd0212014-04-04 14:49:49 -0700149 LOG(INFO) << "Sending " << value << " for metric " << metric << " (sparse)";
150 system_state->metrics_lib()->SendSparseToUMA(metric, value);
David Zeuthen33bae492014-02-25 16:16:18 -0800151 }
152
153 base::TimeDelta time_since_last;
Alex Deymoa2591792015-11-17 00:39:40 -0300154 if (metrics_utils::WallclockDurationHelper(
155 system_state,
156 kPrefsMetricsCheckLastReportingTime,
157 &time_since_last)) {
David Zeuthen33bae492014-02-25 16:16:18 -0800158 metric = kMetricCheckTimeSinceLastCheckMinutes;
159 LOG(INFO) << "Sending " << utils::FormatTimeDelta(time_since_last)
160 << " for metric " << metric;
161 system_state->metrics_lib()->SendToUMA(
162 metric,
163 time_since_last.InMinutes(),
164 0, // min: 0 min
165 30*24*60, // max: 30 days
166 50); // num_buckets
167 }
168
169 base::TimeDelta uptime_since_last;
170 static int64_t uptime_since_last_storage = 0;
Alex Deymoa2591792015-11-17 00:39:40 -0300171 if (metrics_utils::MonotonicDurationHelper(system_state,
172 &uptime_since_last_storage,
173 &uptime_since_last)) {
David Zeuthen33bae492014-02-25 16:16:18 -0800174 metric = kMetricCheckTimeSinceLastCheckUptimeMinutes;
175 LOG(INFO) << "Sending " << utils::FormatTimeDelta(uptime_since_last)
176 << " for metric " << metric;
177 system_state->metrics_lib()->SendToUMA(
178 metric,
179 uptime_since_last.InMinutes(),
180 0, // min: 0 min
181 30*24*60, // max: 30 days
182 50); // num_buckets
183 }
184}
185
David Zeuthen4e1d1492014-04-25 13:12:27 -0700186void ReportAbnormallyTerminatedUpdateAttemptMetrics(
187 SystemState *system_state) {
188
189 string metric = metrics::kMetricAttemptResult;
190 AttemptResult attempt_result = AttemptResult::kAbnormalTermination;
191
192 LOG(INFO) << "Uploading " << static_cast<int>(attempt_result)
193 << " for metric " << metric;
194 system_state->metrics_lib()->SendEnumToUMA(
195 metric,
196 static_cast<int>(attempt_result),
197 static_cast<int>(AttemptResult::kNumConstants));
198}
199
David Zeuthen33bae492014-02-25 16:16:18 -0800200void ReportUpdateAttemptMetrics(
201 SystemState *system_state,
202 int attempt_number,
203 PayloadType payload_type,
204 base::TimeDelta duration,
205 base::TimeDelta duration_uptime,
206 int64_t payload_size,
207 int64_t payload_bytes_downloaded,
208 int64_t payload_download_speed_bps,
209 DownloadSource download_source,
210 AttemptResult attempt_result,
211 ErrorCode internal_error_code,
David Zeuthenb281f072014-04-02 10:20:19 -0700212 DownloadErrorCode payload_download_error_code,
213 ConnectionType connection_type) {
David Zeuthen33bae492014-02-25 16:16:18 -0800214 string metric;
215
216 metric = metrics::kMetricAttemptNumber;
217 LOG(INFO) << "Uploading " << attempt_number << " for metric " << metric;
218 system_state->metrics_lib()->SendToUMA(metric,
219 attempt_number,
220 0, // min: 0 attempts
221 49, // max: 49 attempts
222 50); // num_buckets
223
224 metric = metrics::kMetricAttemptPayloadType;
225 LOG(INFO) << "Uploading " << utils::ToString(payload_type)
226 << " for metric " << metric;
227 system_state->metrics_lib()->SendEnumToUMA(metric,
228 payload_type,
229 kNumPayloadTypes);
230
231 metric = metrics::kMetricAttemptDurationMinutes;
232 LOG(INFO) << "Uploading " << utils::FormatTimeDelta(duration)
233 << " for metric " << metric;
234 system_state->metrics_lib()->SendToUMA(metric,
235 duration.InMinutes(),
236 0, // min: 0 min
237 10*24*60, // max: 10 days
238 50); // num_buckets
239
240 metric = metrics::kMetricAttemptDurationUptimeMinutes;
241 LOG(INFO) << "Uploading " << utils::FormatTimeDelta(duration_uptime)
242 << " for metric " << metric;
243 system_state->metrics_lib()->SendToUMA(metric,
244 duration_uptime.InMinutes(),
245 0, // min: 0 min
246 10*24*60, // max: 10 days
247 50); // num_buckets
248
249 metric = metrics::kMetricAttemptPayloadSizeMiB;
250 int64_t payload_size_mib = payload_size / kNumBytesInOneMiB;
251 LOG(INFO) << "Uploading " << payload_size_mib << " for metric " << metric;
252 system_state->metrics_lib()->SendToUMA(metric,
253 payload_size_mib,
254 0, // min: 0 MiB
255 1024, // max: 1024 MiB = 1 GiB
256 50); // num_buckets
257
258 metric = metrics::kMetricAttemptPayloadBytesDownloadedMiB;
259 int64_t payload_bytes_downloaded_mib =
260 payload_bytes_downloaded / kNumBytesInOneMiB;
261 LOG(INFO) << "Uploading " << payload_bytes_downloaded_mib
262 << " for metric " << metric;
263 system_state->metrics_lib()->SendToUMA(metric,
264 payload_bytes_downloaded_mib,
265 0, // min: 0 MiB
266 1024, // max: 1024 MiB = 1 GiB
267 50); // num_buckets
268
269 metric = metrics::kMetricAttemptPayloadDownloadSpeedKBps;
270 int64_t payload_download_speed_kbps = payload_download_speed_bps / 1000;
271 LOG(INFO) << "Uploading " << payload_download_speed_kbps
272 << " for metric " << metric;
273 system_state->metrics_lib()->SendToUMA(metric,
274 payload_download_speed_kbps,
275 0, // min: 0 kB/s
276 10*1000, // max: 10000 kB/s = 10 MB/s
277 50); // num_buckets
278
279 metric = metrics::kMetricAttemptDownloadSource;
280 LOG(INFO) << "Uploading " << download_source
281 << " for metric " << metric;
282 system_state->metrics_lib()->SendEnumToUMA(metric,
283 download_source,
284 kNumDownloadSources);
285
286 metric = metrics::kMetricAttemptResult;
287 LOG(INFO) << "Uploading " << static_cast<int>(attempt_result)
288 << " for metric " << metric;
289 system_state->metrics_lib()->SendEnumToUMA(
290 metric,
291 static_cast<int>(attempt_result),
292 static_cast<int>(AttemptResult::kNumConstants));
293
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700294 if (internal_error_code != ErrorCode::kSuccess) {
David Zeuthen33bae492014-02-25 16:16:18 -0800295 metric = metrics::kMetricAttemptInternalErrorCode;
296 LOG(INFO) << "Uploading " << internal_error_code
297 << " for metric " << metric;
298 system_state->metrics_lib()->SendEnumToUMA(
299 metric,
Gilad Arnoldd1c4d2d2014-06-05 14:07:53 -0700300 static_cast<int>(internal_error_code),
301 static_cast<int>(ErrorCode::kUmaReportedMax));
David Zeuthen33bae492014-02-25 16:16:18 -0800302 }
303
304 if (payload_download_error_code != DownloadErrorCode::kUnset) {
305 metric = metrics::kMetricAttemptDownloadErrorCode;
306 LOG(INFO) << "Uploading " << static_cast<int>(payload_download_error_code)
David Zeuthenc0dd0212014-04-04 14:49:49 -0700307 << " for metric " << metric << " (sparse)";
308 system_state->metrics_lib()->SendSparseToUMA(
David Zeuthen33bae492014-02-25 16:16:18 -0800309 metric,
David Zeuthenc0dd0212014-04-04 14:49:49 -0700310 static_cast<int>(payload_download_error_code));
David Zeuthen33bae492014-02-25 16:16:18 -0800311 }
312
313 base::TimeDelta time_since_last;
Alex Deymoa2591792015-11-17 00:39:40 -0300314 if (metrics_utils::WallclockDurationHelper(
315 system_state,
316 kPrefsMetricsAttemptLastReportingTime,
317 &time_since_last)) {
David Zeuthen33bae492014-02-25 16:16:18 -0800318 metric = kMetricAttemptTimeSinceLastAttemptMinutes;
319 LOG(INFO) << "Sending " << utils::FormatTimeDelta(time_since_last)
320 << " for metric " << metric;
321 system_state->metrics_lib()->SendToUMA(
322 metric,
323 time_since_last.InMinutes(),
324 0, // min: 0 min
325 30*24*60, // max: 30 days
326 50); // num_buckets
327 }
328
329 static int64_t uptime_since_last_storage = 0;
330 base::TimeDelta uptime_since_last;
Alex Deymoa2591792015-11-17 00:39:40 -0300331 if (metrics_utils::MonotonicDurationHelper(system_state,
332 &uptime_since_last_storage,
333 &uptime_since_last)) {
David Zeuthen33bae492014-02-25 16:16:18 -0800334 metric = kMetricAttemptTimeSinceLastAttemptUptimeMinutes;
335 LOG(INFO) << "Sending " << utils::FormatTimeDelta(uptime_since_last)
336 << " for metric " << metric;
337 system_state->metrics_lib()->SendToUMA(
338 metric,
339 uptime_since_last.InMinutes(),
340 0, // min: 0 min
341 30*24*60, // max: 30 days
342 50); // num_buckets
343 }
David Zeuthenb281f072014-04-02 10:20:19 -0700344
345 metric = metrics::kMetricAttemptConnectionType;
346 LOG(INFO) << "Uploading " << static_cast<int>(connection_type)
347 << " for metric " << metric;
348 system_state->metrics_lib()->SendEnumToUMA(
349 metric,
350 static_cast<int>(connection_type),
351 static_cast<int>(ConnectionType::kNumConstants));
David Zeuthen33bae492014-02-25 16:16:18 -0800352}
353
354
355void ReportSuccessfulUpdateMetrics(
356 SystemState *system_state,
357 int attempt_count,
358 int updates_abandoned_count,
359 PayloadType payload_type,
360 int64_t payload_size,
361 int64_t num_bytes_downloaded[kNumDownloadSources],
362 int download_overhead_percentage,
363 base::TimeDelta total_duration,
364 int reboot_count,
365 int url_switch_count) {
366 string metric;
367 int64_t mbs;
368
369 metric = kMetricSuccessfulUpdatePayloadSizeMiB;
370 mbs = payload_size / kNumBytesInOneMiB;
371 LOG(INFO) << "Uploading " << mbs << " (MiBs) for metric " << metric;
372 system_state->metrics_lib()->SendToUMA(metric,
373 mbs,
374 0, // min: 0 MiB
375 1024, // max: 1024 MiB = 1 GiB
376 50); // num_buckets
377
378 int64_t total_bytes = 0;
379 int download_sources_used = 0;
380 for (int i = 0; i < kNumDownloadSources + 1; i++) {
381 DownloadSource source = static_cast<DownloadSource>(i);
382
383 // Only consider this download source (and send byte counts) as
384 // having been used if we downloaded a non-trivial amount of bytes
Alex Vakulenko072359c2014-07-18 11:41:07 -0700385 // (e.g. at least 1 MiB) that contributed to the
David Zeuthen33bae492014-02-25 16:16:18 -0800386 // update. Otherwise we're going to end up with a lot of zero-byte
387 // events in the histogram.
388
389 metric = metrics::kMetricSuccessfulUpdateBytesDownloadedMiB;
390 if (i < kNumDownloadSources) {
391 metric += utils::ToString(source);
392 mbs = num_bytes_downloaded[i] / kNumBytesInOneMiB;
393 total_bytes += num_bytes_downloaded[i];
394 if (mbs > 0)
395 download_sources_used |= (1 << i);
396 } else {
397 mbs = total_bytes / kNumBytesInOneMiB;
398 }
399
400 if (mbs > 0) {
401 LOG(INFO) << "Uploading " << mbs << " (MiBs) for metric " << metric;
402 system_state->metrics_lib()->SendToUMA(metric,
403 mbs,
404 0, // min: 0 MiB
405 1024, // max: 1024 MiB = 1 GiB
406 50); // num_buckets
407 }
408 }
409
410 metric = metrics::kMetricSuccessfulUpdateDownloadSourcesUsed;
411 LOG(INFO) << "Uploading 0x" << std::hex << download_sources_used
412 << " (bit flags) for metric " << metric;
413 system_state->metrics_lib()->SendToUMA(
414 metric,
415 download_sources_used,
416 0, // min
417 (1 << kNumDownloadSources) - 1, // max
418 1 << kNumDownloadSources); // num_buckets
419
420 metric = metrics::kMetricSuccessfulUpdateDownloadOverheadPercentage;
421 LOG(INFO) << "Uploading " << download_overhead_percentage
422 << "% for metric " << metric;
423 system_state->metrics_lib()->SendToUMA(metric,
424 download_overhead_percentage,
425 0, // min: 0% overhead
426 1000, // max: 1000% overhead
427 50); // num_buckets
428
429 metric = metrics::kMetricSuccessfulUpdateUrlSwitchCount;
430 LOG(INFO) << "Uploading " << url_switch_count
431 << " (count) for metric " << metric;
432 system_state->metrics_lib()->SendToUMA(metric,
433 url_switch_count,
434 0, // min: 0 URL switches
435 49, // max: 49 URL switches
436 50); // num_buckets
437
438 metric = metrics::kMetricSuccessfulUpdateTotalDurationMinutes;
439 LOG(INFO) << "Uploading " << utils::FormatTimeDelta(total_duration)
440 << " for metric " << metric;
441 system_state->metrics_lib()->SendToUMA(
442 metric,
443 static_cast<int>(total_duration.InMinutes()),
444 0, // min: 0 min
445 365*24*60, // max: 365 days ~= 1 year
446 50); // num_buckets
447
448 metric = metrics::kMetricSuccessfulUpdateRebootCount;
449 LOG(INFO) << "Uploading reboot count of " << reboot_count << " for metric "
450 << metric;
451 system_state->metrics_lib()->SendToUMA(metric,
452 reboot_count,
453 0, // min: 0 reboots
454 49, // max: 49 reboots
455 50); // num_buckets
456
457 metric = metrics::kMetricSuccessfulUpdatePayloadType;
458 system_state->metrics_lib()->SendEnumToUMA(metric,
459 payload_type,
460 kNumPayloadTypes);
461 LOG(INFO) << "Uploading " << utils::ToString(payload_type)
462 << " for metric " << metric;
463
464 metric = metrics::kMetricSuccessfulUpdateAttemptCount;
465 system_state->metrics_lib()->SendToUMA(metric,
466 attempt_count,
467 1, // min: 1 attempt
468 50, // max: 50 attempts
469 50); // num_buckets
470 LOG(INFO) << "Uploading " << attempt_count
471 << " for metric " << metric;
472
473 metric = metrics::kMetricSuccessfulUpdateUpdatesAbandonedCount;
474 LOG(INFO) << "Uploading " << updates_abandoned_count
475 << " (count) for metric " << metric;
476 system_state->metrics_lib()->SendToUMA(metric,
477 updates_abandoned_count,
478 0, // min: 0 counts
479 49, // max: 49 counts
480 50); // num_buckets
481}
482
David Zeuthen96197df2014-04-16 12:22:39 -0700483void ReportRollbackMetrics(SystemState *system_state,
484 RollbackResult result) {
485 string metric;
486 int value;
487
488 metric = metrics::kMetricRollbackResult;
489 value = static_cast<int>(result);
490 LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
491 system_state->metrics_lib()->SendEnumToUMA(
492 metric,
493 value,
494 static_cast<int>(metrics::RollbackResult::kNumConstants));
495}
496
David Zeuthen33bae492014-02-25 16:16:18 -0800497} // namespace metrics
498
499} // namespace chromeos_update_engine