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

Unified Diff: chrome/browser/metrics/chrome_setup_metrics_provider.cc

Issue 1537743006: Persist setup metrics and have Chrome report them during UMA upload. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@shared-histograms
Patch Set: Created 5 years 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
Index: chrome/browser/metrics/chrome_setup_metrics_provider.cc
diff --git a/chrome/browser/metrics/chrome_setup_metrics_provider.cc b/chrome/browser/metrics/chrome_setup_metrics_provider.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e68cd43f09f5e460c4f64ae41ce6c950818333ce
--- /dev/null
+++ b/chrome/browser/metrics/chrome_setup_metrics_provider.cc
@@ -0,0 +1,148 @@
+// Copyright 2015 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.
+
+#include "chrome/browser/metrics/chrome_setup_metrics_provider.h"
+
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/files/file.h"
+#include "base/files/file_util.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_base.h"
+#include "base/metrics/persistent_memory_allocator.h"
+#include "base/prefs/pref_service.h"
+#include "base/threading/worker_pool.h"
+#include "base/time/time.h"
+#include "chrome/installer/util/google_update_constants.h"
+#include "components/metrics/metrics_pref_names.h"
+#include "components/metrics/metrics_service.h"
+
+
+ChromeSetupMetricsProvider::ChromeSetupMetricsProvider(
+ metrics::MetricsService* metrics_service,
+ PrefService* local_state)
+ : metrics_found_(0),
+ metrics_service_(metrics_service),
+ pref_service_(local_state),
+ program_directory_(base::CommandLine::ForCurrentProcess()->GetProgram()
+ .DirName()) {
+ // Don't do any further actions if metrics_service is not valid (for testing).
+ if (!metrics_service_)
+ return;
+
+ // Start a background check for pending setup metrics so it can be uploaded
+ // during the initial report.
+ bool posted = base::WorkerPool::PostTask(
+ FROM_HERE,
+ base::Bind(&ChromeSetupMetricsProvider::CheckForSetupMetrics,
Alexei Svitkine (slow) 2015/12/21 16:54:53 In Chromium code, it's best practice to not have t
bcwhite 2015/12/22 12:51:30 Okay. I'm rewriting this to support multiple file
+ base::Unretained(this)),
+ false);
+ DCHECK(posted);
+}
+
+ChromeSetupMetricsProvider::~ChromeSetupMetricsProvider() {
+ // Destruction of this object can lead to failures because of a task
+ // posted on the Worker Pool or because the owned Memory Allocator has
+ // been passed to the Metrics Service. Both cases can only occur if
+ // a Metrics Service has been provided (i.e. not during testing).
+ if (metrics_service_) {
+ NOTREACHED();
+ // Removing the allocator may not be sufficient to avoid a crash (some
+ // Histogram could still be pointing to the memory) but it's the best
+ // that can be done.
+ if (metrics_allocator_)
+ metrics_service_->RemovePersistentMemorySegment(metrics_allocator_.get());
+ }
+}
+
+void ChromeSetupMetricsProvider::OnDidCreateMetricsLog() {
+ if (metrics_allocator_) {
+ // If an allocator has been created then the previous log collected all
+ // the metrics. The allocator can be released and the preferences updated
+ // to make sure it isn't reported again.
+ pref_service_->SetInt64(metrics::prefs::kSetupMetricsLastSeen,
+ base::Time::Now().ToInternalValue());
+ if (metrics_service_)
+ metrics_service_->RemovePersistentMemorySegment(metrics_allocator_.get());
Alexei Svitkine (slow) 2015/12/21 16:54:53 Can this functionality be done by a different help
bcwhite 2015/12/22 12:51:30 Not really. MetricsService is what owns the HSM a
+ metrics_allocator_.reset();
+ metrics_found_.store(false);
+ return;
+ }
+
+ if (metrics_found_.load(std::memory_order_acquire)) { // ACQ metrics_file
+ // A new file of setup metrics has been found. Attach to it and add it to
+ // the list of persistent allocators that need to have metrics reported.
+ DCHECK(metrics_file_);
+ if (base::FilePersistentMemoryAllocator::IsFileAcceptable(*metrics_file_)) {
+ metrics_allocator_.reset(new base::FilePersistentMemoryAllocator(
+ metrics_file_.release(), 0, std::string()));
+ if (!metrics_allocator_->IsCorrupt()) {
+ if (metrics_service_) {
+ metrics_service_->AddPersistentMemorySegment(
+ metrics_allocator_.get());
+ }
+ return;
+ }
+ }
+ // Something is fundamentally wrong with the file. Ignore it.
+ LOG(ERROR) << "Setup metrics file \""
+ << GetSetupMetricsFile().AsUTF8Unsafe()
+ << "\" is not valid -- ignored.";
+ metrics_allocator_.reset();
+ pref_service_->SetInt64(metrics::prefs::kSetupMetricsLastSeen,
+ base::Time::Now().ToInternalValue());
+ return;
+ }
+
+ // Don't do any further actions if metrics_service is not valid (for testing).
+ if (!metrics_service_)
+ return;
+
+ // Nothing else is going on so schedule a check to see if there are new
+ // setup metrics to load. If so, they will be reported during the next
+ // collection run after this one. The check is run off of the worker-
+ // pool so as to not cause delays on the main UI thread (which is currently
+ // where metric collection is done).
+ bool posted = base::WorkerPool::PostTask(
+ FROM_HERE,
+ base::Bind(&ChromeSetupMetricsProvider::CheckForSetupMetrics,
+ base::Unretained(this)),
+ false);
+ DCHECK(posted);
+}
+
+base::FilePath ChromeSetupMetricsProvider::GetSetupMetricsFile() {
+ return program_directory_.AppendASCII(
+ google_update::kSetupHistogramAllocatorName);
+}
+
+void ChromeSetupMetricsProvider::CheckForSetupMetrics() {
+ DCHECK(!metrics_found_.load());
+ DCHECK(!metrics_file_);
+
+ base::File::Info info;
+ if (!base::GetFileInfo(GetSetupMetricsFile(), &info) ||
+ info.is_directory || info.size == 0) {
+ return;
+ }
+
+ const base::Time last_seen = base::Time::FromInternalValue(
+ pref_service_->GetInt64(metrics::prefs::kSetupMetricsLastSeen));
+ if (last_seen >= info.last_modified)
+ return;
+
+ // A new file of setup metrics has been found. Map it into memory.
+ metrics_file_.reset(new base::MemoryMappedFile());
+ metrics_file_->Initialize(GetSetupMetricsFile());
+
+ // Tell main thread that metrics have been found.
+ metrics_found_.store(true, std::memory_order_release); // REL metrics_file
+}
+
+void ChromeSetupMetricsProvider::SetProgramDirectory(
+ const base::FilePath& dir) {
+ program_directory_ = dir;
+}

Powered by Google App Engine
This is Rietveld 408576698