| OLD | NEW |
| (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 DCHECK(thread_checker_.CalledOnValidThread()); |
| 46 base::Closure send_next_log_callback = base::Bind( |
| 47 &ReportingService::SendNextLog, self_ptr_factory_.GetWeakPtr()); |
| 48 upload_scheduler_.reset(new MetricsUploadScheduler(send_next_log_callback)); |
| 49 } |
| 50 |
| 51 void ReportingService::Start() { |
| 52 if (reporting_active_) |
| 53 upload_scheduler_->Start(); |
| 54 } |
| 55 |
| 56 void ReportingService::Stop() { |
| 57 if (upload_scheduler_) |
| 58 upload_scheduler_->Stop(); |
| 59 } |
| 60 |
| 61 void ReportingService::EnableReporting() { |
| 62 if (reporting_active_) |
| 63 return; |
| 64 reporting_active_ = true; |
| 65 Start(); |
| 66 } |
| 67 |
| 68 void ReportingService::DisableReporting() { |
| 69 reporting_active_ = false; |
| 70 Stop(); |
| 71 } |
| 72 |
| 73 bool ReportingService::reporting_active() const { |
| 74 DCHECK(thread_checker_.CalledOnValidThread()); |
| 75 return reporting_active_; |
| 76 } |
| 77 |
| 78 void ReportingService::UpdateMetricsUsagePrefs(const std::string& service_name, |
| 79 int message_size, |
| 80 bool is_cellular) { |
| 81 DCHECK(thread_checker_.CalledOnValidThread()); |
| 82 if (data_use_tracker_) { |
| 83 data_use_tracker_->UpdateMetricsUsagePrefs(service_name, message_size, |
| 84 is_cellular); |
| 85 } |
| 86 } |
| 87 |
| 88 //------------------------------------------------------------------------------ |
| 89 // private methods |
| 90 //------------------------------------------------------------------------------ |
| 91 |
| 92 void ReportingService::SendNextLog() { |
| 93 DVLOG(1) << "SendNextLog"; |
| 94 DCHECK(thread_checker_.CalledOnValidThread()); |
| 95 if (!last_upload_finish_time_.is_null()) { |
| 96 LogActualUploadInterval(base::TimeTicks::Now() - last_upload_finish_time_); |
| 97 last_upload_finish_time_ = base::TimeTicks(); |
| 98 } |
| 99 if (!reporting_active()) { |
| 100 upload_scheduler_->StopAndUploadCancelled(); |
| 101 return; |
| 102 } |
| 103 if (!log_store()->has_unsent_logs()) { |
| 104 // Should only get here if serializing the log failed somehow. |
| 105 upload_scheduler_->Stop(); |
| 106 // Reset backoff interval |
| 107 upload_scheduler_->UploadFinished(true); |
| 108 return; |
| 109 } |
| 110 if (!log_store()->has_staged_log()) |
| 111 log_store()->StageNextLog(); |
| 112 |
| 113 // Proceed to stage the log for upload if log size satisfies cellular log |
| 114 // upload constrains. |
| 115 bool upload_canceled = false; |
| 116 bool is_cellular_logic = client_->IsUMACellularUploadLogicEnabled(); |
| 117 if (is_cellular_logic && data_use_tracker_ && |
| 118 !data_use_tracker_->ShouldUploadLogOnCellular( |
| 119 log_store()->staged_log_hash().size())) { |
| 120 upload_scheduler_->UploadOverDataUsageCap(); |
| 121 upload_canceled = true; |
| 122 } else { |
| 123 SendStagedLog(); |
| 124 } |
| 125 if (is_cellular_logic) { |
| 126 LogCellularConstraint(upload_canceled); |
| 127 } |
| 128 } |
| 129 |
| 130 void ReportingService::SendStagedLog() { |
| 131 DCHECK(thread_checker_.CalledOnValidThread()); |
| 132 DCHECK(log_store()->has_staged_log()); |
| 133 if (!log_store()->has_staged_log()) |
| 134 return; |
| 135 |
| 136 DCHECK(!log_upload_in_progress_); |
| 137 log_upload_in_progress_ = true; |
| 138 |
| 139 if (!log_uploader_) { |
| 140 log_uploader_ = client_->CreateUploader( |
| 141 upload_url(), upload_mime_type(), service_type(), |
| 142 base::Bind(&ReportingService::OnLogUploadComplete, |
| 143 self_ptr_factory_.GetWeakPtr())); |
| 144 } |
| 145 |
| 146 const std::string hash = |
| 147 base::HexEncode(log_store()->staged_log_hash().data(), |
| 148 log_store()->staged_log_hash().size()); |
| 149 log_uploader_->UploadLog(log_store()->staged_log(), hash); |
| 150 } |
| 151 |
| 152 void ReportingService::OnLogUploadComplete(int response_code) { |
| 153 DVLOG(1) << "OnLogUploadComplete:" << response_code; |
| 154 DCHECK(thread_checker_.CalledOnValidThread()); |
| 155 DCHECK(log_upload_in_progress_); |
| 156 log_upload_in_progress_ = false; |
| 157 |
| 158 // Log a histogram to track response success vs. failure rates. |
| 159 LogResponseCode(response_code); |
| 160 |
| 161 bool upload_succeeded = response_code == 200; |
| 162 |
| 163 // Provide boolean for error recovery (allow us to ignore response_code). |
| 164 bool discard_log = false; |
| 165 const size_t log_size = log_store()->staged_log().length(); |
| 166 if (upload_succeeded) { |
| 167 LogSuccess(log_size); |
| 168 } else if (log_size > max_retransmit_size_) { |
| 169 LogLargeRejection(log_size); |
| 170 discard_log = true; |
| 171 } else if (response_code == 400) { |
| 172 // Bad syntax. Retransmission won't work. |
| 173 discard_log = true; |
| 174 } |
| 175 |
| 176 if (upload_succeeded || discard_log) { |
| 177 log_store()->DiscardStagedLog(); |
| 178 // Store the updated list to disk now that the removed log is uploaded. |
| 179 log_store()->PersistUnsentLogs(); |
| 180 } |
| 181 |
| 182 // Error 400 indicates a problem with the log, not with the server, so |
| 183 // don't consider that a sign that the server is in trouble. |
| 184 bool server_is_healthy = upload_succeeded || response_code == 400; |
| 185 if (!log_store()->has_unsent_logs()) { |
| 186 DVLOG(1) << "Stopping upload_scheduler_."; |
| 187 upload_scheduler_->Stop(); |
| 188 } |
| 189 upload_scheduler_->UploadFinished(server_is_healthy); |
| 190 } |
| 191 |
| 192 } // namespace metrics |
| OLD | NEW |