blob: b784b611dbdd1a1d20f7f96e00c492d479bd5f93 [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";
42const char kMetricAttemptDurationMinutes[] =
43 "UpdateEngine.Attempt.DurationMinutes";
44const char kMetricAttemptDurationUptimeMinutes[] =
45 "UpdateEngine.Attempt.DurationUptimeMinutes";
46const char kMetricAttemptTimeSinceLastAttemptMinutes[] =
47 "UpdateEngine.Attempt.TimeSinceLastAttemptMinutes";
48const char kMetricAttemptTimeSinceLastAttemptUptimeMinutes[] =
49 "UpdateEngine.Attempt.TimeSinceLastAttemptUptimeMinutes";
50const char kMetricAttemptPayloadBytesOffset[] =
51 "UpdateEngine.Attempt.PayloadBytesOffset";
52const char kMetricAttemptPayloadBytesNeeded[] =
53 "UpdateEngine.Attempt.PayloadBytesNeeded";
54const char kMetricAttemptPayloadBytesDownloadedMiB[] =
55 "UpdateEngine.Attempt.PayloadBytesDownloadedMiB";
56const char kMetricAttemptPayloadDownloadSpeedKBps[] =
57 "UpdateEngine.Attempt.PayloadDownloadSpeedKBps";
58const char kMetricAttemptDownloadSource[] =
59 "UpdateEngine.Attempt.DownloadSource";
60const char kMetricAttemptResult[] =
61 "UpdateEngine.Attempt.Result";
62const char kMetricAttemptInternalErrorCode[] =
63 "UpdateEngine.Attempt.InternalErrorCode";
64const char kMetricAttemptDownloadErrorCode[] =
65 "UpdateEngine.Attempt.DownloadErrorCode";
66
67// UpdateEngine.SuccessfulUpdate.* metrics.
68const char kMetricSuccessfulUpdateAttemptCount[] =
69 "UpdateEngine.SuccessfulUpdate.AttemptCount";
70const char kMetricSuccessfulUpdateBytesDownloadedMiB[] =
71 "UpdateEngine.SuccessfulUpdate.BytesDownloadedMiB";
72const char kMetricSuccessfulUpdateDownloadOverheadPercentage[] =
73 "UpdateEngine.SuccessfulUpdate.DownloadOverheadPercentage";
74const char kMetricSuccessfulUpdateDownloadSourcesUsed[] =
75 "UpdateEngine.SuccessfulUpdate.DownloadSourcesUsed";
76const char kMetricSuccessfulUpdatePayloadType[] =
77 "UpdateEngine.SuccessfulUpdate.PayloadType";
78const char kMetricSuccessfulUpdatePayloadSizeMiB[] =
79 "UpdateEngine.SuccessfulUpdate.PayloadSizeMiB";
80const char kMetricSuccessfulUpdateRebootCount[] =
81 "UpdateEngine.SuccessfulUpdate.RebootCount";
82const char kMetricSuccessfulUpdateTotalDurationMinutes[] =
83 "UpdateEngine.SuccessfulUpdate.TotalDurationMinutes";
84const char kMetricSuccessfulUpdateUpdatesAbandonedCount[] =
85 "UpdateEngine.SuccessfulUpdate.UpdatesAbandonedCount";
86const char kMetricSuccessfulUpdateUrlSwitchCount[] =
87 "UpdateEngine.SuccessfulUpdate.UrlSwitchCount";
88
89// UpdateEngine.* metrics.
90const char kMetricFailedUpdateCount[] = "UpdateEngine.FailedUpdateCount";
91const char kMetricInstallDateProvisioningSource[] =
92 "UpdateEngine.InstallDateProvisioningSource";
93const char kMetricTimeToRebootMinutes[] =
94 "UpdateEngine.TimeToRebootMinutes";
95
96void ReportDailyMetrics(SystemState *system_state,
97 base::TimeDelta os_age) {
98 string metric = metrics::kMetricDailyOSAgeDays;
99 LOG(INFO) << "Uploading " << utils::FormatTimeDelta(os_age)
100 << " for metric " << metric;
101 system_state->metrics_lib()->SendToUMA(
102 metric,
103 static_cast<int>(os_age.InDays()),
104 0, // min: 0 days
105 6*30, // max: 6 months (approx)
106 50); // num_buckets
107}
108
109void ReportUpdateCheckMetrics(SystemState *system_state,
110 CheckResult result,
111 CheckReaction reaction,
112 DownloadErrorCode download_error_code) {
113 string metric;
114 int value;
115 int max_value;
116
117 if (result != metrics::CheckResult::kUnset) {
118 metric = metrics::kMetricCheckResult;
119 value = static_cast<int>(result);
120 max_value = static_cast<int>(metrics::CheckResult::kNumConstants) - 1;
121 LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
122 system_state->metrics_lib()->SendEnumToUMA(metric, value, max_value);
123 }
124 if (reaction != metrics::CheckReaction::kUnset) {
125 metric = metrics::kMetricCheckReaction;
126 value = static_cast<int>(reaction);
127 max_value = static_cast<int>(metrics::CheckReaction::kNumConstants) - 1;
128 LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
129 system_state->metrics_lib()->SendEnumToUMA(metric, value, max_value);
130 }
131 if (download_error_code != metrics::DownloadErrorCode::kUnset) {
132 metric = metrics::kMetricCheckDownloadErrorCode;
133 value = static_cast<int>(download_error_code);
134 max_value = static_cast<int>(metrics::DownloadErrorCode::kNumConstants) - 1;
135 LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
136 system_state->metrics_lib()->SendEnumToUMA(metric, value, max_value);
137 }
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,
183 DownloadErrorCode payload_download_error_code) {
184 string metric;
185
186 metric = metrics::kMetricAttemptNumber;
187 LOG(INFO) << "Uploading " << attempt_number << " for metric " << metric;
188 system_state->metrics_lib()->SendToUMA(metric,
189 attempt_number,
190 0, // min: 0 attempts
191 49, // max: 49 attempts
192 50); // num_buckets
193
194 metric = metrics::kMetricAttemptPayloadType;
195 LOG(INFO) << "Uploading " << utils::ToString(payload_type)
196 << " for metric " << metric;
197 system_state->metrics_lib()->SendEnumToUMA(metric,
198 payload_type,
199 kNumPayloadTypes);
200
201 metric = metrics::kMetricAttemptDurationMinutes;
202 LOG(INFO) << "Uploading " << utils::FormatTimeDelta(duration)
203 << " for metric " << metric;
204 system_state->metrics_lib()->SendToUMA(metric,
205 duration.InMinutes(),
206 0, // min: 0 min
207 10*24*60, // max: 10 days
208 50); // num_buckets
209
210 metric = metrics::kMetricAttemptDurationUptimeMinutes;
211 LOG(INFO) << "Uploading " << utils::FormatTimeDelta(duration_uptime)
212 << " for metric " << metric;
213 system_state->metrics_lib()->SendToUMA(metric,
214 duration_uptime.InMinutes(),
215 0, // min: 0 min
216 10*24*60, // max: 10 days
217 50); // num_buckets
218
219 metric = metrics::kMetricAttemptPayloadSizeMiB;
220 int64_t payload_size_mib = payload_size / kNumBytesInOneMiB;
221 LOG(INFO) << "Uploading " << payload_size_mib << " for metric " << metric;
222 system_state->metrics_lib()->SendToUMA(metric,
223 payload_size_mib,
224 0, // min: 0 MiB
225 1024, // max: 1024 MiB = 1 GiB
226 50); // num_buckets
227
228 metric = metrics::kMetricAttemptPayloadBytesDownloadedMiB;
229 int64_t payload_bytes_downloaded_mib =
230 payload_bytes_downloaded / kNumBytesInOneMiB;
231 LOG(INFO) << "Uploading " << payload_bytes_downloaded_mib
232 << " for metric " << metric;
233 system_state->metrics_lib()->SendToUMA(metric,
234 payload_bytes_downloaded_mib,
235 0, // min: 0 MiB
236 1024, // max: 1024 MiB = 1 GiB
237 50); // num_buckets
238
239 metric = metrics::kMetricAttemptPayloadDownloadSpeedKBps;
240 int64_t payload_download_speed_kbps = payload_download_speed_bps / 1000;
241 LOG(INFO) << "Uploading " << payload_download_speed_kbps
242 << " for metric " << metric;
243 system_state->metrics_lib()->SendToUMA(metric,
244 payload_download_speed_kbps,
245 0, // min: 0 kB/s
246 10*1000, // max: 10000 kB/s = 10 MB/s
247 50); // num_buckets
248
249 metric = metrics::kMetricAttemptDownloadSource;
250 LOG(INFO) << "Uploading " << download_source
251 << " for metric " << metric;
252 system_state->metrics_lib()->SendEnumToUMA(metric,
253 download_source,
254 kNumDownloadSources);
255
256 metric = metrics::kMetricAttemptResult;
257 LOG(INFO) << "Uploading " << static_cast<int>(attempt_result)
258 << " for metric " << metric;
259 system_state->metrics_lib()->SendEnumToUMA(
260 metric,
261 static_cast<int>(attempt_result),
262 static_cast<int>(AttemptResult::kNumConstants));
263
264 if (internal_error_code != kErrorCodeSuccess) {
265 metric = metrics::kMetricAttemptInternalErrorCode;
266 LOG(INFO) << "Uploading " << internal_error_code
267 << " for metric " << metric;
268 system_state->metrics_lib()->SendEnumToUMA(
269 metric,
270 internal_error_code,
271 kErrorCodeUmaReportedMax);
272 }
273
274 if (payload_download_error_code != DownloadErrorCode::kUnset) {
275 metric = metrics::kMetricAttemptDownloadErrorCode;
276 LOG(INFO) << "Uploading " << static_cast<int>(payload_download_error_code)
277 << " for metric " << metric;
278 system_state->metrics_lib()->SendEnumToUMA(
279 metric,
280 static_cast<int>(payload_download_error_code),
281 static_cast<int>(DownloadErrorCode::kNumConstants));
282 }
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 }
314}
315
316
317void ReportSuccessfulUpdateMetrics(
318 SystemState *system_state,
319 int attempt_count,
320 int updates_abandoned_count,
321 PayloadType payload_type,
322 int64_t payload_size,
323 int64_t num_bytes_downloaded[kNumDownloadSources],
324 int download_overhead_percentage,
325 base::TimeDelta total_duration,
326 int reboot_count,
327 int url_switch_count) {
328 string metric;
329 int64_t mbs;
330
331 metric = kMetricSuccessfulUpdatePayloadSizeMiB;
332 mbs = payload_size / kNumBytesInOneMiB;
333 LOG(INFO) << "Uploading " << mbs << " (MiBs) for metric " << metric;
334 system_state->metrics_lib()->SendToUMA(metric,
335 mbs,
336 0, // min: 0 MiB
337 1024, // max: 1024 MiB = 1 GiB
338 50); // num_buckets
339
340 int64_t total_bytes = 0;
341 int download_sources_used = 0;
342 for (int i = 0; i < kNumDownloadSources + 1; i++) {
343 DownloadSource source = static_cast<DownloadSource>(i);
344
345 // Only consider this download source (and send byte counts) as
346 // having been used if we downloaded a non-trivial amount of bytes
347 // (e.g. at least 1 MiB) that contributed to the the
348 // update. Otherwise we're going to end up with a lot of zero-byte
349 // events in the histogram.
350
351 metric = metrics::kMetricSuccessfulUpdateBytesDownloadedMiB;
352 if (i < kNumDownloadSources) {
353 metric += utils::ToString(source);
354 mbs = num_bytes_downloaded[i] / kNumBytesInOneMiB;
355 total_bytes += num_bytes_downloaded[i];
356 if (mbs > 0)
357 download_sources_used |= (1 << i);
358 } else {
359 mbs = total_bytes / kNumBytesInOneMiB;
360 }
361
362 if (mbs > 0) {
363 LOG(INFO) << "Uploading " << mbs << " (MiBs) for metric " << metric;
364 system_state->metrics_lib()->SendToUMA(metric,
365 mbs,
366 0, // min: 0 MiB
367 1024, // max: 1024 MiB = 1 GiB
368 50); // num_buckets
369 }
370 }
371
372 metric = metrics::kMetricSuccessfulUpdateDownloadSourcesUsed;
373 LOG(INFO) << "Uploading 0x" << std::hex << download_sources_used
374 << " (bit flags) for metric " << metric;
375 system_state->metrics_lib()->SendToUMA(
376 metric,
377 download_sources_used,
378 0, // min
379 (1 << kNumDownloadSources) - 1, // max
380 1 << kNumDownloadSources); // num_buckets
381
382 metric = metrics::kMetricSuccessfulUpdateDownloadOverheadPercentage;
383 LOG(INFO) << "Uploading " << download_overhead_percentage
384 << "% for metric " << metric;
385 system_state->metrics_lib()->SendToUMA(metric,
386 download_overhead_percentage,
387 0, // min: 0% overhead
388 1000, // max: 1000% overhead
389 50); // num_buckets
390
391 metric = metrics::kMetricSuccessfulUpdateUrlSwitchCount;
392 LOG(INFO) << "Uploading " << url_switch_count
393 << " (count) for metric " << metric;
394 system_state->metrics_lib()->SendToUMA(metric,
395 url_switch_count,
396 0, // min: 0 URL switches
397 49, // max: 49 URL switches
398 50); // num_buckets
399
400 metric = metrics::kMetricSuccessfulUpdateTotalDurationMinutes;
401 LOG(INFO) << "Uploading " << utils::FormatTimeDelta(total_duration)
402 << " for metric " << metric;
403 system_state->metrics_lib()->SendToUMA(
404 metric,
405 static_cast<int>(total_duration.InMinutes()),
406 0, // min: 0 min
407 365*24*60, // max: 365 days ~= 1 year
408 50); // num_buckets
409
410 metric = metrics::kMetricSuccessfulUpdateRebootCount;
411 LOG(INFO) << "Uploading reboot count of " << reboot_count << " for metric "
412 << metric;
413 system_state->metrics_lib()->SendToUMA(metric,
414 reboot_count,
415 0, // min: 0 reboots
416 49, // max: 49 reboots
417 50); // num_buckets
418
419 metric = metrics::kMetricSuccessfulUpdatePayloadType;
420 system_state->metrics_lib()->SendEnumToUMA(metric,
421 payload_type,
422 kNumPayloadTypes);
423 LOG(INFO) << "Uploading " << utils::ToString(payload_type)
424 << " for metric " << metric;
425
426 metric = metrics::kMetricSuccessfulUpdateAttemptCount;
427 system_state->metrics_lib()->SendToUMA(metric,
428 attempt_count,
429 1, // min: 1 attempt
430 50, // max: 50 attempts
431 50); // num_buckets
432 LOG(INFO) << "Uploading " << attempt_count
433 << " for metric " << metric;
434
435 metric = metrics::kMetricSuccessfulUpdateUpdatesAbandonedCount;
436 LOG(INFO) << "Uploading " << updates_abandoned_count
437 << " (count) for metric " << metric;
438 system_state->metrics_lib()->SendToUMA(metric,
439 updates_abandoned_count,
440 0, // min: 0 counts
441 49, // max: 49 counts
442 50); // num_buckets
443}
444
445} // namespace metrics
446
447} // namespace chromeos_update_engine