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