Index: components/browser_watcher/watcher_metrics_provider_win.cc |
diff --git a/components/browser_watcher/watcher_metrics_provider_win.cc b/components/browser_watcher/watcher_metrics_provider_win.cc |
index efe177bb998905a42ad20de208bb3860e567963d..c6ab669a03d5efef3a5a21f96630b127ea6ea490 100644 |
--- a/components/browser_watcher/watcher_metrics_provider_win.cc |
+++ b/components/browser_watcher/watcher_metrics_provider_win.cc |
@@ -7,15 +7,25 @@ |
#include <stddef.h> |
#include <limits> |
+#include <memory> |
+#include <set> |
#include <vector> |
#include "base/bind.h" |
+#include "base/feature_list.h" |
+#include "base/metrics/histogram.h" |
+#include "base/metrics/histogram_base.h" |
+#include "base/metrics/histogram_macros.h" |
#include "base/metrics/sparse_histogram.h" |
#include "base/process/process.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/string_piece.h" |
#include "base/strings/utf_string_conversions.h" |
#include "base/win/registry.h" |
+#include "components/browser_watcher/features.h" |
+#include "components/browser_watcher/postmortem_report_collector.h" |
+#include "components/browser_watcher/stability_debugging_win.h" |
+#include "third_party/crashpad/crashpad/client/crash_report_database.h" |
namespace browser_watcher { |
@@ -185,6 +195,19 @@ void DeleteExitCodeRegistryKey(const base::string16& registry_path) { |
DVLOG(1) << "Failed to delete exit code key " << registry_path; |
} |
+enum CollectionInitializationStatus { |
+ INIT_SUCCESS = 0, |
+ UNKNOWN_DIR = 1, |
+ GET_STABILITY_FILE_PATH_FAILED = 2, |
+ CRASHPAD_DATABASE_INIT_FAILED = 3, |
+ INIT_STATUS_MAX = 4 |
+}; |
+ |
+void LogCollectionInitStatus(CollectionInitializationStatus status) { |
+ UMA_HISTOGRAM_ENUMERATION("ActivityTracker.Collect.InitStatus", status, |
+ INIT_STATUS_MAX); |
+} |
+ |
} // namespace |
const char WatcherMetricsProviderWin::kBrowserExitCodeHistogramName[] = |
@@ -192,12 +215,17 @@ const char WatcherMetricsProviderWin::kBrowserExitCodeHistogramName[] = |
WatcherMetricsProviderWin::WatcherMetricsProviderWin( |
const base::string16& registry_path, |
- base::TaskRunner* cleanup_io_task_runner) |
+ const base::FilePath& user_data_dir, |
+ const base::FilePath& crash_dir, |
+ base::TaskRunner* io_task_runner) |
: recording_enabled_(false), |
cleanup_scheduled_(false), |
registry_path_(registry_path), |
- cleanup_io_task_runner_(cleanup_io_task_runner) { |
- DCHECK(cleanup_io_task_runner_); |
+ user_data_dir_(user_data_dir), |
+ crash_dir_(crash_dir), |
+ io_task_runner_(io_task_runner), |
+ weak_ptr_factory_(this) { |
+ DCHECK(io_task_runner_); |
} |
WatcherMetricsProviderWin::~WatcherMetricsProviderWin() { |
@@ -212,7 +240,7 @@ void WatcherMetricsProviderWin::OnRecordingDisabled() { |
// When metrics reporting is disabled, the providers get an |
// OnRecordingDisabled notification at startup. Use that first notification |
// to issue the cleanup task. |
- cleanup_io_task_runner_->PostTask( |
+ io_task_runner_->PostTask( |
FROM_HERE, base::Bind(&DeleteExitCodeRegistryKey, registry_path_)); |
cleanup_scheduled_ = true; |
@@ -231,4 +259,65 @@ void WatcherMetricsProviderWin::ProvideStabilityMetrics( |
DeleteExitFunnels(registry_path_); |
} |
+void WatcherMetricsProviderWin::CollectPostmortemReports( |
+ const base::Closure& done_callback) { |
+ io_task_runner_->PostTaskAndReply( |
+ FROM_HERE, |
+ base::Bind( |
+ &WatcherMetricsProviderWin::CollectPostmortemReportsOnBlockingPool, |
+ weak_ptr_factory_.GetWeakPtr()), |
+ done_callback); |
+} |
+ |
+void WatcherMetricsProviderWin::CollectPostmortemReportsOnBlockingPool() { |
+ // Note: the feature controls both instrumentation and collection. |
+ bool is_stability_debugging_on = |
+ base::FeatureList::IsEnabled(browser_watcher::kStabilityDebuggingFeature); |
+ if (!is_stability_debugging_on) { |
+ // TODO(manzagop): delete possible leftover data. |
+ return; |
+ } |
+ |
+ SCOPED_UMA_HISTOGRAM_TIMER("ActivityTracker.Collect.TotalTime"); |
+ |
+ if (user_data_dir_.empty() || crash_dir_.empty()) { |
+ LOG(ERROR) << "User data directory or crash directory is unknown."; |
+ LogCollectionInitStatus(UNKNOWN_DIR); |
+ return; |
+ } |
+ |
+ // Determine the stability directory and the stability file for the current |
+ // process. |
+ base::FilePath stability_dir = GetStabilityDir(user_data_dir_); |
+ base::FilePath current_stability_file; |
+ if (!GetStabilityFileForProcess(base::Process::Current(), user_data_dir_, |
+ ¤t_stability_file)) { |
+ LOG(ERROR) << "Failed to get the current stability file."; |
+ LogCollectionInitStatus(GET_STABILITY_FILE_PATH_FAILED); |
+ return; |
+ } |
+ const std::set<base::FilePath>& excluded_debug_files = { |
+ current_stability_file}; |
+ |
+ // Create a database. Note: Chrome already has a g_database in crashpad.cc but |
+ // it has internal linkage. Create a new one. |
+ std::unique_ptr<crashpad::CrashReportDatabase> crashpad_database = |
+ crashpad::CrashReportDatabase::InitializeWithoutCreating(crash_dir_); |
+ if (!crashpad_database) { |
+ LOG(ERROR) << "Failed to initialize a CrashPad database."; |
+ LogCollectionInitStatus(CRASHPAD_DATABASE_INIT_FAILED); |
+ return; |
+ } |
+ |
+ // Note: not caching the histogram pointer as this function isn't expected to |
+ // be called multiple times. |
+ LogCollectionInitStatus(INIT_SUCCESS); |
+ |
+ // TODO(manzagop): fix incorrect version attribution on update. |
+ PostmortemReportCollector collector; |
+ collector.CollectAndSubmitForUpload(stability_dir, GetStabilityFilePattern(), |
+ excluded_debug_files, |
+ crashpad_database.get()); |
+} |
+ |
} // namespace browser_watcher |