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

Unified Diff: components/metrics/reporting_service.cc

Issue 2608833002: Move logic for uploading logs into a ReportingService object. (Closed)
Patch Set: Rebase again 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/metrics/reporting_service.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/metrics/reporting_service.cc
diff --git a/components/metrics/reporting_service.cc b/components/metrics/reporting_service.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a541b298be8ffc829b7ba076f429ded46ffb0f29
--- /dev/null
+++ b/components/metrics/reporting_service.cc
@@ -0,0 +1,197 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// ReportingService handles uploading serialized logs to a server.
+
+#include "components/metrics/reporting_service.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "components/metrics/data_use_tracker.h"
+#include "components/metrics/log_store.h"
+#include "components/metrics/metrics_log_uploader.h"
+#include "components/metrics/metrics_service_client.h"
+#include "components/metrics/metrics_upload_scheduler.h"
+
+namespace metrics {
+
+// static
+void ReportingService::RegisterPrefs(PrefRegistrySimple* registry) {
+ DataUseTracker::RegisterPrefs(registry);
+}
+
+ReportingService::ReportingService(MetricsServiceClient* client,
+ PrefService* local_state,
+ size_t max_retransmit_size)
+ : client_(client),
+ max_retransmit_size_(max_retransmit_size),
+ reporting_active_(false),
+ log_upload_in_progress_(false),
+ data_use_tracker_(DataUseTracker::Create(local_state)),
+ self_ptr_factory_(this) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(client_);
+ DCHECK(local_state);
+}
+
+ReportingService::~ReportingService() {
+ DisableReporting();
+}
+
+void ReportingService::Initialize() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ log_store()->LoadPersistedUnsentLogs();
+ base::Closure send_next_log_callback = base::Bind(
+ &ReportingService::SendNextLog, self_ptr_factory_.GetWeakPtr());
+ upload_scheduler_.reset(new MetricsUploadScheduler(send_next_log_callback));
+}
+
+void ReportingService::Start() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (reporting_active_)
+ upload_scheduler_->Start();
+}
+
+void ReportingService::Stop() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (upload_scheduler_)
+ upload_scheduler_->Stop();
+}
+
+void ReportingService::EnableReporting() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (reporting_active_)
+ return;
+ reporting_active_ = true;
+ Start();
+}
+
+void ReportingService::DisableReporting() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ reporting_active_ = false;
+ Stop();
+}
+
+bool ReportingService::reporting_active() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return reporting_active_;
+}
+
+void ReportingService::UpdateMetricsUsagePrefs(const std::string& service_name,
+ int message_size,
+ bool is_cellular) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (data_use_tracker_) {
+ data_use_tracker_->UpdateMetricsUsagePrefs(service_name, message_size,
+ is_cellular);
+ }
+}
+
+//------------------------------------------------------------------------------
+// private methods
+//------------------------------------------------------------------------------
+
+void ReportingService::SendNextLog() {
+ DVLOG(1) << "SendNextLog";
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!last_upload_finish_time_.is_null()) {
+ LogActualUploadInterval(base::TimeTicks::Now() - last_upload_finish_time_);
+ last_upload_finish_time_ = base::TimeTicks();
+ }
+ if (!reporting_active()) {
+ upload_scheduler_->StopAndUploadCancelled();
+ return;
+ }
+ if (!log_store()->has_unsent_logs()) {
+ // Should only get here if serializing the log failed somehow.
+ upload_scheduler_->Stop();
+ // Reset backoff interval
+ upload_scheduler_->UploadFinished(true);
+ return;
+ }
+ if (!log_store()->has_staged_log())
+ log_store()->StageNextLog();
+
+ // Proceed to stage the log for upload if log size satisfies cellular log
+ // upload constrains.
+ bool upload_canceled = false;
+ bool is_cellular_logic = client_->IsUMACellularUploadLogicEnabled();
+ if (is_cellular_logic && data_use_tracker_ &&
+ !data_use_tracker_->ShouldUploadLogOnCellular(
+ log_store()->staged_log_hash().size())) {
+ upload_scheduler_->UploadOverDataUsageCap();
+ upload_canceled = true;
+ } else {
+ SendStagedLog();
+ }
+ if (is_cellular_logic) {
+ LogCellularConstraint(upload_canceled);
+ }
+}
+
+void ReportingService::SendStagedLog() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(log_store()->has_staged_log());
+ if (!log_store()->has_staged_log())
+ return;
+
+ DCHECK(!log_upload_in_progress_);
+ log_upload_in_progress_ = true;
+
+ if (!log_uploader_) {
+ log_uploader_ = client_->CreateUploader(
+ GetUploadUrl(), upload_mime_type(), service_type(),
+ base::Bind(&ReportingService::OnLogUploadComplete,
+ self_ptr_factory_.GetWeakPtr()));
+ }
+
+ const std::string hash =
+ base::HexEncode(log_store()->staged_log_hash().data(),
+ log_store()->staged_log_hash().size());
+ log_uploader_->UploadLog(log_store()->staged_log(), hash);
+}
+
+void ReportingService::OnLogUploadComplete(int response_code) {
+ DVLOG(1) << "OnLogUploadComplete:" << response_code;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(log_upload_in_progress_);
+ log_upload_in_progress_ = false;
+
+ // Log a histogram to track response success vs. failure rates.
+ LogResponseCode(response_code);
+
+ bool upload_succeeded = response_code == 200;
+
+ // Provide boolean for error recovery (allow us to ignore response_code).
+ bool discard_log = false;
+ const size_t log_size = log_store()->staged_log().length();
+ if (upload_succeeded) {
+ LogSuccess(log_size);
+ } else if (log_size > max_retransmit_size_) {
+ LogLargeRejection(log_size);
+ discard_log = true;
+ } else if (response_code == 400) {
+ // Bad syntax. Retransmission won't work.
+ discard_log = true;
+ }
+
+ if (upload_succeeded || discard_log) {
+ log_store()->DiscardStagedLog();
+ // Store the updated list to disk now that the removed log is uploaded.
+ log_store()->PersistUnsentLogs();
+ }
+
+ // Error 400 indicates a problem with the log, not with the server, so
+ // don't consider that a sign that the server is in trouble.
+ bool server_is_healthy = upload_succeeded || response_code == 400;
+ if (!log_store()->has_unsent_logs()) {
+ DVLOG(1) << "Stopping upload_scheduler_.";
+ upload_scheduler_->Stop();
+ }
+ upload_scheduler_->UploadFinished(server_is_healthy);
+}
+
+} // namespace metrics
« no previous file with comments | « components/metrics/reporting_service.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698