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