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