1 //
2 // Copyright (C) 2014 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "update_engine/metrics_reporter_omaha.h"
18 
19 #include <memory>
20 
21 #include <base/logging.h>
22 #include <base/strings/string_number_conversions.h>
23 #include <metrics/metrics_library.h>
24 
25 #include "update_engine/common/clock_interface.h"
26 #include "update_engine/common/constants.h"
27 #include "update_engine/common/prefs_interface.h"
28 #include "update_engine/common/utils.h"
29 #include "update_engine/metrics_utils.h"
30 #include "update_engine/omaha_request_params.h"
31 #include "update_engine/system_state.h"
32 
33 using std::string;
34 
35 namespace chromeos_update_engine {
36 
37 namespace metrics {
38 
39 // UpdateEngine.Daily.* metrics.
40 const char kMetricDailyOSAgeDays[] = "UpdateEngine.Daily.OSAgeDays";
41 
42 // UpdateEngine.Check.* metrics.
43 const char kMetricCheckDownloadErrorCode[] =
44     "UpdateEngine.Check.DownloadErrorCode";
45 const char kMetricCheckReaction[] = "UpdateEngine.Check.Reaction";
46 const char kMetricCheckResult[] = "UpdateEngine.Check.Result";
47 const char kMetricCheckTargetVersion[] = "UpdateEngine.Check.TargetVersion";
48 const char kMetricCheckRollbackTargetVersion[] =
49     "UpdateEngine.Check.RollbackTargetVersion";
50 const char kMetricCheckTimeSinceLastCheckMinutes[] =
51     "UpdateEngine.Check.TimeSinceLastCheckMinutes";
52 const char kMetricCheckTimeSinceLastCheckUptimeMinutes[] =
53     "UpdateEngine.Check.TimeSinceLastCheckUptimeMinutes";
54 
55 // UpdateEngine.Attempt.* metrics.
56 const char kMetricAttemptNumber[] = "UpdateEngine.Attempt.Number";
57 const char kMetricAttemptPayloadType[] = "UpdateEngine.Attempt.PayloadType";
58 const char kMetricAttemptPayloadSizeMiB[] =
59     "UpdateEngine.Attempt.PayloadSizeMiB";
60 const char kMetricAttemptConnectionType[] =
61     "UpdateEngine.Attempt.ConnectionType";
62 const char kMetricAttemptDurationMinutes[] =
63     "UpdateEngine.Attempt.DurationMinutes";
64 const char kMetricAttemptDurationUptimeMinutes[] =
65     "UpdateEngine.Attempt.DurationUptimeMinutes";
66 const char kMetricAttemptTimeSinceLastAttemptMinutes[] =
67     "UpdateEngine.Attempt.TimeSinceLastAttemptMinutes";
68 const char kMetricAttemptTimeSinceLastAttemptUptimeMinutes[] =
69     "UpdateEngine.Attempt.TimeSinceLastAttemptUptimeMinutes";
70 const char kMetricAttemptPayloadBytesDownloadedMiB[] =
71     "UpdateEngine.Attempt.PayloadBytesDownloadedMiB";
72 const char kMetricAttemptPayloadDownloadSpeedKBps[] =
73     "UpdateEngine.Attempt.PayloadDownloadSpeedKBps";
74 const char kMetricAttemptDownloadSource[] =
75     "UpdateEngine.Attempt.DownloadSource";
76 const char kMetricAttemptResult[] = "UpdateEngine.Attempt.Result";
77 const char kMetricAttemptInternalErrorCode[] =
78     "UpdateEngine.Attempt.InternalErrorCode";
79 const char kMetricAttemptDownloadErrorCode[] =
80     "UpdateEngine.Attempt.DownloadErrorCode";
81 
82 // UpdateEngine.SuccessfulUpdate.* metrics.
83 const char kMetricSuccessfulUpdateAttemptCount[] =
84     "UpdateEngine.SuccessfulUpdate.AttemptCount";
85 const char kMetricSuccessfulUpdateBytesDownloadedMiB[] =
86     "UpdateEngine.SuccessfulUpdate.BytesDownloadedMiB";
87 const char kMetricSuccessfulUpdateDownloadOverheadPercentage[] =
88     "UpdateEngine.SuccessfulUpdate.DownloadOverheadPercentage";
89 const char kMetricSuccessfulUpdateDownloadSourcesUsed[] =
90     "UpdateEngine.SuccessfulUpdate.DownloadSourcesUsed";
91 const char kMetricSuccessfulUpdateDurationFromSeenDays[] =
92     "UpdateEngine.SuccessfulUpdate.DurationFromSeenDays.NoTimeRestriction";
93 const char kMetricSuccessfulUpdateDurationFromSeenTimeRestrictedDays[] =
94     "UpdateEngine.SuccessfulUpdate.DurationFromSeenDays.TimeRestricted";
95 const char kMetricSuccessfulUpdatePayloadType[] =
96     "UpdateEngine.SuccessfulUpdate.PayloadType";
97 const char kMetricSuccessfulUpdatePayloadSizeMiB[] =
98     "UpdateEngine.SuccessfulUpdate.PayloadSizeMiB";
99 const char kMetricSuccessfulUpdateRebootCount[] =
100     "UpdateEngine.SuccessfulUpdate.RebootCount";
101 const char kMetricSuccessfulUpdateTotalDurationMinutes[] =
102     "UpdateEngine.SuccessfulUpdate.TotalDurationMinutes";
103 const char kMetricSuccessfulUpdateTotalDurationUptimeMinutes[] =
104     "UpdateEngine.SuccessfulUpdate.TotalDurationUptimeMinutes";
105 const char kMetricSuccessfulUpdateUpdatesAbandonedCount[] =
106     "UpdateEngine.SuccessfulUpdate.UpdatesAbandonedCount";
107 const char kMetricSuccessfulUpdateUrlSwitchCount[] =
108     "UpdateEngine.SuccessfulUpdate.UrlSwitchCount";
109 
110 // UpdateEngine.Rollback.* metric.
111 const char kMetricRollbackResult[] = "UpdateEngine.Rollback.Result";
112 
113 // UpdateEngine.EnterpriseRollback.* metrics.
114 const char kMetricEnterpriseRollbackFailure[] =
115     "UpdateEngine.EnterpriseRollback.Failure";
116 const char kMetricEnterpriseRollbackSuccess[] =
117     "UpdateEngine.EnterpriseRollback.Success";
118 
119 // UpdateEngine.CertificateCheck.* metrics.
120 const char kMetricCertificateCheckUpdateCheck[] =
121     "UpdateEngine.CertificateCheck.UpdateCheck";
122 const char kMetricCertificateCheckDownload[] =
123     "UpdateEngine.CertificateCheck.Download";
124 
125 // UpdateEngine.KernelKey.* metrics.
126 const char kMetricKernelMinVersion[] = "UpdateEngine.KernelKey.MinVersion";
127 const char kMetricKernelMaxRollforwardVersion[] =
128     "UpdateEngine.KernelKey.MaxRollforwardVersion";
129 const char kMetricKernelMaxRollforwardSetSuccess[] =
130     "UpdateEngine.KernelKey.MaxRollforwardSetSuccess";
131 
132 // UpdateEngine.* metrics.
133 const char kMetricFailedUpdateCount[] = "UpdateEngine.FailedUpdateCount";
134 const char kMetricInstallDateProvisioningSource[] =
135     "UpdateEngine.InstallDateProvisioningSource";
136 const char kMetricTimeToRebootMinutes[] = "UpdateEngine.TimeToRebootMinutes";
137 
138 std::unique_ptr<MetricsReporterInterface> CreateMetricsReporter() {
139   return std::make_unique<MetricsReporterOmaha>();
140 }
141 
142 }  // namespace metrics
143 
144 MetricsReporterOmaha::MetricsReporterOmaha()
145     : metrics_lib_(new MetricsLibrary()) {}
146 
147 void MetricsReporterOmaha::Initialize() {
148   metrics_lib_->Init();
149 }
150 
151 void MetricsReporterOmaha::ReportDailyMetrics(base::TimeDelta os_age) {
152   string metric = metrics::kMetricDailyOSAgeDays;
153   LOG(INFO) << "Uploading " << utils::FormatTimeDelta(os_age) << " for metric "
154             << metric;
155   metrics_lib_->SendToUMA(metric,
156                           static_cast<int>(os_age.InDays()),
157                           0,       // min: 0 days
158                           6 * 30,  // max: 6 months (approx)
159                           50);     // num_buckets
160 }
161 
162 void MetricsReporterOmaha::ReportUpdateCheckMetrics(
163     SystemState* system_state,
164     metrics::CheckResult result,
165     metrics::CheckReaction reaction,
166     metrics::DownloadErrorCode download_error_code) {
167   string metric;
168   int value;
169   int max_value;
170 
171   if (result != metrics::CheckResult::kUnset) {
172     metric = metrics::kMetricCheckResult;
173     value = static_cast<int>(result);
174     max_value = static_cast<int>(metrics::CheckResult::kNumConstants) - 1;
175     LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
176     metrics_lib_->SendEnumToUMA(metric, value, max_value);
177   }
178   if (reaction != metrics::CheckReaction::kUnset) {
179     metric = metrics::kMetricCheckReaction;
180     value = static_cast<int>(reaction);
181     max_value = static_cast<int>(metrics::CheckReaction::kNumConstants) - 1;
182     LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
183     metrics_lib_->SendEnumToUMA(metric, value, max_value);
184   }
185   if (download_error_code != metrics::DownloadErrorCode::kUnset) {
186     metric = metrics::kMetricCheckDownloadErrorCode;
187     value = static_cast<int>(download_error_code);
188     LOG(INFO) << "Sending " << value << " for metric " << metric << " (sparse)";
189     metrics_lib_->SendSparseToUMA(metric, value);
190   }
191 
192   base::TimeDelta time_since_last;
193   if (metrics_utils::WallclockDurationHelper(
194           system_state,
195           kPrefsMetricsCheckLastReportingTime,
196           &time_since_last)) {
197     metric = metrics::kMetricCheckTimeSinceLastCheckMinutes;
198     LOG(INFO) << "Sending " << utils::FormatTimeDelta(time_since_last)
199               << " for metric " << metric;
200     metrics_lib_->SendToUMA(metric,
201                             time_since_last.InMinutes(),
202                             0,             // min: 0 min
203                             30 * 24 * 60,  // max: 30 days
204                             50);           // num_buckets
205   }
206 
207   base::TimeDelta uptime_since_last;
208   static int64_t uptime_since_last_storage = 0;
209   if (metrics_utils::MonotonicDurationHelper(
210           system_state, &uptime_since_last_storage, &uptime_since_last)) {
211     metric = metrics::kMetricCheckTimeSinceLastCheckUptimeMinutes;
212     LOG(INFO) << "Sending " << utils::FormatTimeDelta(uptime_since_last)
213               << " for metric " << metric;
214     metrics_lib_->SendToUMA(metric,
215                             uptime_since_last.InMinutes(),
216                             0,             // min: 0 min
217                             30 * 24 * 60,  // max: 30 days
218                             50);           // num_buckets
219   }
220 
221   // First section of target version specified for the update.
222   if (system_state && system_state->request_params()) {
223     string target_version =
224         system_state->request_params()->target_version_prefix();
225     value = utils::VersionPrefix(target_version);
226     if (value != 0) {
227       metric = metrics::kMetricCheckTargetVersion;
228       LOG(INFO) << "Sending " << value << " for metric " << metric
229                 << " (sparse)";
230       metrics_lib_->SendSparseToUMA(metric, value);
231       if (system_state->request_params()->rollback_allowed()) {
232         metric = metrics::kMetricCheckRollbackTargetVersion;
233         LOG(INFO) << "Sending " << value << " for metric " << metric
234                   << " (sparse)";
235         metrics_lib_->SendSparseToUMA(metric, value);
236       }
237     }
238   }
239 }
240 
241 void MetricsReporterOmaha::ReportAbnormallyTerminatedUpdateAttemptMetrics() {
242   string metric = metrics::kMetricAttemptResult;
243   metrics::AttemptResult attempt_result =
244       metrics::AttemptResult::kAbnormalTermination;
245 
246   LOG(INFO) << "Uploading " << static_cast<int>(attempt_result)
247             << " for metric " << metric;
248   metrics_lib_->SendEnumToUMA(
249       metric,
250       static_cast<int>(attempt_result),
251       static_cast<int>(metrics::AttemptResult::kNumConstants));
252 }
253 
254 void MetricsReporterOmaha::ReportUpdateAttemptMetrics(
255     SystemState* system_state,
256     int attempt_number,
257     PayloadType payload_type,
258     base::TimeDelta duration,
259     base::TimeDelta duration_uptime,
260     int64_t payload_size,
261     metrics::AttemptResult attempt_result,
262     ErrorCode internal_error_code) {
263   string metric = metrics::kMetricAttemptNumber;
264   LOG(INFO) << "Uploading " << attempt_number << " for metric " << metric;
265   metrics_lib_->SendToUMA(metric,
266                           attempt_number,
267                           0,    // min: 0 attempts
268                           49,   // max: 49 attempts
269                           50);  // num_buckets
270 
271   metric = metrics::kMetricAttemptPayloadType;
272   LOG(INFO) << "Uploading " << utils::ToString(payload_type) << " for metric "
273             << metric;
274   metrics_lib_->SendEnumToUMA(metric, payload_type, kNumPayloadTypes);
275 
276   metric = metrics::kMetricAttemptDurationMinutes;
277   LOG(INFO) << "Uploading " << utils::FormatTimeDelta(duration)
278             << " for metric " << metric;
279   metrics_lib_->SendToUMA(metric,
280                           duration.InMinutes(),
281                           0,             // min: 0 min
282                           10 * 24 * 60,  // max: 10 days
283                           50);           // num_buckets
284 
285   metric = metrics::kMetricAttemptDurationUptimeMinutes;
286   LOG(INFO) << "Uploading " << utils::FormatTimeDelta(duration_uptime)
287             << " for metric " << metric;
288   metrics_lib_->SendToUMA(metric,
289                           duration_uptime.InMinutes(),
290                           0,             // min: 0 min
291                           10 * 24 * 60,  // max: 10 days
292                           50);           // num_buckets
293 
294   metric = metrics::kMetricAttemptPayloadSizeMiB;
295   int64_t payload_size_mib = payload_size / kNumBytesInOneMiB;
296   LOG(INFO) << "Uploading " << payload_size_mib << " for metric " << metric;
297   metrics_lib_->SendToUMA(metric,
298                           payload_size_mib,
299                           0,     // min: 0 MiB
300                           1024,  // max: 1024 MiB = 1 GiB
301                           50);   // num_buckets
302 
303   metric = metrics::kMetricAttemptResult;
304   LOG(INFO) << "Uploading " << static_cast<int>(attempt_result)
305             << " for metric " << metric;
306   metrics_lib_->SendEnumToUMA(
307       metric,
308       static_cast<int>(attempt_result),
309       static_cast<int>(metrics::AttemptResult::kNumConstants));
310 
311   if (internal_error_code != ErrorCode::kSuccess) {
312     ReportInternalErrorCode(internal_error_code);
313   }
314 
315   base::TimeDelta time_since_last;
316   if (metrics_utils::WallclockDurationHelper(
317           system_state,
318           kPrefsMetricsAttemptLastReportingTime,
319           &time_since_last)) {
320     metric = metrics::kMetricAttemptTimeSinceLastAttemptMinutes;
321     LOG(INFO) << "Sending " << utils::FormatTimeDelta(time_since_last)
322               << " for metric " << metric;
323     metrics_lib_->SendToUMA(metric,
324                             time_since_last.InMinutes(),
325                             0,             // min: 0 min
326                             30 * 24 * 60,  // max: 30 days
327                             50);           // num_buckets
328   }
329 
330   static int64_t uptime_since_last_storage = 0;
331   base::TimeDelta uptime_since_last;
332   if (metrics_utils::MonotonicDurationHelper(
333           system_state, &uptime_since_last_storage, &uptime_since_last)) {
334     metric = metrics::kMetricAttemptTimeSinceLastAttemptUptimeMinutes;
335     LOG(INFO) << "Sending " << utils::FormatTimeDelta(uptime_since_last)
336               << " for metric " << metric;
337     metrics_lib_->SendToUMA(metric,
338                             uptime_since_last.InMinutes(),
339                             0,             // min: 0 min
340                             30 * 24 * 60,  // max: 30 days
341                             50);           // num_buckets
342   }
343 }
344 
345 void MetricsReporterOmaha::ReportUpdateAttemptDownloadMetrics(
346     int64_t payload_bytes_downloaded,
347     int64_t payload_download_speed_bps,
348     DownloadSource download_source,
349     metrics::DownloadErrorCode payload_download_error_code,
350     metrics::ConnectionType connection_type) {
351   string metric = metrics::kMetricAttemptPayloadBytesDownloadedMiB;
352   int64_t payload_bytes_downloaded_mib =
353       payload_bytes_downloaded / kNumBytesInOneMiB;
354   LOG(INFO) << "Uploading " << payload_bytes_downloaded_mib << " for metric "
355             << metric;
356   metrics_lib_->SendToUMA(metric,
357                           payload_bytes_downloaded_mib,
358                           0,     // min: 0 MiB
359                           1024,  // max: 1024 MiB = 1 GiB
360                           50);   // num_buckets
361 
362   metric = metrics::kMetricAttemptPayloadDownloadSpeedKBps;
363   int64_t payload_download_speed_kbps = payload_download_speed_bps / 1000;
364   LOG(INFO) << "Uploading " << payload_download_speed_kbps << " for metric "
365             << metric;
366   metrics_lib_->SendToUMA(metric,
367                           payload_download_speed_kbps,
368                           0,          // min: 0 kB/s
369                           10 * 1000,  // max: 10000 kB/s = 10 MB/s
370                           50);        // num_buckets
371 
372   metric = metrics::kMetricAttemptDownloadSource;
373   LOG(INFO) << "Uploading " << download_source << " for metric " << metric;
374   metrics_lib_->SendEnumToUMA(metric, download_source, kNumDownloadSources);
375 
376   if (payload_download_error_code != metrics::DownloadErrorCode::kUnset) {
377     metric = metrics::kMetricAttemptDownloadErrorCode;
378     LOG(INFO) << "Uploading " << static_cast<int>(payload_download_error_code)
379               << " for metric " << metric << " (sparse)";
380     metrics_lib_->SendSparseToUMA(
381         metric, static_cast<int>(payload_download_error_code));
382   }
383 
384   metric = metrics::kMetricAttemptConnectionType;
385   LOG(INFO) << "Uploading " << static_cast<int>(connection_type)
386             << " for metric " << metric;
387   metrics_lib_->SendEnumToUMA(
388       metric,
389       static_cast<int>(connection_type),
390       static_cast<int>(metrics::ConnectionType::kNumConstants));
391 }
392 
393 void MetricsReporterOmaha::ReportSuccessfulUpdateMetrics(
394     int attempt_count,
395     int updates_abandoned_count,
396     PayloadType payload_type,
397     int64_t payload_size,
398     int64_t num_bytes_downloaded[kNumDownloadSources],
399     int download_overhead_percentage,
400     base::TimeDelta total_duration,
401     base::TimeDelta total_duration_uptime,
402     int reboot_count,
403     int url_switch_count) {
404   string metric = metrics::kMetricSuccessfulUpdatePayloadSizeMiB;
405   int64_t mbs = payload_size / kNumBytesInOneMiB;
406   LOG(INFO) << "Uploading " << mbs << " (MiBs) for metric " << metric;
407   metrics_lib_->SendToUMA(metric,
408                           mbs,
409                           0,     // min: 0 MiB
410                           1024,  // max: 1024 MiB = 1 GiB
411                           50);   // num_buckets
412 
413   int64_t total_bytes = 0;
414   int download_sources_used = 0;
415   for (int i = 0; i < kNumDownloadSources + 1; i++) {
416     DownloadSource source = static_cast<DownloadSource>(i);
417 
418     // Only consider this download source (and send byte counts) as
419     // having been used if we downloaded a non-trivial amount of bytes
420     // (e.g. at least 1 MiB) that contributed to the
421     // update. Otherwise we're going to end up with a lot of zero-byte
422     // events in the histogram.
423 
424     metric = metrics::kMetricSuccessfulUpdateBytesDownloadedMiB;
425     if (i < kNumDownloadSources) {
426       metric += utils::ToString(source);
427       mbs = num_bytes_downloaded[i] / kNumBytesInOneMiB;
428       total_bytes += num_bytes_downloaded[i];
429       if (mbs > 0)
430         download_sources_used |= (1 << i);
431     } else {
432       mbs = total_bytes / kNumBytesInOneMiB;
433     }
434 
435     if (mbs > 0) {
436       LOG(INFO) << "Uploading " << mbs << " (MiBs) for metric " << metric;
437       metrics_lib_->SendToUMA(metric,
438                               mbs,
439                               0,     // min: 0 MiB
440                               1024,  // max: 1024 MiB = 1 GiB
441                               50);   // num_buckets
442     }
443   }
444 
445   metric = metrics::kMetricSuccessfulUpdateDownloadSourcesUsed;
446   LOG(INFO) << "Uploading 0x" << std::hex << download_sources_used
447             << " (bit flags) for metric " << metric;
448   metrics_lib_->SendToUMA(metric,
449                           download_sources_used,
450                           0,                               // min
451                           (1 << kNumDownloadSources) - 1,  // max
452                           1 << kNumDownloadSources);       // num_buckets
453 
454   metric = metrics::kMetricSuccessfulUpdateDownloadOverheadPercentage;
455   LOG(INFO) << "Uploading " << download_overhead_percentage << "% for metric "
456             << metric;
457   metrics_lib_->SendToUMA(metric,
458                           download_overhead_percentage,
459                           0,     // min: 0% overhead
460                           1000,  // max: 1000% overhead
461                           50);   // num_buckets
462 
463   metric = metrics::kMetricSuccessfulUpdateUrlSwitchCount;
464   LOG(INFO) << "Uploading " << url_switch_count << " (count) for metric "
465             << metric;
466   metrics_lib_->SendToUMA(metric,
467                           url_switch_count,
468                           0,    // min: 0 URL switches
469                           49,   // max: 49 URL switches
470                           50);  // num_buckets
471 
472   metric = metrics::kMetricSuccessfulUpdateTotalDurationMinutes;
473   LOG(INFO) << "Uploading " << utils::FormatTimeDelta(total_duration)
474             << " for metric " << metric;
475   metrics_lib_->SendToUMA(metric,
476                           static_cast<int>(total_duration.InMinutes()),
477                           0,              // min: 0 min
478                           365 * 24 * 60,  // max: 365 days ~= 1 year
479                           50);            // num_buckets
480 
481   metric = metrics::kMetricSuccessfulUpdateTotalDurationUptimeMinutes;
482   LOG(INFO) << "Uploading " << utils::FormatTimeDelta(total_duration_uptime)
483             << " for metric " << metric;
484   metrics_lib_->SendToUMA(metric,
485                           static_cast<int>(total_duration_uptime.InMinutes()),
486                           0,             // min: 0 min
487                           30 * 24 * 60,  // max: 30 days
488                           50);           // num_buckets
489 
490   metric = metrics::kMetricSuccessfulUpdateRebootCount;
491   LOG(INFO) << "Uploading reboot count of " << reboot_count << " for metric "
492             << metric;
493   metrics_lib_->SendToUMA(metric,
494                           reboot_count,
495                           0,    // min: 0 reboots
496                           49,   // max: 49 reboots
497                           50);  // num_buckets
498 
499   metric = metrics::kMetricSuccessfulUpdatePayloadType;
500   metrics_lib_->SendEnumToUMA(metric, payload_type, kNumPayloadTypes);
501   LOG(INFO) << "Uploading " << utils::ToString(payload_type) << " for metric "
502             << metric;
503 
504   metric = metrics::kMetricSuccessfulUpdateAttemptCount;
505   metrics_lib_->SendToUMA(metric,
506                           attempt_count,
507                           1,    // min: 1 attempt
508                           50,   // max: 50 attempts
509                           50);  // num_buckets
510   LOG(INFO) << "Uploading " << attempt_count << " for metric " << metric;
511 
512   metric = metrics::kMetricSuccessfulUpdateUpdatesAbandonedCount;
513   LOG(INFO) << "Uploading " << updates_abandoned_count << " (count) for metric "
514             << metric;
515   metrics_lib_->SendToUMA(metric,
516                           updates_abandoned_count,
517                           0,    // min: 0 counts
518                           49,   // max: 49 counts
519                           50);  // num_buckets
520 }
521 
522 void MetricsReporterOmaha::ReportRollbackMetrics(
523     metrics::RollbackResult result) {
524   string metric = metrics::kMetricRollbackResult;
525   int value = static_cast<int>(result);
526   LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
527   metrics_lib_->SendEnumToUMA(
528       metric, value, static_cast<int>(metrics::RollbackResult::kNumConstants));
529 }
530 
531 void MetricsReporterOmaha::ReportEnterpriseRollbackMetrics(
532     bool success, const string& rollback_version) {
533   int value = utils::VersionPrefix(rollback_version);
534   string metric = metrics::kMetricEnterpriseRollbackSuccess;
535   if (!success)
536     metric = metrics::kMetricEnterpriseRollbackFailure;
537   LOG(INFO) << "Sending " << value << " for metric " << metric;
538   metrics_lib_->SendSparseToUMA(metric, value);
539 }
540 
541 void MetricsReporterOmaha::ReportCertificateCheckMetrics(
542     ServerToCheck server_to_check, CertificateCheckResult result) {
543   string metric;
544   switch (server_to_check) {
545     case ServerToCheck::kUpdate:
546       metric = metrics::kMetricCertificateCheckUpdateCheck;
547       break;
548     case ServerToCheck::kDownload:
549       metric = metrics::kMetricCertificateCheckDownload;
550       break;
551     case ServerToCheck::kNone:
552       return;
553   }
554   LOG(INFO) << "Uploading " << static_cast<int>(result) << " for metric "
555             << metric;
556   metrics_lib_->SendEnumToUMA(
557       metric,
558       static_cast<int>(result),
559       static_cast<int>(CertificateCheckResult::kNumConstants));
560 }
561 
562 void MetricsReporterOmaha::ReportFailedUpdateCount(int target_attempt) {
563   string metric = metrics::kMetricFailedUpdateCount;
564   metrics_lib_->SendToUMA(metric,
565                           target_attempt,
566                           1,   // min value
567                           50,  // max value
568                           kNumDefaultUmaBuckets);
569 
570   LOG(INFO) << "Uploading " << target_attempt << " (count) for metric "
571             << metric;
572 }
573 
574 void MetricsReporterOmaha::ReportTimeToReboot(int time_to_reboot_minutes) {
575   string metric = metrics::kMetricTimeToRebootMinutes;
576   metrics_lib_->SendToUMA(metric,
577                           time_to_reboot_minutes,
578                           0,             // min: 0 minute
579                           30 * 24 * 60,  // max: 1 month (approx)
580                           kNumDefaultUmaBuckets);
581 
582   LOG(INFO) << "Uploading " << time_to_reboot_minutes << " for metric "
583             << metric;
584 }
585 
586 void MetricsReporterOmaha::ReportInstallDateProvisioningSource(int source,
587                                                                int max) {
588   metrics_lib_->SendEnumToUMA(metrics::kMetricInstallDateProvisioningSource,
589                               source,  // Sample.
590                               max);
591 }
592 
593 void MetricsReporterOmaha::ReportInternalErrorCode(ErrorCode error_code) {
594   auto metric = metrics::kMetricAttemptInternalErrorCode;
595   LOG(INFO) << "Uploading " << error_code << " for metric " << metric;
596   metrics_lib_->SendEnumToUMA(metric,
597                               static_cast<int>(error_code),
598                               static_cast<int>(ErrorCode::kUmaReportedMax));
599 }
600 
601 void MetricsReporterOmaha::ReportKeyVersionMetrics(
602     int kernel_min_version,
603     int kernel_max_rollforward_version,
604     bool kernel_max_rollforward_success) {
605   int value = kernel_min_version;
606   string metric = metrics::kMetricKernelMinVersion;
607   LOG(INFO) << "Sending " << value << " for metric " << metric;
608   metrics_lib_->SendSparseToUMA(metric, value);
609 
610   value = kernel_max_rollforward_version;
611   metric = metrics::kMetricKernelMaxRollforwardVersion;
612   LOG(INFO) << "Sending " << value << " for metric " << metric;
613   metrics_lib_->SendSparseToUMA(metric, value);
614 
615   bool bool_value = kernel_max_rollforward_success;
616   metric = metrics::kMetricKernelMaxRollforwardSetSuccess;
617   LOG(INFO) << "Sending " << bool_value << " for metric " << metric
618             << " (bool)";
619   metrics_lib_->SendBoolToUMA(metric, bool_value);
620 }
621 
622 void MetricsReporterOmaha::ReportEnterpriseUpdateSeenToDownloadDays(
623     bool has_time_restriction_policy, int time_to_update_days) {
624   string metric =
625       has_time_restriction_policy
626           ? metrics::kMetricSuccessfulUpdateDurationFromSeenTimeRestrictedDays
627           : metrics::kMetricSuccessfulUpdateDurationFromSeenDays;
628   LOG(INFO) << "Sending " << time_to_update_days << " for metric " << metric;
629 
630   metrics_lib_->SendToUMA(metric,
631                           time_to_update_days,
632                           1,       // min: 1 days
633                           6 * 30,  // max: 6 months (approx)
634                           50);     // num_buckets
635 }
636 
637 }  // namespace chromeos_update_engine
638