Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / metrics / metrics_reporting_scheduler.cc
blob944da432b1eb681175c2bcbebd9d753da449f069
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/metrics/metrics_reporting_scheduler.h"
7 #include "base/compiler_specific.h"
8 #include "chrome/browser/metrics/metrics_service.h"
10 using base::TimeDelta;
12 namespace {
14 // The delay, in seconds, after startup before sending the first log message.
15 #if defined(OS_ANDROID) || defined(OS_IOS)
16 // Sessions are more likely to be short on a mobile device, so handle the
17 // initial log quickly.
18 const int kInitialUploadIntervalSeconds = 15;
19 #else
20 const int kInitialUploadIntervalSeconds = 60;
21 #endif
23 // The delay, in seconds, between uploading when there are queued logs from
24 // previous sessions to send.
25 #if defined(OS_ANDROID) || defined(OS_IOS)
26 // Sending in a burst is better on a mobile device, since keeping the radio on
27 // is very expensive.
28 const int kUnsentLogsIntervalSeconds = 3;
29 #else
30 const int kUnsentLogsIntervalSeconds = 15;
31 #endif
33 // Standard interval between log uploads, in seconds.
34 #if defined(OS_ANDROID) || defined(OS_IOS)
35 const int kStandardUploadIntervalSeconds = 5 * 60; // Five minutes.
36 #else
37 const int kStandardUploadIntervalSeconds = 30 * 60; // Thirty minutes.
38 #endif
40 // When uploading metrics to the server fails, we progressively wait longer and
41 // longer before sending the next log. This backoff process helps reduce load
42 // on a server that is having issues.
43 // The following is the multiplier we use to expand that inter-log duration.
44 const double kBackoffMultiplier = 1.1;
46 // The maximum backoff multiplier.
47 const int kMaxBackoffMultiplier = 10;
49 enum InitSequence {
50 TIMER_FIRED_FIRST,
51 INIT_TASK_COMPLETED_FIRST,
52 INIT_SEQUENCE_ENUM_SIZE,
55 void LogMetricsInitSequence(InitSequence sequence) {
56 UMA_HISTOGRAM_ENUMERATION("UMA.InitSequence", sequence,
57 INIT_SEQUENCE_ENUM_SIZE);
60 } // anonymous namespace
62 MetricsReportingScheduler::MetricsReportingScheduler(
63 const base::Closure& upload_callback)
64 : upload_callback_(upload_callback),
65 upload_interval_(TimeDelta::FromSeconds(kInitialUploadIntervalSeconds)),
66 running_(false),
67 callback_pending_(false),
68 init_task_complete_(false),
69 waiting_for_init_task_complete_(false) {
72 MetricsReportingScheduler::~MetricsReportingScheduler() {}
74 void MetricsReportingScheduler::Start() {
75 running_ = true;
76 ScheduleNextUpload();
79 void MetricsReportingScheduler::Stop() {
80 running_ = false;
81 if (upload_timer_.IsRunning())
82 upload_timer_.Stop();
85 // Callback from MetricsService when the startup init task has completed.
86 void MetricsReportingScheduler::InitTaskComplete() {
87 DCHECK(!init_task_complete_);
88 init_task_complete_ = true;
89 if (waiting_for_init_task_complete_) {
90 waiting_for_init_task_complete_ = false;
91 TriggerUpload();
92 } else {
93 LogMetricsInitSequence(INIT_TASK_COMPLETED_FIRST);
97 void MetricsReportingScheduler::UploadFinished(bool server_is_healthy,
98 bool more_logs_remaining) {
99 DCHECK(callback_pending_);
100 callback_pending_ = false;
101 // If the server is having issues, back off. Otherwise, reset to default
102 // (unless there are more logs to send, in which case the next upload should
103 // happen sooner).
104 if (!server_is_healthy) {
105 BackOffUploadInterval();
106 } else if (more_logs_remaining) {
107 upload_interval_ = TimeDelta::FromSeconds(kUnsentLogsIntervalSeconds);
108 } else {
109 upload_interval_ = TimeDelta::FromSeconds(kStandardUploadIntervalSeconds);
112 if (running_)
113 ScheduleNextUpload();
116 void MetricsReportingScheduler::UploadCancelled() {
117 DCHECK(callback_pending_);
118 callback_pending_ = false;
119 if (running_)
120 ScheduleNextUpload();
123 void MetricsReportingScheduler::SetUploadIntervalForTesting(
124 base::TimeDelta interval) {
125 upload_interval_ = interval;
128 void MetricsReportingScheduler::TriggerUpload() {
129 // If the timer fired before the init task has completed, don't trigger the
130 // upload yet - wait for the init task to complete and do it then.
131 if (!init_task_complete_) {
132 LogMetricsInitSequence(TIMER_FIRED_FIRST);
133 waiting_for_init_task_complete_ = true;
134 return;
136 callback_pending_ = true;
137 upload_callback_.Run();
140 void MetricsReportingScheduler::ScheduleNextUpload() {
141 DCHECK(running_);
142 if (upload_timer_.IsRunning() || callback_pending_)
143 return;
145 upload_timer_.Start(FROM_HERE, upload_interval_, this,
146 &MetricsReportingScheduler::TriggerUpload);
149 void MetricsReportingScheduler::BackOffUploadInterval() {
150 DCHECK_GT(kBackoffMultiplier, 1.0);
151 upload_interval_ = TimeDelta::FromMicroseconds(
152 static_cast<int64>(kBackoffMultiplier *
153 upload_interval_.InMicroseconds()));
155 TimeDelta max_interval = kMaxBackoffMultiplier *
156 TimeDelta::FromSeconds(kStandardUploadIntervalSeconds);
157 if (upload_interval_ > max_interval || upload_interval_.InSeconds() < 0) {
158 upload_interval_ = max_interval;