Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(260)

Side by Side Diff: components/metrics/reporting_service.cc

Issue 2608833002: Move logic for uploading logs into a ReportingService object. (Closed)
Patch Set: Incorporate feedback Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // 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 // ReportingService handles uploading serialized logs to a server.
6
7 #include "components/metrics/reporting_service.h"
8
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "components/metrics/data_use_tracker.h"
14 #include "components/metrics/log_store.h"
15 #include "components/metrics/metrics_log_uploader.h"
16 #include "components/metrics/metrics_service_client.h"
17 #include "components/metrics/metrics_upload_scheduler.h"
18
19 namespace metrics {
20
21 // static
22 void ReportingService::RegisterPrefs(PrefRegistrySimple* registry) {
23 DataUseTracker::RegisterPrefs(registry);
24 }
25
26 ReportingService::ReportingService(MetricsServiceClient* client,
27 PrefService* local_state,
28 size_t max_retransmit_size)
29 : client_(client),
30 max_retransmit_size_(max_retransmit_size),
31 reporting_active_(false),
32 log_upload_in_progress_(false),
33 data_use_tracker_(DataUseTracker::Create(local_state)),
34 self_ptr_factory_(this) {
35 DCHECK(thread_checker_.CalledOnValidThread());
36 DCHECK(client_);
37 DCHECK(local_state);
38 }
39
40 ReportingService::~ReportingService() {
41 DisableReporting();
42 }
43
44 void ReportingService::Initialize() {
45 log_store()->LoadPersistedUnsentLogs();
46 DCHECK(thread_checker_.CalledOnValidThread());
47 base::Closure send_next_log_callback = base::Bind(
48 &ReportingService::SendNextLog, self_ptr_factory_.GetWeakPtr());
49 upload_scheduler_.reset(new MetricsUploadScheduler(send_next_log_callback));
50 }
51
52 void ReportingService::Start() {
53 if (reporting_active_)
54 upload_scheduler_->Start();
55 }
56
57 void ReportingService::Stop() {
58 if (upload_scheduler_)
59 upload_scheduler_->Stop();
60 }
61
62 void ReportingService::EnableReporting() {
63 if (reporting_active_)
64 return;
65 reporting_active_ = true;
66 Start();
67 }
68
69 void ReportingService::DisableReporting() {
70 reporting_active_ = false;
71 Stop();
72 }
73
74 bool ReportingService::reporting_active() const {
75 DCHECK(thread_checker_.CalledOnValidThread());
Alexei Svitkine (slow) 2017/03/01 16:06:29 Nit: Add these to all the other functions.
Steven Holte 2017/03/04 01:35:51 Done.
76 return reporting_active_;
77 }
78
79 void ReportingService::UpdateMetricsUsagePrefs(const std::string& service_name,
80 int message_size,
81 bool is_cellular) {
82 DCHECK(thread_checker_.CalledOnValidThread());
83 if (data_use_tracker_) {
84 data_use_tracker_->UpdateMetricsUsagePrefs(service_name, message_size,
85 is_cellular);
86 }
87 }
88
89 //------------------------------------------------------------------------------
90 // private methods
91 //------------------------------------------------------------------------------
92
93 void ReportingService::SendNextLog() {
94 DVLOG(1) << "SendNextLog";
95 DCHECK(thread_checker_.CalledOnValidThread());
96 if (!last_upload_finish_time_.is_null()) {
97 LogActualUploadInterval(base::TimeTicks::Now() - last_upload_finish_time_);
98 last_upload_finish_time_ = base::TimeTicks();
99 }
100 if (!reporting_active()) {
101 upload_scheduler_->StopAndUploadCancelled();
102 return;
103 }
104 if (!log_store()->has_unsent_logs()) {
105 // Should only get here if serializing the log failed somehow.
106 upload_scheduler_->Stop();
107 // Reset backoff interval
108 upload_scheduler_->UploadFinished(true);
109 return;
110 }
111 if (!log_store()->has_staged_log())
112 log_store()->StageNextLog();
113
114 // Proceed to stage the log for upload if log size satisfies cellular log
115 // upload constrains.
116 bool upload_canceled = false;
117 bool is_cellular_logic = client_->IsUMACellularUploadLogicEnabled();
118 if (is_cellular_logic && data_use_tracker_ &&
119 !data_use_tracker_->ShouldUploadLogOnCellular(
120 log_store()->staged_log_hash().size())) {
121 upload_scheduler_->UploadOverDataUsageCap();
122 upload_canceled = true;
123 } else {
124 SendStagedLog();
125 }
126 if (is_cellular_logic) {
127 LogCellularConstraint(upload_canceled);
128 }
129 }
130
131 void ReportingService::SendStagedLog() {
132 DCHECK(thread_checker_.CalledOnValidThread());
133 DCHECK(log_store()->has_staged_log());
134 if (!log_store()->has_staged_log())
135 return;
136
137 DCHECK(!log_upload_in_progress_);
138 log_upload_in_progress_ = true;
139
140 if (!log_uploader_) {
141 log_uploader_ = client_->CreateUploader(
142 upload_url(), upload_mime_type(), service_type(),
143 base::Bind(&ReportingService::OnLogUploadComplete,
144 self_ptr_factory_.GetWeakPtr()));
145 }
146
147 const std::string hash =
148 base::HexEncode(log_store()->staged_log_hash().data(),
149 log_store()->staged_log_hash().size());
150 log_uploader_->UploadLog(log_store()->staged_log(), hash);
151 }
152
153 void ReportingService::OnLogUploadComplete(int response_code) {
154 DVLOG(1) << "OnLogUploadComplete:" << response_code;
155 DCHECK(thread_checker_.CalledOnValidThread());
156 DCHECK(log_upload_in_progress_);
157 log_upload_in_progress_ = false;
158
159 // Log a histogram to track response success vs. failure rates.
160 LogResponseCode(response_code);
161
162 bool upload_succeeded = response_code == 200;
163
164 // Provide boolean for error recovery (allow us to ignore response_code).
165 bool discard_log = false;
166 const size_t log_size = log_store()->staged_log().length();
167 if (upload_succeeded) {
168 LogSuccess(log_size);
169 } else if (log_size > max_retransmit_size_) {
170 LogLargeRejection(log_size);
171 discard_log = true;
172 } else if (response_code == 400) {
173 // Bad syntax. Retransmission won't work.
174 discard_log = true;
175 }
176
177 if (upload_succeeded || discard_log) {
178 log_store()->DiscardStagedLog();
179 // Store the updated list to disk now that the removed log is uploaded.
180 log_store()->PersistUnsentLogs();
181 }
182
183 // Error 400 indicates a problem with the log, not with the server, so
184 // don't consider that a sign that the server is in trouble.
185 bool server_is_healthy = upload_succeeded || response_code == 400;
186 if (!log_store()->has_unsent_logs()) {
187 DVLOG(1) << "Stopping upload_scheduler_.";
188 upload_scheduler_->Stop();
189 }
190 upload_scheduler_->UploadFinished(server_is_healthy);
191 }
192
193 } // namespace metrics
OLDNEW
« components/metrics/reporting_service.h ('K') | « components/metrics/reporting_service.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698