blob: 45e713540a725b2b7dbaacb0239330b1c1738775 [file] [log] [blame]
holte68395852017-01-10 20:40:211// Copyright 2017 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "components/metrics/metrics_upload_scheduler.h"
6
7#include <stdint.h>
8
9#include "base/metrics/histogram_macros.h"
10#include "build/build_config.h"
11#include "components/metrics/metrics_scheduler.h"
12
13namespace metrics {
14
15namespace {
16
17// The delay, in seconds, between uploading when there are queued logs from
18// previous sessions to send. Sending in a burst is better on a mobile device,
19// since keeping the radio on is very expensive, so prefer to keep this short.
20const int kUnsentLogsIntervalSeconds = 3;
21
22// When uploading metrics to the server fails, we progressively wait longer and
23// longer before sending the next log. This backoff process helps reduce load
24// on a server that is having issues.
25// The following is the multiplier we use to expand that inter-log duration.
26const double kBackoffMultiplier = 1.1;
27
28// The maximum backoff interval in minutes.
29const int kMaxBackoffIntervalMinutes = 10;
30
31// Minutes to wait if we are unable to upload due to data usage cap.
32const int kOverDataUsageIntervalMinutes = 5;
33
34// Increases the upload interval each time it's called, to handle the case
35// where the server is having issues.
36base::TimeDelta BackOffUploadInterval(base::TimeDelta interval) {
37 DCHECK_GT(kBackoffMultiplier, 1.0);
38 interval = base::TimeDelta::FromMicroseconds(static_cast<int64_t>(
39 kBackoffMultiplier * interval.InMicroseconds()));
40
41 base::TimeDelta max_interval =
42 base::TimeDelta::FromMinutes(kMaxBackoffIntervalMinutes);
43 if (interval > max_interval || interval.InSeconds() < 0) {
44 interval = max_interval;
45 }
46 return interval;
47}
48
49} // namespace
50
51MetricsUploadScheduler::MetricsUploadScheduler(
52 const base::Closure& upload_callback)
53 : MetricsScheduler(upload_callback),
54 upload_interval_(
55 base::TimeDelta::FromSeconds(kUnsentLogsIntervalSeconds)) {}
56
57MetricsUploadScheduler::~MetricsUploadScheduler() {}
58
59void MetricsUploadScheduler::UploadFinished(bool server_is_healthy) {
60 // If the server is having issues, back off. Otherwise, reset to default
61 // (unless there are more logs to send, in which case the next upload should
62 // happen sooner).
63 if (!server_is_healthy) {
64 upload_interval_ = BackOffUploadInterval(upload_interval_);
65 } else {
66 upload_interval_ = base::TimeDelta::FromSeconds(kUnsentLogsIntervalSeconds);
67 }
68 TaskDone(upload_interval_);
69}
70
71void MetricsUploadScheduler::UploadCancelled() {
72 TaskDone(upload_interval_);
73}
74
75void MetricsUploadScheduler::UploadOverDataUsageCap() {
76 TaskDone(base::TimeDelta::FromMinutes(kOverDataUsageIntervalMinutes));
77}
78
79void MetricsUploadScheduler::LogActualUploadInterval(base::TimeDelta interval) {
80 UMA_HISTOGRAM_CUSTOM_COUNTS("UMA.ActualLogUploadInterval",
81 interval.InMinutes(), 1,
82 base::TimeDelta::FromHours(12).InMinutes(), 50);
83}
84
85void MetricsUploadScheduler::TriggerTask() {
86 if (!last_upload_finish_time_.is_null()) {
87 LogActualUploadInterval(base::TimeTicks::Now() - last_upload_finish_time_);
88 last_upload_finish_time_ = base::TimeTicks();
89 }
90 MetricsScheduler::TriggerTask();
91}
92
93} // namespace metrics