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