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/cros/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/constants.h"
26 #include "update_engine/common/prefs_interface.h"
27 #include "update_engine/common/system_state.h"
28 #include "update_engine/common/utils.h"
29 #include "update_engine/cros/omaha_request_params.h"
30 #include "update_engine/metrics_utils.h"
31 
32 using base::Time;
33 using base::TimeDelta;
34 using std::string;
35 
36 namespace chromeos_update_engine {
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 
CreateMetricsReporter(DynamicPartitionControlInterface * dynamic_partition_control)138 std::unique_ptr<MetricsReporterInterface> CreateMetricsReporter(
139     DynamicPartitionControlInterface* dynamic_partition_control) {
140   return std::make_unique<MetricsReporterOmaha>();
141 }
142 
143 }  // namespace metrics
144 
MetricsReporterOmaha()145 MetricsReporterOmaha::MetricsReporterOmaha()
146     : metrics_lib_(new MetricsLibrary()) {}
147 
ReportDailyMetrics(base::TimeDelta os_age)148 void MetricsReporterOmaha::ReportDailyMetrics(base::TimeDelta os_age) {
149   string metric = metrics::kMetricDailyOSAgeDays;
150   metrics_lib_->SendToUMA(metric,
151                           static_cast<int>(os_age.InDays()),
152                           0,       // min: 0 days
153                           6 * 30,  // max: 6 months (approx)
154                           50);     // num_buckets
155 }
156 
ReportUpdateCheckMetrics(metrics::CheckResult result,metrics::CheckReaction reaction,metrics::DownloadErrorCode download_error_code)157 void MetricsReporterOmaha::ReportUpdateCheckMetrics(
158     metrics::CheckResult result,
159     metrics::CheckReaction reaction,
160     metrics::DownloadErrorCode download_error_code) {
161   string metric;
162   int value;
163   int max_value;
164 
165   if (result != metrics::CheckResult::kUnset) {
166     metric = metrics::kMetricCheckResult;
167     value = static_cast<int>(result);
168     max_value = static_cast<int>(metrics::CheckResult::kNumConstants) - 1;
169     metrics_lib_->SendEnumToUMA(metric, value, max_value);
170   }
171   if (reaction != metrics::CheckReaction::kUnset) {
172     metric = metrics::kMetricCheckReaction;
173     value = static_cast<int>(reaction);
174     max_value = static_cast<int>(metrics::CheckReaction::kNumConstants) - 1;
175     metrics_lib_->SendEnumToUMA(metric, value, max_value);
176   }
177   if (download_error_code != metrics::DownloadErrorCode::kUnset) {
178     metric = metrics::kMetricCheckDownloadErrorCode;
179     value = static_cast<int>(download_error_code);
180     metrics_lib_->SendSparseToUMA(metric, value);
181   }
182 
183   base::TimeDelta time_since_last;
184   if (WallclockDurationHelper(kPrefsMetricsCheckLastReportingTime,
185                               &time_since_last)) {
186     metric = metrics::kMetricCheckTimeSinceLastCheckMinutes;
187     metrics_lib_->SendToUMA(metric,
188                             time_since_last.InMinutes(),
189                             0,             // min: 0 min
190                             30 * 24 * 60,  // max: 30 days
191                             50);           // num_buckets
192   }
193 
194   base::TimeDelta uptime_since_last;
195   static int64_t uptime_since_last_storage = 0;
196   if (MonotonicDurationHelper(&uptime_since_last_storage, &uptime_since_last)) {
197     metric = metrics::kMetricCheckTimeSinceLastCheckUptimeMinutes;
198     metrics_lib_->SendToUMA(metric,
199                             uptime_since_last.InMinutes(),
200                             0,             // min: 0 min
201                             30 * 24 * 60,  // max: 30 days
202                             50);           // num_buckets
203   }
204 
205   // First section of target version specified for the update.
206   if (SystemState::Get()->request_params()) {
207     string target_version =
208         SystemState::Get()->request_params()->target_version_prefix();
209     value = utils::VersionPrefix(target_version);
210     if (value != 0) {
211       metric = metrics::kMetricCheckTargetVersion;
212       metrics_lib_->SendSparseToUMA(metric, value);
213       if (SystemState::Get()->request_params()->rollback_allowed()) {
214         metric = metrics::kMetricCheckRollbackTargetVersion;
215         metrics_lib_->SendSparseToUMA(metric, value);
216       }
217     }
218   }
219 }
220 
ReportAbnormallyTerminatedUpdateAttemptMetrics()221 void MetricsReporterOmaha::ReportAbnormallyTerminatedUpdateAttemptMetrics() {
222   string metric = metrics::kMetricAttemptResult;
223   metrics::AttemptResult attempt_result =
224       metrics::AttemptResult::kAbnormalTermination;
225 
226   metrics_lib_->SendEnumToUMA(
227       metric,
228       static_cast<int>(attempt_result),
229       static_cast<int>(metrics::AttemptResult::kNumConstants));
230 }
231 
ReportUpdateAttemptMetrics(int attempt_number,PayloadType payload_type,base::TimeDelta duration,base::TimeDelta duration_uptime,int64_t payload_size,metrics::AttemptResult attempt_result,ErrorCode internal_error_code)232 void MetricsReporterOmaha::ReportUpdateAttemptMetrics(
233     int attempt_number,
234     PayloadType payload_type,
235     base::TimeDelta duration,
236     base::TimeDelta duration_uptime,
237     int64_t payload_size,
238     metrics::AttemptResult attempt_result,
239     ErrorCode internal_error_code) {
240   string metric = metrics::kMetricAttemptNumber;
241   metrics_lib_->SendToUMA(metric,
242                           attempt_number,
243                           0,    // min: 0 attempts
244                           49,   // max: 49 attempts
245                           50);  // num_buckets
246 
247   metric = metrics::kMetricAttemptPayloadType;
248   metrics_lib_->SendEnumToUMA(metric, payload_type, kNumPayloadTypes);
249 
250   metric = metrics::kMetricAttemptDurationMinutes;
251   metrics_lib_->SendToUMA(metric,
252                           duration.InMinutes(),
253                           0,             // min: 0 min
254                           10 * 24 * 60,  // max: 10 days
255                           50);           // num_buckets
256 
257   metric = metrics::kMetricAttemptDurationUptimeMinutes;
258   metrics_lib_->SendToUMA(metric,
259                           duration_uptime.InMinutes(),
260                           0,             // min: 0 min
261                           10 * 24 * 60,  // max: 10 days
262                           50);           // num_buckets
263 
264   metric = metrics::kMetricAttemptPayloadSizeMiB;
265   int64_t payload_size_mib = payload_size / kNumBytesInOneMiB;
266   metrics_lib_->SendToUMA(metric,
267                           payload_size_mib,
268                           0,     // min: 0 MiB
269                           1024,  // max: 1024 MiB = 1 GiB
270                           50);   // num_buckets
271 
272   metric = metrics::kMetricAttemptResult;
273   metrics_lib_->SendEnumToUMA(
274       metric,
275       static_cast<int>(attempt_result),
276       static_cast<int>(metrics::AttemptResult::kNumConstants));
277 
278   if (internal_error_code != ErrorCode::kSuccess) {
279     ReportInternalErrorCode(internal_error_code);
280   }
281 
282   base::TimeDelta time_since_last;
283   if (WallclockDurationHelper(kPrefsMetricsAttemptLastReportingTime,
284                               &time_since_last)) {
285     metric = metrics::kMetricAttemptTimeSinceLastAttemptMinutes;
286     metrics_lib_->SendToUMA(metric,
287                             time_since_last.InMinutes(),
288                             0,             // min: 0 min
289                             30 * 24 * 60,  // max: 30 days
290                             50);           // num_buckets
291   }
292 
293   static int64_t uptime_since_last_storage = 0;
294   base::TimeDelta uptime_since_last;
295   if (MonotonicDurationHelper(&uptime_since_last_storage, &uptime_since_last)) {
296     metric = metrics::kMetricAttemptTimeSinceLastAttemptUptimeMinutes;
297     metrics_lib_->SendToUMA(metric,
298                             uptime_since_last.InMinutes(),
299                             0,             // min: 0 min
300                             30 * 24 * 60,  // max: 30 days
301                             50);           // num_buckets
302   }
303 }
304 
ReportUpdateAttemptDownloadMetrics(int64_t payload_bytes_downloaded,int64_t payload_download_speed_bps,DownloadSource download_source,metrics::DownloadErrorCode payload_download_error_code,metrics::ConnectionType connection_type)305 void MetricsReporterOmaha::ReportUpdateAttemptDownloadMetrics(
306     int64_t payload_bytes_downloaded,
307     int64_t payload_download_speed_bps,
308     DownloadSource download_source,
309     metrics::DownloadErrorCode payload_download_error_code,
310     metrics::ConnectionType connection_type) {
311   string metric = metrics::kMetricAttemptPayloadBytesDownloadedMiB;
312   int64_t payload_bytes_downloaded_mib =
313       payload_bytes_downloaded / kNumBytesInOneMiB;
314   metrics_lib_->SendToUMA(metric,
315                           payload_bytes_downloaded_mib,
316                           0,     // min: 0 MiB
317                           1024,  // max: 1024 MiB = 1 GiB
318                           50);   // num_buckets
319 
320   metric = metrics::kMetricAttemptPayloadDownloadSpeedKBps;
321   int64_t payload_download_speed_kbps = payload_download_speed_bps / 1000;
322   metrics_lib_->SendToUMA(metric,
323                           payload_download_speed_kbps,
324                           0,          // min: 0 kB/s
325                           10 * 1000,  // max: 10000 kB/s = 10 MB/s
326                           50);        // num_buckets
327 
328   metric = metrics::kMetricAttemptDownloadSource;
329   metrics_lib_->SendEnumToUMA(metric, download_source, kNumDownloadSources);
330 
331   if (payload_download_error_code != metrics::DownloadErrorCode::kUnset) {
332     metric = metrics::kMetricAttemptDownloadErrorCode;
333     metrics_lib_->SendSparseToUMA(
334         metric, static_cast<int>(payload_download_error_code));
335   }
336 
337   metric = metrics::kMetricAttemptConnectionType;
338   metrics_lib_->SendEnumToUMA(
339       metric,
340       static_cast<int>(connection_type),
341       static_cast<int>(metrics::ConnectionType::kNumConstants));
342 }
343 
ReportSuccessfulUpdateMetrics(int attempt_count,int updates_abandoned_count,PayloadType payload_type,int64_t payload_size,int64_t num_bytes_downloaded[kNumDownloadSources],int download_overhead_percentage,base::TimeDelta total_duration,base::TimeDelta total_duration_uptime,int reboot_count,int url_switch_count)344 void MetricsReporterOmaha::ReportSuccessfulUpdateMetrics(
345     int attempt_count,
346     int updates_abandoned_count,
347     PayloadType payload_type,
348     int64_t payload_size,
349     int64_t num_bytes_downloaded[kNumDownloadSources],
350     int download_overhead_percentage,
351     base::TimeDelta total_duration,
352     base::TimeDelta total_duration_uptime,
353     int reboot_count,
354     int url_switch_count) {
355   string metric = metrics::kMetricSuccessfulUpdatePayloadSizeMiB;
356   int64_t mbs = payload_size / kNumBytesInOneMiB;
357   metrics_lib_->SendToUMA(metric,
358                           mbs,
359                           0,     // min: 0 MiB
360                           1024,  // max: 1024 MiB = 1 GiB
361                           50);   // num_buckets
362 
363   int64_t total_bytes = 0;
364   int download_sources_used = 0;
365   for (int i = 0; i < kNumDownloadSources + 1; i++) {
366     DownloadSource source = static_cast<DownloadSource>(i);
367 
368     // Only consider this download source (and send byte counts) as
369     // having been used if we downloaded a non-trivial amount of bytes
370     // (e.g. at least 1 MiB) that contributed to the
371     // update. Otherwise we're going to end up with a lot of zero-byte
372     // events in the histogram.
373 
374     metric = metrics::kMetricSuccessfulUpdateBytesDownloadedMiB;
375     if (i < kNumDownloadSources) {
376       metric += utils::ToString(source);
377       mbs = num_bytes_downloaded[i] / kNumBytesInOneMiB;
378       total_bytes += num_bytes_downloaded[i];
379       if (mbs > 0)
380         download_sources_used |= (1 << i);
381     } else {
382       mbs = total_bytes / kNumBytesInOneMiB;
383     }
384 
385     if (mbs > 0) {
386       metrics_lib_->SendToUMA(metric,
387                               mbs,
388                               0,     // min: 0 MiB
389                               1024,  // max: 1024 MiB = 1 GiB
390                               50);   // num_buckets
391     }
392   }
393 
394   metric = metrics::kMetricSuccessfulUpdateDownloadSourcesUsed;
395   metrics_lib_->SendToUMA(metric,
396                           download_sources_used,
397                           0,                               // min
398                           (1 << kNumDownloadSources) - 1,  // max
399                           1 << kNumDownloadSources);       // num_buckets
400 
401   metric = metrics::kMetricSuccessfulUpdateDownloadOverheadPercentage;
402   metrics_lib_->SendToUMA(metric,
403                           download_overhead_percentage,
404                           0,     // min: 0% overhead
405                           1000,  // max: 1000% overhead
406                           50);   // num_buckets
407 
408   metric = metrics::kMetricSuccessfulUpdateUrlSwitchCount;
409   metrics_lib_->SendToUMA(metric,
410                           url_switch_count,
411                           0,    // min: 0 URL switches
412                           49,   // max: 49 URL switches
413                           50);  // num_buckets
414 
415   metric = metrics::kMetricSuccessfulUpdateTotalDurationMinutes;
416   metrics_lib_->SendToUMA(metric,
417                           static_cast<int>(total_duration.InMinutes()),
418                           0,              // min: 0 min
419                           365 * 24 * 60,  // max: 365 days ~= 1 year
420                           50);            // num_buckets
421 
422   metric = metrics::kMetricSuccessfulUpdateTotalDurationUptimeMinutes;
423   metrics_lib_->SendToUMA(metric,
424                           static_cast<int>(total_duration_uptime.InMinutes()),
425                           0,             // min: 0 min
426                           30 * 24 * 60,  // max: 30 days
427                           50);           // num_buckets
428 
429   metric = metrics::kMetricSuccessfulUpdateRebootCount;
430   metrics_lib_->SendToUMA(metric,
431                           reboot_count,
432                           0,    // min: 0 reboots
433                           49,   // max: 49 reboots
434                           50);  // num_buckets
435 
436   metric = metrics::kMetricSuccessfulUpdatePayloadType;
437   metrics_lib_->SendEnumToUMA(metric, payload_type, kNumPayloadTypes);
438 
439   metric = metrics::kMetricSuccessfulUpdateAttemptCount;
440   metrics_lib_->SendToUMA(metric,
441                           attempt_count,
442                           1,    // min: 1 attempt
443                           50,   // max: 50 attempts
444                           50);  // num_buckets
445 
446   metric = metrics::kMetricSuccessfulUpdateUpdatesAbandonedCount;
447   metrics_lib_->SendToUMA(metric,
448                           updates_abandoned_count,
449                           0,    // min: 0 counts
450                           49,   // max: 49 counts
451                           50);  // num_buckets
452 }
453 
ReportRollbackMetrics(metrics::RollbackResult result)454 void MetricsReporterOmaha::ReportRollbackMetrics(
455     metrics::RollbackResult result) {
456   string metric = metrics::kMetricRollbackResult;
457   int value = static_cast<int>(result);
458   metrics_lib_->SendEnumToUMA(
459       metric, value, static_cast<int>(metrics::RollbackResult::kNumConstants));
460 }
461 
ReportEnterpriseRollbackMetrics(bool success,const string & rollback_version)462 void MetricsReporterOmaha::ReportEnterpriseRollbackMetrics(
463     bool success, const string& rollback_version) {
464   int value = utils::VersionPrefix(rollback_version);
465   string metric = metrics::kMetricEnterpriseRollbackSuccess;
466   if (!success)
467     metric = metrics::kMetricEnterpriseRollbackFailure;
468   metrics_lib_->SendSparseToUMA(metric, value);
469 }
470 
ReportCertificateCheckMetrics(ServerToCheck server_to_check,CertificateCheckResult result)471 void MetricsReporterOmaha::ReportCertificateCheckMetrics(
472     ServerToCheck server_to_check, CertificateCheckResult result) {
473   string metric;
474   switch (server_to_check) {
475     case ServerToCheck::kUpdate:
476       metric = metrics::kMetricCertificateCheckUpdateCheck;
477       break;
478     case ServerToCheck::kDownload:
479       metric = metrics::kMetricCertificateCheckDownload;
480       break;
481     case ServerToCheck::kNone:
482       return;
483   }
484   metrics_lib_->SendEnumToUMA(
485       metric,
486       static_cast<int>(result),
487       static_cast<int>(CertificateCheckResult::kNumConstants));
488 }
489 
ReportFailedUpdateCount(int target_attempt)490 void MetricsReporterOmaha::ReportFailedUpdateCount(int target_attempt) {
491   string metric = metrics::kMetricFailedUpdateCount;
492   metrics_lib_->SendToUMA(metric,
493                           target_attempt,
494                           1,   // min value
495                           50,  // max value
496                           kNumDefaultUmaBuckets);
497 }
498 
ReportTimeToReboot(int time_to_reboot_minutes)499 void MetricsReporterOmaha::ReportTimeToReboot(int time_to_reboot_minutes) {
500   string metric = metrics::kMetricTimeToRebootMinutes;
501   metrics_lib_->SendToUMA(metric,
502                           time_to_reboot_minutes,
503                           0,             // min: 0 minute
504                           30 * 24 * 60,  // max: 1 month (approx)
505                           kNumDefaultUmaBuckets);
506 }
507 
ReportInstallDateProvisioningSource(int source,int max)508 void MetricsReporterOmaha::ReportInstallDateProvisioningSource(int source,
509                                                                int max) {
510   metrics_lib_->SendEnumToUMA(metrics::kMetricInstallDateProvisioningSource,
511                               source,  // Sample.
512                               max);
513 }
514 
ReportInternalErrorCode(ErrorCode error_code)515 void MetricsReporterOmaha::ReportInternalErrorCode(ErrorCode error_code) {
516   auto metric = metrics::kMetricAttemptInternalErrorCode;
517   metrics_lib_->SendEnumToUMA(metric,
518                               static_cast<int>(error_code),
519                               static_cast<int>(ErrorCode::kUmaReportedMax));
520 }
521 
ReportKeyVersionMetrics(int kernel_min_version,int kernel_max_rollforward_version,bool kernel_max_rollforward_success)522 void MetricsReporterOmaha::ReportKeyVersionMetrics(
523     int kernel_min_version,
524     int kernel_max_rollforward_version,
525     bool kernel_max_rollforward_success) {
526   int value = kernel_min_version;
527   string metric = metrics::kMetricKernelMinVersion;
528   metrics_lib_->SendSparseToUMA(metric, value);
529 
530   value = kernel_max_rollforward_version;
531   metric = metrics::kMetricKernelMaxRollforwardVersion;
532   metrics_lib_->SendSparseToUMA(metric, value);
533 
534   bool bool_value = kernel_max_rollforward_success;
535   metric = metrics::kMetricKernelMaxRollforwardSetSuccess;
536   metrics_lib_->SendBoolToUMA(metric, bool_value);
537 }
538 
ReportEnterpriseUpdateSeenToDownloadDays(bool has_time_restriction_policy,int time_to_update_days)539 void MetricsReporterOmaha::ReportEnterpriseUpdateSeenToDownloadDays(
540     bool has_time_restriction_policy, int time_to_update_days) {
541   string metric =
542       has_time_restriction_policy
543           ? metrics::kMetricSuccessfulUpdateDurationFromSeenTimeRestrictedDays
544           : metrics::kMetricSuccessfulUpdateDurationFromSeenDays;
545 
546   metrics_lib_->SendToUMA(metric,
547                           time_to_update_days,
548                           1,       // min: 1 days
549                           6 * 30,  // max: 6 months (approx)
550                           50);     // num_buckets
551 }
552 
WallclockDurationHelper(const std::string & state_variable_key,TimeDelta * out_duration)553 bool MetricsReporterOmaha::WallclockDurationHelper(
554     const std::string& state_variable_key,
555     TimeDelta* out_duration) {
556   bool ret = false;
557   Time now = SystemState::Get()->clock()->GetWallclockTime();
558   int64_t stored_value;
559   if (SystemState::Get()->prefs()->GetInt64(state_variable_key,
560                                             &stored_value)) {
561     Time stored_time = Time::FromInternalValue(stored_value);
562     if (stored_time > now) {
563       LOG(ERROR) << "Stored time-stamp used for " << state_variable_key
564                  << " is in the future.";
565     } else {
566       *out_duration = now - stored_time;
567       ret = true;
568     }
569   }
570 
571   if (!SystemState::Get()->prefs()->SetInt64(state_variable_key,
572                                              now.ToInternalValue())) {
573     LOG(ERROR) << "Error storing time-stamp in " << state_variable_key;
574   }
575 
576   return ret;
577 }
578 
MonotonicDurationHelper(int64_t * storage,TimeDelta * out_duration)579 bool MetricsReporterOmaha::MonotonicDurationHelper(int64_t* storage,
580                                                    TimeDelta* out_duration) {
581   bool ret = false;
582   Time now = SystemState::Get()->clock()->GetMonotonicTime();
583   if (*storage != 0) {
584     Time stored_time = Time::FromInternalValue(*storage);
585     *out_duration = now - stored_time;
586     ret = true;
587   }
588   *storage = now.ToInternalValue();
589 
590   return ret;
591 }
592 
593 }  // namespace chromeos_update_engine
594