Home | History | Annotate | Download | only in update_engine
      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 #include <string>
     21 
     22 #include <base/logging.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/system_state.h"
     31 
     32 using std::string;
     33 
     34 namespace chromeos_update_engine {
     35 
     36 namespace metrics {
     37 
     38 // UpdateEngine.Daily.* metrics.
     39 const char kMetricDailyOSAgeDays[] = "UpdateEngine.Daily.OSAgeDays";
     40 
     41 // UpdateEngine.Check.* metrics.
     42 const char kMetricCheckDownloadErrorCode[] =
     43     "UpdateEngine.Check.DownloadErrorCode";
     44 const char kMetricCheckReaction[] = "UpdateEngine.Check.Reaction";
     45 const char kMetricCheckResult[] = "UpdateEngine.Check.Result";
     46 const char kMetricCheckTimeSinceLastCheckMinutes[] =
     47     "UpdateEngine.Check.TimeSinceLastCheckMinutes";
     48 const char kMetricCheckTimeSinceLastCheckUptimeMinutes[] =
     49     "UpdateEngine.Check.TimeSinceLastCheckUptimeMinutes";
     50 
     51 // UpdateEngine.Attempt.* metrics.
     52 const char kMetricAttemptNumber[] = "UpdateEngine.Attempt.Number";
     53 const char kMetricAttemptPayloadType[] = "UpdateEngine.Attempt.PayloadType";
     54 const char kMetricAttemptPayloadSizeMiB[] =
     55     "UpdateEngine.Attempt.PayloadSizeMiB";
     56 const char kMetricAttemptConnectionType[] =
     57     "UpdateEngine.Attempt.ConnectionType";
     58 const char kMetricAttemptDurationMinutes[] =
     59     "UpdateEngine.Attempt.DurationMinutes";
     60 const char kMetricAttemptDurationUptimeMinutes[] =
     61     "UpdateEngine.Attempt.DurationUptimeMinutes";
     62 const char kMetricAttemptTimeSinceLastAttemptMinutes[] =
     63     "UpdateEngine.Attempt.TimeSinceLastAttemptMinutes";
     64 const char kMetricAttemptTimeSinceLastAttemptUptimeMinutes[] =
     65     "UpdateEngine.Attempt.TimeSinceLastAttemptUptimeMinutes";
     66 const char kMetricAttemptPayloadBytesDownloadedMiB[] =
     67     "UpdateEngine.Attempt.PayloadBytesDownloadedMiB";
     68 const char kMetricAttemptPayloadDownloadSpeedKBps[] =
     69     "UpdateEngine.Attempt.PayloadDownloadSpeedKBps";
     70 const char kMetricAttemptDownloadSource[] =
     71     "UpdateEngine.Attempt.DownloadSource";
     72 const char kMetricAttemptResult[] = "UpdateEngine.Attempt.Result";
     73 const char kMetricAttemptInternalErrorCode[] =
     74     "UpdateEngine.Attempt.InternalErrorCode";
     75 const char kMetricAttemptDownloadErrorCode[] =
     76     "UpdateEngine.Attempt.DownloadErrorCode";
     77 
     78 // UpdateEngine.SuccessfulUpdate.* metrics.
     79 const char kMetricSuccessfulUpdateAttemptCount[] =
     80     "UpdateEngine.SuccessfulUpdate.AttemptCount";
     81 const char kMetricSuccessfulUpdateBytesDownloadedMiB[] =
     82     "UpdateEngine.SuccessfulUpdate.BytesDownloadedMiB";
     83 const char kMetricSuccessfulUpdateDownloadOverheadPercentage[] =
     84     "UpdateEngine.SuccessfulUpdate.DownloadOverheadPercentage";
     85 const char kMetricSuccessfulUpdateDownloadSourcesUsed[] =
     86     "UpdateEngine.SuccessfulUpdate.DownloadSourcesUsed";
     87 const char kMetricSuccessfulUpdatePayloadType[] =
     88     "UpdateEngine.SuccessfulUpdate.PayloadType";
     89 const char kMetricSuccessfulUpdatePayloadSizeMiB[] =
     90     "UpdateEngine.SuccessfulUpdate.PayloadSizeMiB";
     91 const char kMetricSuccessfulUpdateRebootCount[] =
     92     "UpdateEngine.SuccessfulUpdate.RebootCount";
     93 const char kMetricSuccessfulUpdateTotalDurationMinutes[] =
     94     "UpdateEngine.SuccessfulUpdate.TotalDurationMinutes";
     95 const char kMetricSuccessfulUpdateUpdatesAbandonedCount[] =
     96     "UpdateEngine.SuccessfulUpdate.UpdatesAbandonedCount";
     97 const char kMetricSuccessfulUpdateUrlSwitchCount[] =
     98     "UpdateEngine.SuccessfulUpdate.UrlSwitchCount";
     99 
    100 // UpdateEngine.Rollback.* metric.
    101 const char kMetricRollbackResult[] = "UpdateEngine.Rollback.Result";
    102 
    103 // UpdateEngine.CertificateCheck.* metrics.
    104 const char kMetricCertificateCheckUpdateCheck[] =
    105     "UpdateEngine.CertificateCheck.UpdateCheck";
    106 const char kMetricCertificateCheckDownload[] =
    107     "UpdateEngine.CertificateCheck.Download";
    108 
    109 // UpdateEngine.* metrics.
    110 const char kMetricFailedUpdateCount[] = "UpdateEngine.FailedUpdateCount";
    111 const char kMetricInstallDateProvisioningSource[] =
    112     "UpdateEngine.InstallDateProvisioningSource";
    113 const char kMetricTimeToRebootMinutes[] = "UpdateEngine.TimeToRebootMinutes";
    114 
    115 std::unique_ptr<MetricsReporterInterface> CreateMetricsReporter() {
    116   return std::make_unique<MetricsReporterOmaha>();
    117 }
    118 
    119 }  // namespace metrics
    120 
    121 MetricsReporterOmaha::MetricsReporterOmaha()
    122     : metrics_lib_(new MetricsLibrary()) {}
    123 
    124 void MetricsReporterOmaha::Initialize() {
    125   metrics_lib_->Init();
    126 }
    127 
    128 void MetricsReporterOmaha::ReportDailyMetrics(base::TimeDelta os_age) {
    129   string metric = metrics::kMetricDailyOSAgeDays;
    130   LOG(INFO) << "Uploading " << utils::FormatTimeDelta(os_age) << " for metric "
    131             << metric;
    132   metrics_lib_->SendToUMA(metric,
    133                           static_cast<int>(os_age.InDays()),
    134                           0,       // min: 0 days
    135                           6 * 30,  // max: 6 months (approx)
    136                           50);     // num_buckets
    137 }
    138 
    139 void MetricsReporterOmaha::ReportUpdateCheckMetrics(
    140     SystemState* system_state,
    141     metrics::CheckResult result,
    142     metrics::CheckReaction reaction,
    143     metrics::DownloadErrorCode download_error_code) {
    144   string metric;
    145   int value;
    146   int max_value;
    147 
    148   if (result != metrics::CheckResult::kUnset) {
    149     metric = metrics::kMetricCheckResult;
    150     value = static_cast<int>(result);
    151     max_value = static_cast<int>(metrics::CheckResult::kNumConstants) - 1;
    152     LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
    153     metrics_lib_->SendEnumToUMA(metric, value, max_value);
    154   }
    155   if (reaction != metrics::CheckReaction::kUnset) {
    156     metric = metrics::kMetricCheckReaction;
    157     value = static_cast<int>(reaction);
    158     max_value = static_cast<int>(metrics::CheckReaction::kNumConstants) - 1;
    159     LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
    160     metrics_lib_->SendEnumToUMA(metric, value, max_value);
    161   }
    162   if (download_error_code != metrics::DownloadErrorCode::kUnset) {
    163     metric = metrics::kMetricCheckDownloadErrorCode;
    164     value = static_cast<int>(download_error_code);
    165     LOG(INFO) << "Sending " << value << " for metric " << metric << " (sparse)";
    166     metrics_lib_->SendSparseToUMA(metric, value);
    167   }
    168 
    169   base::TimeDelta time_since_last;
    170   if (metrics_utils::WallclockDurationHelper(
    171           system_state,
    172           kPrefsMetricsCheckLastReportingTime,
    173           &time_since_last)) {
    174     metric = metrics::kMetricCheckTimeSinceLastCheckMinutes;
    175     LOG(INFO) << "Sending " << utils::FormatTimeDelta(time_since_last)
    176               << " for metric " << metric;
    177     metrics_lib_->SendToUMA(metric,
    178                             time_since_last.InMinutes(),
    179                             0,             // min: 0 min
    180                             30 * 24 * 60,  // max: 30 days
    181                             50);           // num_buckets
    182   }
    183 
    184   base::TimeDelta uptime_since_last;
    185   static int64_t uptime_since_last_storage = 0;
    186   if (metrics_utils::MonotonicDurationHelper(
    187           system_state, &uptime_since_last_storage, &uptime_since_last)) {
    188     metric = metrics::kMetricCheckTimeSinceLastCheckUptimeMinutes;
    189     LOG(INFO) << "Sending " << utils::FormatTimeDelta(uptime_since_last)
    190               << " for metric " << metric;
    191     metrics_lib_->SendToUMA(metric,
    192                             uptime_since_last.InMinutes(),
    193                             0,             // min: 0 min
    194                             30 * 24 * 60,  // max: 30 days
    195                             50);           // num_buckets
    196   }
    197 }
    198 
    199 void MetricsReporterOmaha::ReportAbnormallyTerminatedUpdateAttemptMetrics() {
    200   string metric = metrics::kMetricAttemptResult;
    201   metrics::AttemptResult attempt_result =
    202       metrics::AttemptResult::kAbnormalTermination;
    203 
    204   LOG(INFO) << "Uploading " << static_cast<int>(attempt_result)
    205             << " for metric " << metric;
    206   metrics_lib_->SendEnumToUMA(
    207       metric,
    208       static_cast<int>(attempt_result),
    209       static_cast<int>(metrics::AttemptResult::kNumConstants));
    210 }
    211 
    212 void MetricsReporterOmaha::ReportUpdateAttemptMetrics(
    213     SystemState* system_state,
    214     int attempt_number,
    215     PayloadType payload_type,
    216     base::TimeDelta duration,
    217     base::TimeDelta duration_uptime,
    218     int64_t payload_size,
    219     metrics::AttemptResult attempt_result,
    220     ErrorCode internal_error_code) {
    221   string metric = metrics::kMetricAttemptNumber;
    222   LOG(INFO) << "Uploading " << attempt_number << " for metric " << metric;
    223   metrics_lib_->SendToUMA(metric,
    224                           attempt_number,
    225                           0,    // min: 0 attempts
    226                           49,   // max: 49 attempts
    227                           50);  // num_buckets
    228 
    229   metric = metrics::kMetricAttemptPayloadType;
    230   LOG(INFO) << "Uploading " << utils::ToString(payload_type) << " for metric "
    231             << metric;
    232   metrics_lib_->SendEnumToUMA(metric, payload_type, kNumPayloadTypes);
    233 
    234   metric = metrics::kMetricAttemptDurationMinutes;
    235   LOG(INFO) << "Uploading " << utils::FormatTimeDelta(duration)
    236             << " for metric " << metric;
    237   metrics_lib_->SendToUMA(metric,
    238                           duration.InMinutes(),
    239                           0,             // min: 0 min
    240                           10 * 24 * 60,  // max: 10 days
    241                           50);           // num_buckets
    242 
    243   metric = metrics::kMetricAttemptDurationUptimeMinutes;
    244   LOG(INFO) << "Uploading " << utils::FormatTimeDelta(duration_uptime)
    245             << " for metric " << metric;
    246   metrics_lib_->SendToUMA(metric,
    247                           duration_uptime.InMinutes(),
    248                           0,             // min: 0 min
    249                           10 * 24 * 60,  // max: 10 days
    250                           50);           // num_buckets
    251 
    252   metric = metrics::kMetricAttemptPayloadSizeMiB;
    253   int64_t payload_size_mib = payload_size / kNumBytesInOneMiB;
    254   LOG(INFO) << "Uploading " << payload_size_mib << " for metric " << metric;
    255   metrics_lib_->SendToUMA(metric,
    256                           payload_size_mib,
    257                           0,     // min: 0 MiB
    258                           1024,  // max: 1024 MiB = 1 GiB
    259                           50);   // num_buckets
    260 
    261 
    262 
    263   metric = metrics::kMetricAttemptResult;
    264   LOG(INFO) << "Uploading " << static_cast<int>(attempt_result)
    265             << " for metric " << metric;
    266   metrics_lib_->SendEnumToUMA(
    267       metric,
    268       static_cast<int>(attempt_result),
    269       static_cast<int>(metrics::AttemptResult::kNumConstants));
    270 
    271   if (internal_error_code != ErrorCode::kSuccess) {
    272     metric = metrics::kMetricAttemptInternalErrorCode;
    273     LOG(INFO) << "Uploading " << internal_error_code << " for metric "
    274               << metric;
    275     metrics_lib_->SendEnumToUMA(metric,
    276                                 static_cast<int>(internal_error_code),
    277                                 static_cast<int>(ErrorCode::kUmaReportedMax));
    278   }
    279 
    280   base::TimeDelta time_since_last;
    281   if (metrics_utils::WallclockDurationHelper(
    282           system_state,
    283           kPrefsMetricsAttemptLastReportingTime,
    284           &time_since_last)) {
    285     metric = metrics::kMetricAttemptTimeSinceLastAttemptMinutes;
    286     LOG(INFO) << "Sending " << utils::FormatTimeDelta(time_since_last)
    287               << " for metric " << metric;
    288     metrics_lib_->SendToUMA(metric,
    289                             time_since_last.InMinutes(),
    290                             0,             // min: 0 min
    291                             30 * 24 * 60,  // max: 30 days
    292                             50);           // num_buckets
    293   }
    294 
    295   static int64_t uptime_since_last_storage = 0;
    296   base::TimeDelta uptime_since_last;
    297   if (metrics_utils::MonotonicDurationHelper(
    298           system_state, &uptime_since_last_storage, &uptime_since_last)) {
    299     metric = metrics::kMetricAttemptTimeSinceLastAttemptUptimeMinutes;
    300     LOG(INFO) << "Sending " << utils::FormatTimeDelta(uptime_since_last)
    301               << " for metric " << metric;
    302     metrics_lib_->SendToUMA(metric,
    303                             uptime_since_last.InMinutes(),
    304                             0,             // min: 0 min
    305                             30 * 24 * 60,  // max: 30 days
    306                             50);           // num_buckets
    307   }
    308 }
    309 
    310 void MetricsReporterOmaha::ReportUpdateAttemptDownloadMetrics(
    311     int64_t payload_bytes_downloaded,
    312     int64_t payload_download_speed_bps,
    313     DownloadSource download_source,
    314     metrics::DownloadErrorCode payload_download_error_code,
    315     metrics::ConnectionType connection_type) {
    316   string metric = metrics::kMetricAttemptPayloadBytesDownloadedMiB;
    317   int64_t payload_bytes_downloaded_mib =
    318       payload_bytes_downloaded / kNumBytesInOneMiB;
    319   LOG(INFO) << "Uploading " << payload_bytes_downloaded_mib << " for metric "
    320             << metric;
    321   metrics_lib_->SendToUMA(metric,
    322                           payload_bytes_downloaded_mib,
    323                           0,     // min: 0 MiB
    324                           1024,  // max: 1024 MiB = 1 GiB
    325                           50);   // num_buckets
    326 
    327   metric = metrics::kMetricAttemptPayloadDownloadSpeedKBps;
    328   int64_t payload_download_speed_kbps = payload_download_speed_bps / 1000;
    329   LOG(INFO) << "Uploading " << payload_download_speed_kbps << " for metric "
    330             << metric;
    331   metrics_lib_->SendToUMA(metric,
    332                           payload_download_speed_kbps,
    333                           0,          // min: 0 kB/s
    334                           10 * 1000,  // max: 10000 kB/s = 10 MB/s
    335                           50);        // num_buckets
    336 
    337   metric = metrics::kMetricAttemptDownloadSource;
    338   LOG(INFO) << "Uploading " << download_source << " for metric " << metric;
    339   metrics_lib_->SendEnumToUMA(metric, download_source, kNumDownloadSources);
    340 
    341   if (payload_download_error_code != metrics::DownloadErrorCode::kUnset) {
    342     metric = metrics::kMetricAttemptDownloadErrorCode;
    343     LOG(INFO) << "Uploading " << static_cast<int>(payload_download_error_code)
    344               << " for metric " << metric << " (sparse)";
    345     metrics_lib_->SendSparseToUMA(
    346         metric, static_cast<int>(payload_download_error_code));
    347   }
    348 
    349   metric = metrics::kMetricAttemptConnectionType;
    350   LOG(INFO) << "Uploading " << static_cast<int>(connection_type)
    351             << " for metric " << metric;
    352   metrics_lib_->SendEnumToUMA(
    353       metric,
    354       static_cast<int>(connection_type),
    355       static_cast<int>(metrics::ConnectionType::kNumConstants));
    356 }
    357 
    358 void MetricsReporterOmaha::ReportSuccessfulUpdateMetrics(
    359     int attempt_count,
    360     int updates_abandoned_count,
    361     PayloadType payload_type,
    362     int64_t payload_size,
    363     int64_t num_bytes_downloaded[kNumDownloadSources],
    364     int download_overhead_percentage,
    365     base::TimeDelta total_duration,
    366     int reboot_count,
    367     int url_switch_count) {
    368   string metric = metrics::kMetricSuccessfulUpdatePayloadSizeMiB;
    369   int64_t mbs = payload_size / kNumBytesInOneMiB;
    370   LOG(INFO) << "Uploading " << mbs << " (MiBs) for metric " << metric;
    371   metrics_lib_->SendToUMA(metric,
    372                           mbs,
    373                           0,     // min: 0 MiB
    374                           1024,  // max: 1024 MiB = 1 GiB
    375                           50);   // num_buckets
    376 
    377   int64_t total_bytes = 0;
    378   int download_sources_used = 0;
    379   for (int i = 0; i < kNumDownloadSources + 1; i++) {
    380     DownloadSource source = static_cast<DownloadSource>(i);
    381 
    382     // Only consider this download source (and send byte counts) as
    383     // having been used if we downloaded a non-trivial amount of bytes
    384     // (e.g. at least 1 MiB) that contributed to the
    385     // update. Otherwise we're going to end up with a lot of zero-byte
    386     // events in the histogram.
    387 
    388     metric = metrics::kMetricSuccessfulUpdateBytesDownloadedMiB;
    389     if (i < kNumDownloadSources) {
    390       metric += utils::ToString(source);
    391       mbs = num_bytes_downloaded[i] / kNumBytesInOneMiB;
    392       total_bytes += num_bytes_downloaded[i];
    393       if (mbs > 0)
    394         download_sources_used |= (1 << i);
    395     } else {
    396       mbs = total_bytes / kNumBytesInOneMiB;
    397     }
    398 
    399     if (mbs > 0) {
    400       LOG(INFO) << "Uploading " << mbs << " (MiBs) for metric " << metric;
    401       metrics_lib_->SendToUMA(metric,
    402                               mbs,
    403                               0,     // min: 0 MiB
    404                               1024,  // max: 1024 MiB = 1 GiB
    405                               50);   // num_buckets
    406     }
    407   }
    408 
    409   metric = metrics::kMetricSuccessfulUpdateDownloadSourcesUsed;
    410   LOG(INFO) << "Uploading 0x" << std::hex << download_sources_used
    411             << " (bit flags) for metric " << metric;
    412   metrics_lib_->SendToUMA(metric,
    413                           download_sources_used,
    414                           0,                               // min
    415                           (1 << kNumDownloadSources) - 1,  // max
    416                           1 << kNumDownloadSources);       // num_buckets
    417 
    418   metric = metrics::kMetricSuccessfulUpdateDownloadOverheadPercentage;
    419   LOG(INFO) << "Uploading " << download_overhead_percentage << "% for metric "
    420             << metric;
    421   metrics_lib_->SendToUMA(metric,
    422                           download_overhead_percentage,
    423                           0,     // min: 0% overhead
    424                           1000,  // max: 1000% overhead
    425                           50);   // num_buckets
    426 
    427   metric = metrics::kMetricSuccessfulUpdateUrlSwitchCount;
    428   LOG(INFO) << "Uploading " << url_switch_count << " (count) for metric "
    429             << metric;
    430   metrics_lib_->SendToUMA(metric,
    431                           url_switch_count,
    432                           0,    // min: 0 URL switches
    433                           49,   // max: 49 URL switches
    434                           50);  // num_buckets
    435 
    436   metric = metrics::kMetricSuccessfulUpdateTotalDurationMinutes;
    437   LOG(INFO) << "Uploading " << utils::FormatTimeDelta(total_duration)
    438             << " for metric " << metric;
    439   metrics_lib_->SendToUMA(metric,
    440                           static_cast<int>(total_duration.InMinutes()),
    441                           0,              // min: 0 min
    442                           365 * 24 * 60,  // max: 365 days ~= 1 year
    443                           50);            // num_buckets
    444 
    445   metric = metrics::kMetricSuccessfulUpdateRebootCount;
    446   LOG(INFO) << "Uploading reboot count of " << reboot_count << " for metric "
    447             << metric;
    448   metrics_lib_->SendToUMA(metric,
    449                           reboot_count,
    450                           0,    // min: 0 reboots
    451                           49,   // max: 49 reboots
    452                           50);  // num_buckets
    453 
    454   metric = metrics::kMetricSuccessfulUpdatePayloadType;
    455   metrics_lib_->SendEnumToUMA(metric, payload_type, kNumPayloadTypes);
    456   LOG(INFO) << "Uploading " << utils::ToString(payload_type) << " for metric "
    457             << metric;
    458 
    459   metric = metrics::kMetricSuccessfulUpdateAttemptCount;
    460   metrics_lib_->SendToUMA(metric,
    461                           attempt_count,
    462                           1,    // min: 1 attempt
    463                           50,   // max: 50 attempts
    464                           50);  // num_buckets
    465   LOG(INFO) << "Uploading " << attempt_count << " for metric " << metric;
    466 
    467   metric = metrics::kMetricSuccessfulUpdateUpdatesAbandonedCount;
    468   LOG(INFO) << "Uploading " << updates_abandoned_count << " (count) for metric "
    469             << metric;
    470   metrics_lib_->SendToUMA(metric,
    471                           updates_abandoned_count,
    472                           0,    // min: 0 counts
    473                           49,   // max: 49 counts
    474                           50);  // num_buckets
    475 }
    476 
    477 void MetricsReporterOmaha::ReportRollbackMetrics(
    478     metrics::RollbackResult result) {
    479   string metric = metrics::kMetricRollbackResult;
    480   int value = static_cast<int>(result);
    481   LOG(INFO) << "Sending " << value << " for metric " << metric << " (enum)";
    482   metrics_lib_->SendEnumToUMA(
    483       metric, value, static_cast<int>(metrics::RollbackResult::kNumConstants));
    484 }
    485 
    486 void MetricsReporterOmaha::ReportCertificateCheckMetrics(
    487     ServerToCheck server_to_check, CertificateCheckResult result) {
    488   string metric;
    489   switch (server_to_check) {
    490     case ServerToCheck::kUpdate:
    491       metric = metrics::kMetricCertificateCheckUpdateCheck;
    492       break;
    493     case ServerToCheck::kDownload:
    494       metric = metrics::kMetricCertificateCheckDownload;
    495       break;
    496     case ServerToCheck::kNone:
    497       return;
    498   }
    499   LOG(INFO) << "Uploading " << static_cast<int>(result) << " for metric "
    500             << metric;
    501   metrics_lib_->SendEnumToUMA(
    502       metric,
    503       static_cast<int>(result),
    504       static_cast<int>(CertificateCheckResult::kNumConstants));
    505 }
    506 
    507 void MetricsReporterOmaha::ReportFailedUpdateCount(int target_attempt) {
    508   string metric = metrics::kMetricFailedUpdateCount;
    509   metrics_lib_->SendToUMA(metric,
    510                           target_attempt,
    511                           1,   // min value
    512                           50,  // max value
    513                           kNumDefaultUmaBuckets);
    514 
    515   LOG(INFO) << "Uploading " << target_attempt << " (count) for metric "
    516             << metric;
    517 }
    518 
    519 void MetricsReporterOmaha::ReportTimeToReboot(int time_to_reboot_minutes) {
    520   string metric = metrics::kMetricTimeToRebootMinutes;
    521   metrics_lib_->SendToUMA(metric,
    522                           time_to_reboot_minutes,
    523                           0,             // min: 0 minute
    524                           30 * 24 * 60,  // max: 1 month (approx)
    525                           kNumDefaultUmaBuckets);
    526 
    527   LOG(INFO) << "Uploading " << time_to_reboot_minutes << " for metric "
    528             << metric;
    529 }
    530 
    531 void MetricsReporterOmaha::ReportInstallDateProvisioningSource(int source,
    532                                                                int max) {
    533   metrics_lib_->SendEnumToUMA(metrics::kMetricInstallDateProvisioningSource,
    534                               source,  // Sample.
    535                               max);
    536 }
    537 
    538 }  // namespace chromeos_update_engine
    539