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