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