Commit 72e80adc authored by Sigurdur Asgeirsson's avatar Sigurdur Asgeirsson Committed by Commit Bot

Remove unused persistent browser watcher stability debugging code.

It's been a couple of years since this code was used, and the oncoming
refactoring will be easier without this in the way.

Bug: 1044707
Change-Id: Ic6e07b8f3ce61312d2c5a89d8af9850ea7510a2e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2032230Reviewed-by: default avatarJoe Mason <joenotcharles@chromium.org>
Reviewed-by: default avatarJesse Doherty <jwd@chromium.org>
Commit-Queue: Jesse Doherty <jwd@chromium.org>
Auto-Submit: Sigurður Ásgeirsson <siggi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#737444}
parent 55dc3f03
......@@ -40,7 +40,6 @@
#include "components/browser_watcher/stability_data_names.h"
#include "components/browser_watcher/stability_debugging.h"
#include "components/browser_watcher/stability_metrics.h"
#include "components/browser_watcher/stability_paths.h"
#include "components/browser_watcher/stability_report.pb.h"
#endif
......@@ -107,7 +106,7 @@ void RecordChromeModuleInfo(
global_tracker->RecordModuleInfo(module);
}
void SetupStabilityDebugging() {
void SetupExtendedCrashReporting() {
if (!base::FeatureList::IsEnabled(
browser_watcher::kExtendedCrashReportingFeature)) {
return;
......@@ -119,43 +118,14 @@ void SetupStabilityDebugging() {
const int kStackDepth = 4;
const uint64_t kAllocatorId = 0;
// Check whether activities are to be recorded persistently or only in-memory.
const bool in_memory_only = base::GetFieldTrialParamByFeatureAsBool(
browser_watcher::kExtendedCrashReportingFeature,
browser_watcher::kInMemoryOnlyParam, true);
if (in_memory_only) {
base::debug::GlobalActivityTracker::CreateWithAllocator(
std::make_unique<base::LocalPersistentMemoryAllocator>(
kMemorySize, kAllocatorId,
browser_watcher::kExtendedCrashReportingFeature.name),
kStackDepth, 0);
} else {
// Ensure the stability directory exists and determine the stability file's
// path.
base::FilePath user_data_dir;
if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir) ||
!base::CreateDirectory(
browser_watcher::GetStabilityDir(user_data_dir))) {
return;
}
browser_watcher::LogStabilityRecordEvent(
browser_watcher::StabilityRecordEvent::kStabilityDirectoryExists);
base::FilePath stability_file;
if (!browser_watcher::GetStabilityFileForProcess(
base::Process::Current(), user_data_dir, &stability_file)) {
return;
}
browser_watcher::LogStabilityRecordEvent(
browser_watcher::StabilityRecordEvent::kGotStabilityPath);
base::debug::GlobalActivityTracker::CreateWithFile(
stability_file, kMemorySize, kAllocatorId, "", kStackDepth);
}
base::debug::GlobalActivityTracker::CreateWithAllocator(
std::make_unique<base::LocalPersistentMemoryAllocator>(
kMemorySize, kAllocatorId,
browser_watcher::kExtendedCrashReportingFeature.name),
kStackDepth, 0);
// Track code activities (such as posting task, blocking on locks, and
// joining threads) that can cause hanging threads and general instability
base::debug::GlobalActivityTracker* global_tracker =
base::debug::GlobalActivityTracker::Get();
if (!global_tracker)
......@@ -168,6 +138,9 @@ void SetupStabilityDebugging() {
static browser_watcher::ActivityTrackerAnnotation activity_tracker_annotation(
allocator->data(), allocator->size());
// Record the main DLL module info for easier symbolization.
RecordChromeModuleInfo(global_tracker);
browser_watcher::LogStabilityRecordEvent(
browser_watcher::StabilityRecordEvent::kGotTracker);
// Record product, version, channel, special build and platform.
......@@ -197,32 +170,6 @@ void SetupStabilityDebugging() {
proc_data.SetInt(browser_watcher::kStabilityProcessType,
browser_watcher::ProcessState::BROWSER_PROCESS);
if (!in_memory_only) {
// Record information about chrome's module. We want this to be done early.
RecordChromeModuleInfo(global_tracker);
// Trigger a flush of the memory mapped file to maximize the chances of
// having a minimal amount of content in the stability file, even if
// the system crashes or loses power. Even running in the background,
// this is a potentially expensive operation, so done under an experiment
// to allow measuring the performance effects, if any.
const bool should_flush = base::GetFieldTrialParamByFeatureAsBool(
browser_watcher::kExtendedCrashReportingFeature,
browser_watcher::kInitFlushParam, false);
if (should_flush) {
base::PostTask(
FROM_HERE, {base::ThreadPool(), base::MayBlock()},
base::BindOnce(&base::PersistentMemoryAllocator::Flush,
base::Unretained(global_tracker->allocator()), true));
}
// Store a copy of the system profile in this allocator. There will be some
// delay before this gets populated, perhaps as much as a minute. Because
// of this, there is no need to flush it here.
metrics::GlobalPersistentSystemProfile::GetInstance()
->RegisterPersistentAllocator(global_tracker->allocator());
}
browser_watcher::RegisterStabilityVEH();
}
#endif // defined(OS_WIN)
......@@ -233,7 +180,7 @@ void SetupDesktopFieldTrials() {
prerender::ConfigureNoStatePrefetch();
SetupStunProbeTrial();
#if defined(OS_WIN)
SetupStabilityDebugging();
SetupExtendedCrashReporting();
#endif // defined(OS_WIN)
}
......
......@@ -60,7 +60,6 @@
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/browser_watcher/stability_paths.h"
#include "components/crash/core/common/crash_keys.h"
#include "components/history/core/browser/history_service.h"
#include "components/metrics/call_stack_profile_metrics_provider.h"
......@@ -539,14 +538,6 @@ void ChromeMetricsServiceClient::OnEnvironmentUpdate(std::string* environment) {
#endif // OS_WIN || OS_MACOSX || OS_ANDROID
}
void ChromeMetricsServiceClient::OnLogCleanShutdown() {
#if defined(OS_WIN)
base::FilePath user_data_dir;
if (base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
browser_watcher::MarkOwnStabilityFileDeleted(user_data_dir);
#endif // OS_WIN
}
void ChromeMetricsServiceClient::CollectFinalMetricsForLog(
base::OnceClosure done_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
......
......@@ -67,7 +67,6 @@ class ChromeMetricsServiceClient : public metrics::MetricsServiceClient,
metrics::SystemProfileProto::Channel GetChannel() override;
std::string GetVersionString() override;
void OnEnvironmentUpdate(std::string* serialized_environment) override;
void OnLogCleanShutdown() override;
void CollectFinalMetricsForLog(base::OnceClosure done_callback) override;
std::unique_ptr<metrics::MetricsLogUploader> CreateUploader(
const GURL& server_url,
......
......@@ -30,34 +30,14 @@ if (is_win) {
"watcher_metrics_provider_win.cc",
"watcher_metrics_provider_win.h",
]
deps = [
":postmortem_stability",
":stability_client",
"//base",
"//components/metrics",
"//third_party/crashpad/crashpad/client",
]
}
static_library("postmortem_stability") {
sources = [
"postmortem_minidump_writer.h",
"postmortem_minidump_writer_win.cc",
"postmortem_report_collector.cc",
"postmortem_report_collector.h",
]
deps = [
":stability_client",
":stability_common",
":stability_report_proto",
"//base",
"//components/metrics:metrics",
"//components/variations",
"//components/metrics",
"//third_party/crashpad/crashpad/client",
"//third_party/crashpad/crashpad/minidump",
"//third_party/crashpad/crashpad/util",
]
ldflags = [ "/DELAYLOAD:wevtapi.dll" ] # Only used after unclean shutdowns.
}
static_library("crash_stability") {
......@@ -106,8 +86,6 @@ if (is_win) {
"stability_debugging.h",
"stability_metrics.cc",
"stability_metrics.h",
"stability_paths.cc",
"stability_paths.h",
]
deps = [
"//base",
......@@ -121,10 +99,7 @@ if (is_win) {
"activity_tracker_annotation_unittest.cc",
"endsession_watcher_window_win_unittest.cc",
"exit_code_watcher_win_unittest.cc",
"postmortem_minidump_writer_win_unittest.cc",
"postmortem_report_collector_unittest.cc",
"stability_debugging_win_unittest.cc",
"stability_paths_unittest.cc",
"stability_report_extractor_unittest.cc",
"watcher_client_win_unittest.cc",
"watcher_metrics_provider_win_unittest.cc",
......@@ -134,7 +109,6 @@ if (is_win) {
deps = [
":browser_watcher",
":browser_watcher_client",
":postmortem_stability",
":stability_client",
":stability_common",
":stability_report_proto",
......@@ -164,7 +138,9 @@ if (is_win) {
executable("fetch_system_session_events") {
sources = [ "fetch_system_session_events_main_win.cc" ]
deps = [
":postmortem_stability",
":stability_client",
":stability_common",
":stability_report_proto",
"//base",
"//components/metrics:metrics",
]
......
......@@ -11,8 +11,4 @@ const base::Feature kExtendedCrashReportingFeature{
const char kInMemoryOnlyParam[] = "in_memory_only";
const char kInitFlushParam[] = "init_flush";
const char kCollectPostmortemParam[] = "collect_postmortem";
} // namespace browser_watcher
......@@ -17,14 +17,6 @@ extern const base::Feature kExtendedCrashReportingFeature;
// activity in-memory only.
extern const char kInMemoryOnlyParam[];
// Name of an experiment parameter that controls whether to perform an initial
// flush.
extern const char kInitFlushParam[];
// Name of an experiment parameter that controls whether to collect postmortem
// reports.
extern const char kCollectPostmortemParam[];
} // namespace browser_watcher
#endif // COMPONENTS_BROWSER_WATCHER_FEATURES_H_
// Copyright 2016 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.
#ifndef COMPONENTS_BROWSER_WATCHER_POSTMORTEM_MINIDUMP_WRITER_H_
#define COMPONENTS_BROWSER_WATCHER_POSTMORTEM_MINIDUMP_WRITER_H_
#include <stdint.h>
#include <string>
#include "components/browser_watcher/stability_report.pb.h"
#include "third_party/crashpad/crashpad/util/file/file_writer.h"
#include "third_party/crashpad/crashpad/util/misc/uuid.h"
namespace browser_watcher {
// Write to |minidump_file| a minimal minidump that wraps |report|. Returns
// true on success, false otherwise.
// Note: the caller owns |minidump_file| and is responsible for keeping it valid
// for this function's duration. |minidump_file| is expected to be empty
// and a binary stream.
bool WritePostmortemDump(crashpad::FileWriterInterface* minidump_file,
const crashpad::UUID& client_id,
const crashpad::UUID& report_id,
StabilityReport* report);
} // namespace browser_watcher
#endif // COMPONENTS_BROWSER_WATCHER_POSTMORTEM_MINIDUMP_WRITER_H_
// Copyright 2016 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 "components/browser_watcher/postmortem_minidump_writer.h"
#include <windows.h> // NOLINT
#include <dbghelp.h>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/win/scoped_handle.h"
#include "components/browser_watcher/stability_data_names.h"
#include "components/browser_watcher/stability_report.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/crashpad/crashpad/snapshot/minidump/process_snapshot_minidump.h"
#include "third_party/crashpad/crashpad/util/file/file_reader.h"
#include "third_party/crashpad/crashpad/util/misc/uuid.h"
namespace browser_watcher {
using crashpad::UUID;
const char kProductName[] = "some-product";
const char kExpectedProductName[] = "some-product_Postmortem";
const char kVersion[] = "51.0.2704.106";
const char kChannel[] = "some-channel";
const char kPlatform[] = "some-platform";
class WritePostmortemDumpTest : public testing::Test {
public:
void SetUp() override {
testing::Test::SetUp();
expected_client_id_.InitializeWithNew();
expected_report_id_.InitializeWithNew();
// Create a stability report.
// TODO(manzagop): flesh out the report once proto is more detailed.
ProcessState* process_state = expected_report_.add_process_states();
CodeModule* module = process_state->add_modules();
module->set_base_address(1024);
module->set_code_file("some_code_file.dll");
// Set up directory and path.
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
minidump_path_ = temp_dir_.GetPath().AppendASCII("minidump.dmp");
}
bool WriteDump(bool add_product_details) {
// Make a copy of the expected report as product details are stripped from
// the proto written to the minidump stream.
StabilityReport report(expected_report_);
if (add_product_details) {
google::protobuf::Map<std::string, TypedValue>& global_data =
*report.mutable_global_data();
global_data[kStabilityChannel].set_string_value(kChannel);
global_data[kStabilityPlatform].set_string_value(kPlatform);
global_data[kStabilityProduct].set_string_value(kProductName);
global_data[kStabilityVersion].set_string_value(kVersion);
}
crashpad::FileWriter writer;
if (!writer.Open(minidump_path_, crashpad::FileWriteMode::kCreateOrFail,
crashpad::FilePermissions::kWorldReadable)) {
return false;
}
return WritePostmortemDump(&writer, expected_client_id_,
expected_report_id_, &report);
}
const base::FilePath& minidump_path() { return minidump_path_; }
const UUID& expected_client_id() { return expected_client_id_; }
const UUID& expected_report_id() { return expected_report_id_; }
const StabilityReport& expected_report() { return expected_report_; }
private:
base::ScopedTempDir temp_dir_;
base::FilePath minidump_path_;
UUID expected_client_id_;
UUID expected_report_id_;
StabilityReport expected_report_;
};
TEST_F(WritePostmortemDumpTest, MissingProductDetailsFailureTest) {
ASSERT_FALSE(WriteDump(false));
}
TEST_F(WritePostmortemDumpTest, ValidateStabilityReportTest) {
ASSERT_TRUE(WriteDump(true));
// Read back the minidump to extract the proto.
// TODO(manzagop): rely on crashpad for reading the proto once crashpad
// supports it (https://crashpad.chromium.org/bug/10).
base::ScopedFILE minidump_file;
minidump_file.reset(base::OpenFile(minidump_path(), "rb"));
ASSERT_TRUE(minidump_file.get());
MINIDUMP_HEADER header = {};
ASSERT_EQ(1U, fread(&header, sizeof(header), 1, minidump_file.get()));
ASSERT_EQ(static_cast<ULONG32>(MINIDUMP_SIGNATURE), header.Signature);
ASSERT_EQ(2U, header.NumberOfStreams);
RVA directory_rva = header.StreamDirectoryRva;
MINIDUMP_DIRECTORY directory = {};
ASSERT_EQ(0, fseek(minidump_file.get(), directory_rva, SEEK_SET));
ASSERT_EQ(1U, fread(&directory, sizeof(directory), 1, minidump_file.get()));
ASSERT_EQ(0x4B6B0002U, directory.StreamType);
RVA report_rva = directory.Location.Rva;
ULONG32 report_size_bytes = directory.Location.DataSize;
std::string recovered_serialized_report;
recovered_serialized_report.resize(report_size_bytes);
ASSERT_EQ(0, fseek(minidump_file.get(), report_rva, SEEK_SET));
ASSERT_EQ(report_size_bytes, fread(&recovered_serialized_report.at(0), 1,
report_size_bytes, minidump_file.get()));
// Validate the recovered report.
std::string expected_serialized_report;
expected_report().SerializeToString(&expected_serialized_report);
ASSERT_EQ(expected_serialized_report, recovered_serialized_report);
StabilityReport recovered_report;
ASSERT_TRUE(recovered_report.ParseFromString(recovered_serialized_report));
}
TEST_F(WritePostmortemDumpTest, CrashpadCanReadTest) {
ASSERT_TRUE(WriteDump(true));
// Validate crashpad can read the produced minidump.
crashpad::FileReader minidump_file_reader;
ASSERT_TRUE(minidump_file_reader.Open(minidump_path()));
crashpad::ProcessSnapshotMinidump minidump_process_snapshot;
ASSERT_TRUE(minidump_process_snapshot.Initialize(&minidump_file_reader));
// Validate the crashpadinfo.
UUID client_id;
minidump_process_snapshot.ClientID(&client_id);
ASSERT_EQ(expected_client_id(), client_id);
UUID report_id;
minidump_process_snapshot.ReportID(&report_id);
ASSERT_EQ(expected_report_id(), report_id);
std::map<std::string, std::string> parameters =
minidump_process_snapshot.AnnotationsSimpleMap();
auto it = parameters.find("prod");
ASSERT_NE(parameters.end(), it);
ASSERT_EQ(kExpectedProductName, it->second);
it = parameters.find("ver");
ASSERT_NE(parameters.end(), it);
ASSERT_EQ(kVersion, it->second);
it = parameters.find("channel");
ASSERT_NE(parameters.end(), it);
ASSERT_EQ(kChannel, it->second);
it = parameters.find("plat");
ASSERT_NE(parameters.end(), it);
ASSERT_EQ(kPlatform, it->second);
}
} // namespace browser_watcher
// Copyright 2016 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 "components/browser_watcher/postmortem_report_collector.h"
#include <utility>
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/path_service.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/browser_watcher/postmortem_minidump_writer.h"
#include "components/browser_watcher/stability_data_names.h"
#include "third_party/crashpad/crashpad/client/settings.h"
#include "third_party/crashpad/crashpad/util/misc/uuid.h"
namespace browser_watcher {
using base::FilePath;
using crashpad::CrashReportDatabase;
namespace {
// DO NOT CHANGE VALUES. This is logged persistently in a histogram.
enum SystemSessionAnalysisStatus {
SYSTEM_SESSION_ANALYSIS_SUCCESS = 0,
SYSTEM_SESSION_ANALYSIS_NO_TIMESTAMP = 1,
SYSTEM_SESSION_ANALYSIS_NO_ANALYZER = 2,
SYSTEM_SESSION_ANALYSIS_FAILED = 3,
SYSTEM_SESSION_ANALYSIS_OUTSIDE_RANGE = 4,
SYSTEM_SESSION_ANALYSIS_STATUS_MAX = 5
};
bool GetStartTimestamp(
const google::protobuf::Map<std::string, TypedValue>& global_data,
base::Time* time) {
DCHECK(time);
const auto& it = global_data.find(kStabilityStartTimestamp);
if (it == global_data.end())
return false;
const TypedValue& value = it->second;
if (value.value_case() != TypedValue::kSignedValue)
return false;
*time = base::Time::FromDeltaSinceWindowsEpoch(
base::TimeDelta::FromMicroseconds(value.signed_value()));
return true;
}
void LogCollectionStatus(CollectionStatus status) {
base::UmaHistogramEnumeration("ActivityTracker.Collect.Status", status,
COLLECTION_STATUS_MAX);
}
} // namespace
PostmortemReportCollector::PostmortemReportCollector(
metrics::SystemSessionAnalyzer* analyzer)
: report_database_(nullptr), system_session_analyzer_(analyzer) {}
PostmortemReportCollector::PostmortemReportCollector(
const std::string& product_name,
const std::string& version_number,
const std::string& channel_name,
crashpad::CrashReportDatabase* report_database,
metrics::SystemSessionAnalyzer* analyzer)
: product_name_(product_name),
version_number_(version_number),
channel_name_(channel_name),
report_database_(report_database),
system_session_analyzer_(analyzer) {
DCHECK(!product_name_.empty());
DCHECK(!version_number.empty());
DCHECK(!channel_name.empty());
DCHECK_NE(nullptr, report_database);
}
PostmortemReportCollector::~PostmortemReportCollector() {}
void PostmortemReportCollector::Process(
const std::vector<base::FilePath>& stability_files) {
// Determine the crashpad client id.
crashpad::UUID client_id;
if (report_database_) {
crashpad::Settings* settings = report_database_->GetSettings();
if (settings) {
// If GetSettings() or GetClientID() fails client_id will be left at its
// default value, all zeroes, which is appropriate.
settings->GetClientID(&client_id);
}
}
for (const FilePath& file : stability_files) {
ProcessOneReport(client_id, file);
}
}
void PostmortemReportCollector::ProcessOneReport(
const crashpad::UUID& client_id,
const FilePath& file) {
LogCollectionStatus(COLLECTION_ATTEMPT);
// Note: the code below involves two notions of report: chrome internal state
// reports and the crashpad reports they get wrapped into.
// Collect the data from the debug file to a proto.
StabilityReport report_proto;
CollectionStatus status = CollectOneReport(file, &report_proto);
if (status != SUCCESS) {
// The file was empty, or there was an error collecting the data. This is
// not deemed an unclean shutdown. Detailed logging happens within the
// Collect function.
LogCollectionStatus(status);
if (!base::DeleteFile(file, false))
LogCollectionStatus(DEBUG_FILE_DELETION_FAILED);
return;
}
// Delete the stability file. If the file cannot be deleted, do not report its
// contents - it will be retried in a future processing run. Note that this
// approach can lead to under reporting and retries. However, under reporting
// is preferable to the over reporting that would happen with a file that
// cannot be deleted. Also note that the crash registration may still fail at
// this point: losing the report in such a case is deemed acceptable.
if (!base::DeleteFile(file, false)) {
DLOG(ERROR) << "Failed to delete " << file.value();
LogCollectionStatus(DEBUG_FILE_DELETION_FAILED);
return;
}
LogCollectionStatus(UNCLEAN_SHUTDOWN);
if (report_proto.system_state().session_state() == SystemState::UNCLEAN)
LogCollectionStatus(UNCLEAN_SESSION);
if (report_database_)
GenerateCrashReport(client_id, &report_proto);
}
CollectionStatus PostmortemReportCollector::CollectOneReport(
const base::FilePath& file,
StabilityReport* report) {
DCHECK(report);
std::unique_ptr<base::debug::GlobalActivityAnalyzer> global_analyzer =
base::debug::GlobalActivityAnalyzer::CreateWithFile(file);
if (!global_analyzer)
return ANALYZER_CREATION_FAILED;
CollectionStatus status = Extract(std::move(global_analyzer), report);
if (status != SUCCESS)
return status;
SetReporterDetails(report);
RecordSystemShutdownState(report);
return SUCCESS;
}
void PostmortemReportCollector::SetReporterDetails(
StabilityReport* report) const {
DCHECK(report);
google::protobuf::Map<std::string, TypedValue>& global_data =
*(report->mutable_global_data());
// Reporter version details. These are useful as the reporter may be of a
// different version.
global_data[kStabilityReporterChannel].set_string_value(channel_name());
#if defined(ARCH_CPU_X86)
global_data[kStabilityReporterPlatform].set_string_value(
std::string("Win32"));
#elif defined(ARCH_CPU_X86_64)
global_data[kStabilityReporterPlatform].set_string_value(
std::string("Win64"));
#endif
global_data[kStabilityReporterProduct].set_string_value(product_name());
global_data[kStabilityReporterVersion].set_string_value(version_number());
}
void PostmortemReportCollector::RecordSystemShutdownState(
StabilityReport* report) const {
DCHECK(report);
// The session state for the stability report, recorded to provided visibility
// into whether the system session was clean.
SystemState::SessionState session_state = SystemState::UNKNOWN;
// The status of the analysis, recorded to provide insight into the success
// or failure of the analysis.
SystemSessionAnalysisStatus status = SYSTEM_SESSION_ANALYSIS_SUCCESS;
base::Time time;
if (!GetStartTimestamp(report->global_data(), &time)) {
status = SYSTEM_SESSION_ANALYSIS_NO_TIMESTAMP;
} else if (!system_session_analyzer_) {
status = SYSTEM_SESSION_ANALYSIS_NO_ANALYZER;
} else {
metrics::SystemSessionAnalyzer::Status analyzer_status =
system_session_analyzer_->IsSessionUnclean(time);
switch (analyzer_status) {
case metrics::SystemSessionAnalyzer::FAILED:
status = SYSTEM_SESSION_ANALYSIS_FAILED;
break;
case metrics::SystemSessionAnalyzer::CLEAN:
session_state = SystemState::CLEAN;
break;
case metrics::SystemSessionAnalyzer::UNCLEAN:
session_state = SystemState::UNCLEAN;
break;
case metrics::SystemSessionAnalyzer::OUTSIDE_RANGE:
status = SYSTEM_SESSION_ANALYSIS_OUTSIDE_RANGE;
break;
}
}
report->mutable_system_state()->set_session_state(session_state);
base::UmaHistogramEnumeration(
"ActivityTracker.Collect.SystemSessionAnalysisStatus", status,
SYSTEM_SESSION_ANALYSIS_STATUS_MAX);
}
void PostmortemReportCollector::GenerateCrashReport(
const crashpad::UUID& client_id,
StabilityReport* report_proto) {
DCHECK_NE(nullptr, report_database_);
DCHECK(report_proto);
// Prepare a crashpad report.
std::unique_ptr<CrashReportDatabase::NewReport> new_report;
CrashReportDatabase::OperationStatus database_status =
report_database_->PrepareNewCrashReport(&new_report);
if (database_status != CrashReportDatabase::kNoError) {
LogCollectionStatus(PREPARE_NEW_CRASH_REPORT_FAILED);
return;
}
// Write the report to a minidump.
if (!WriteReportToMinidump(report_proto, client_id, new_report->ReportID(),
new_report->Writer())) {
LogCollectionStatus(WRITE_TO_MINIDUMP_FAILED);
return;
}
// Finalize the report wrt the report database. Note that this doesn't trigger
// an immediate upload, but Crashpad will eventually upload the report (as of
// writing, the delay is on the order of up to 15 minutes).
crashpad::UUID unused_report_id;
database_status = report_database_->FinishedWritingCrashReport(
std::move(new_report), &unused_report_id);
if (database_status != CrashReportDatabase::kNoError) {
LogCollectionStatus(FINISHED_WRITING_CRASH_REPORT_FAILED);
return;
}
LogCollectionStatus(SUCCESS);
}
bool PostmortemReportCollector::WriteReportToMinidump(
StabilityReport* report,
const crashpad::UUID& client_id,
const crashpad::UUID& report_id,
crashpad::FileWriterInterface* minidump_file) {
DCHECK(report);
return WritePostmortemDump(minidump_file, client_id, report_id, report);
}
} // namespace browser_watcher
// Copyright 2016 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.
//
// Following an unclean shutdown, a stability report can be collected and
// submitted for upload to a reporter.
#ifndef COMPONENTS_BROWSER_WATCHER_POSTMORTEM_REPORT_COLLECTOR_H_
#define COMPONENTS_BROWSER_WATCHER_POSTMORTEM_REPORT_COLLECTOR_H_
#include <stdio.h>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/debug/activity_analyzer.h"
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/strings/string16.h"
#include "components/browser_watcher/stability_report.pb.h"
#include "components/browser_watcher/stability_report_extractor.h"
#include "components/metrics/system_session_analyzer_win.h"
#include "third_party/crashpad/crashpad/client/crash_report_database.h"
#include "third_party/crashpad/crashpad/util/file/file_writer.h"
namespace browser_watcher {
// Performs postmortem stability data collection and analysis. The data is then
// reported as user metrics (e.g. to estimate the number of unclean shutdowns,
// or those attributable to the system) and, optionally, as crash reports for
// a more detailed view.
class PostmortemReportCollector {
public:
// Creates a postmortem report collector. The |product_name|, |version_number|
// and |channel_name| are used to set reporter information in postmortem
// crash reports. If |report_database| is set, postmortem crash reports are
// generated and registered against it. If |analyzer| is set, it used to
// analyze the containing system session.
PostmortemReportCollector(metrics::SystemSessionAnalyzer* analyzer);
PostmortemReportCollector(const std::string& product_name,
const std::string& version_number,
const std::string& channel_name,
crashpad::CrashReportDatabase* report_database,
metrics::SystemSessionAnalyzer* analyzer);
~PostmortemReportCollector();
// Analyzes |stability_files|, logs postmortem user metrics and optionally
// generates postmortem crash reports.
void Process(const std::vector<base::FilePath>& stability_files);
const std::string& product_name() const { return product_name_; }
const std::string& version_number() const { return version_number_; }
const std::string& channel_name() const { return channel_name_; }
private:
FRIEND_TEST_ALL_PREFIXES(PostmortemReportCollectorTest,
GetDebugStateFilePaths);
FRIEND_TEST_ALL_PREFIXES(PostmortemReportCollectorTest, CollectEmptyFile);
FRIEND_TEST_ALL_PREFIXES(PostmortemReportCollectorTest, CollectRandomFile);
FRIEND_TEST_ALL_PREFIXES(PostmortemReportCollectorCollectionTest,
CollectSuccess);
FRIEND_TEST_ALL_PREFIXES(
PostmortemReportCollectorCollectionFromGlobalTrackerTest,
LogCollection);
FRIEND_TEST_ALL_PREFIXES(
PostmortemReportCollectorCollectionFromGlobalTrackerTest,
ProcessUserDataCollection);
FRIEND_TEST_ALL_PREFIXES(
PostmortemReportCollectorCollectionFromGlobalTrackerTest,
FieldTrialCollection);
FRIEND_TEST_ALL_PREFIXES(
PostmortemReportCollectorCollectionFromGlobalTrackerTest,
ModuleCollection);
FRIEND_TEST_ALL_PREFIXES(
PostmortemReportCollectorCollectionFromGlobalTrackerTest,
SystemStateTest);
// Processes a stability file, reports user metrics and optionally generates a
// crash report.
void ProcessOneReport(const crashpad::UUID& client_id,
const base::FilePath& file);
virtual CollectionStatus CollectOneReport(
const base::FilePath& stability_file,
StabilityReport* report);
void SetReporterDetails(StabilityReport* report) const;
void RecordSystemShutdownState(StabilityReport* report) const;
void GenerateCrashReport(const crashpad::UUID& client_id,
StabilityReport* report_proto);
virtual bool WriteReportToMinidump(
StabilityReport* report,
const crashpad::UUID& client_id,
const crashpad::UUID& report_id,
crashpad::FileWriterInterface* minidump_file);
std::string product_name_;
std::string version_number_;
std::string channel_name_;
crashpad::CrashReportDatabase* report_database_; // Not owned.
metrics::SystemSessionAnalyzer* system_session_analyzer_; // Not owned.
DISALLOW_COPY_AND_ASSIGN(PostmortemReportCollector);
};
} // namespace browser_watcher
#endif // COMPONENTS_BROWSER_WATCHER_POSTMORTEM_REPORT_COLLECTOR_H_
......@@ -10,11 +10,11 @@ namespace browser_watcher {
// DO NOT REMOVE OR REORDER VALUES. This is logged persistently in a histogram.
enum class CollectOnCrashEvent {
kCollectAttempt,
kUserDataDirNotEmpty,
kPathExists,
kUserDataDirNotEmptyUnused, // No longer used.
kPathExistsUnused, // No longer used.
kReportExtractionSuccess,
kPmaSetDeletedFailed,
kOpenForDeleteFailed,
kPmaSetDeletedFailedUnused, // No longer used.
kOpenForDeleteFailedUnused, // No longer used.
kSuccess,
kInMemoryAnnotationExists,
// New values go here.
......@@ -24,12 +24,12 @@ enum class CollectOnCrashEvent {
// DO NOT REMOVE OR REORDER VALUES. This is logged persistently in a histogram.
enum class StabilityRecordEvent {
kRecordAttempt,
kStabilityDirectoryExists,
kGotStabilityPath,
kStabilityDirectoryExistsUnused, // No longer used.
kGotStabilityPathUnused, // No longer used.
kGotTracker,
kMarkDeleted,
kMarkDeletedGotFile,
kOpenForDeleteFailed,
kMarkDeletedUnused, // No longer used.
kMarkDeletedGotFileUnused, // No longer used.
kOpenForDeleteFailedUnused, // No longer used.
// New values go here.
kStabilityRecordEventMax
};
......
// 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.
#include "components/browser_watcher/stability_paths.h"
#if defined(OS_WIN)
#include <windows.h>
#endif // defined(OS_WIN)
#include <memory>
#include <string>
#include <utility>
#include "base/debug/activity_tracker.h"
#include "base/feature_list.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/memory_mapped_file.h"
#include "base/metrics/persistent_memory_allocator.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "components/browser_watcher/features.h"
#include "components/browser_watcher/stability_metrics.h"
#if defined(OS_WIN)
#include "third_party/crashpad/crashpad/util/misc/time.h"
namespace browser_watcher {
using base::FilePath;
using base::FilePersistentMemoryAllocator;
using base::MemoryMappedFile;
using base::PersistentMemoryAllocator;
namespace {
bool GetCreationTime(const base::Process& process, FILETIME* creation_time) {
FILETIME ignore;
return ::GetProcessTimes(process.Handle(), creation_time, &ignore, &ignore,
&ignore) != 0;
}
bool SetPmaFileDeleted(const base::FilePath& file_path) {
// Map the file read-write so it can guarantee consistency between
// the analyzer and any trackers that may still be active.
std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile());
if (!mmfile->Initialize(file_path, MemoryMappedFile::READ_WRITE))
return false;
if (!FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, true))
return false;
FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, 0,
base::StringPiece(), true);
allocator.SetMemoryState(PersistentMemoryAllocator::MEMORY_DELETED);
return true;
}
} // namespace
FilePath GetStabilityDir(const FilePath& user_data_dir) {
return user_data_dir.AppendASCII("Stability");
}
FilePath GetStabilityFileForProcess(base::ProcessId pid,
timeval creation_time,
const FilePath& user_data_dir) {
FilePath stability_dir = GetStabilityDir(user_data_dir);
constexpr uint64_t kMicrosecondsPerSecond = static_cast<uint64_t>(1E6);
int64_t creation_time_us =
creation_time.tv_sec * kMicrosecondsPerSecond + creation_time.tv_usec;
std::string file_name =
base::StringPrintf("%" CrPRIdPid "-%lld", pid, creation_time_us);
return stability_dir.AppendASCII(file_name).AddExtension(
base::PersistentMemoryAllocator::kFileExtension);
}
bool GetStabilityFileForProcess(const base::Process& process,
const FilePath& user_data_dir,
FilePath* file_path) {
DCHECK(file_path);
FILETIME creation_time;
if (!GetCreationTime(process, &creation_time))
return false;
// We rely on Crashpad's conversion to ensure the resulting filename is the
// same as on crash, when the creation time is obtained via Crashpad.
*file_path = GetStabilityFileForProcess(
process.Pid(), crashpad::FiletimeToTimevalEpoch(creation_time),
user_data_dir);
return true;
}
FilePath::StringType GetStabilityFilePattern() {
return FilePath::StringType(FILE_PATH_LITERAL("*-*")) +
base::PersistentMemoryAllocator::kFileExtension;
}
std::vector<FilePath> GetStabilityFiles(
const FilePath& stability_dir,
const FilePath::StringType& stability_file_pattern,
const std::set<FilePath>& excluded_stability_files) {
DCHECK_NE(true, stability_dir.empty());
DCHECK_NE(true, stability_file_pattern.empty());
std::vector<FilePath> paths;
base::FileEnumerator enumerator(stability_dir, false /* recursive */,
base::FileEnumerator::FILES,
stability_file_pattern);
FilePath path;
for (path = enumerator.Next(); !path.empty(); path = enumerator.Next()) {
if (excluded_stability_files.find(path) == excluded_stability_files.end())
paths.push_back(path);
}
return paths;
}
void MarkOwnStabilityFileDeleted(const base::FilePath& user_data_dir) {
base::debug::GlobalActivityTracker* global_tracker =
base::debug::GlobalActivityTracker::Get();
if (!global_tracker)
return; // No stability instrumentation.
global_tracker->MarkDeleted();
LogStabilityRecordEvent(StabilityRecordEvent::kMarkDeleted);
// Open (with delete) and then immediately close the file by going out of
// scope. This should cause the stability debugging file to be deleted prior
// to the next execution.
base::FilePath stability_file;
if (!GetStabilityFileForProcess(base::Process::Current(), user_data_dir,
&stability_file)) {
return;
}
LogStabilityRecordEvent(StabilityRecordEvent::kMarkDeletedGotFile);
base::File deleter(stability_file, base::File::FLAG_OPEN |
base::File::FLAG_READ |
base::File::FLAG_DELETE_ON_CLOSE);
if (!deleter.IsValid())
LogStabilityRecordEvent(StabilityRecordEvent::kOpenForDeleteFailed);
}
void MarkStabilityFileDeletedOnCrash(const base::FilePath& file_path) {
if (!SetPmaFileDeleted(file_path))
LogCollectOnCrashEvent(CollectOnCrashEvent::kPmaSetDeletedFailed);
base::File deleter(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
base::File::FLAG_DELETE_ON_CLOSE);
if (!deleter.IsValid())
LogCollectOnCrashEvent(CollectOnCrashEvent::kOpenForDeleteFailed);
}
} // namespace browser_watcher
#endif // defined(OS_WIN)
// 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.
#ifndef COMPONENTS_BROWSER_WATCHER_STABILITY_PATHS_H_
#define COMPONENTS_BROWSER_WATCHER_STABILITY_PATHS_H_
#include <set>
#include <vector>
#include "base/files/file_path.h"
#include "base/process/process.h"
#include "build/build_config.h"
#if defined(OS_WIN)
#include <winsock2.h>
#endif // defined(OS_WIN)
namespace browser_watcher {
#if defined(OS_WIN)
// Returns the stability debugging directory.
base::FilePath GetStabilityDir(const base::FilePath& user_data_dir);
// Returns the stability debugging path, which is based on pid and creation time
// to ensure uniqueness in the face of pid recycling.
base::FilePath GetStabilityFileForProcess(base::ProcessId pid,
timeval creation_time,
const base::FilePath& user_data_dir);
// On success, returns true and |path| contains the path to the stability file.
// On failure, returns false.
bool GetStabilityFileForProcess(const base::Process& process,
const base::FilePath& user_data_dir,
base::FilePath* path);
// Returns a pattern that matches file names returned by GetFileForProcess.
base::FilePath::StringType GetStabilityFilePattern();
// Returns files in |stability_dir| that match |stability_file_pattern|,
// excluding those in |excluded_stability_files|.
std::vector<base::FilePath> GetStabilityFiles(
const base::FilePath& stability_dir,
const base::FilePath::StringType& stability_file_pattern,
const std::set<base::FilePath>& excluded_stability_files);
// Sets the current process's stability file's state to deleted (via the
// GlobalActivityTracker) and opens the file for deletion. Metrics pertaining to
// stability recording are logged.
void MarkOwnStabilityFileDeleted(const base::FilePath& user_data_dir);
// Sets another process's stability file's state to deleted, then opens it for
// deletion. This function is meant for use by the crashpad handler; it logs
// metrics labelled as in the context of crash collection.
void MarkStabilityFileDeletedOnCrash(const base::FilePath& file_path);
#endif // defined(OS_WIN)
} // namespace browser_watcher
#endif // COMPONENTS_BROWSER_WATCHER_STABILITY_PATHS_H_
// 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.
#include "components/browser_watcher/stability_paths.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/process/process.h"
#include "base/test/multiprocess_test.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
namespace browser_watcher {
class StabilityPathsMultiProcTest : public base::MultiProcessTest {};
MULTIPROCESS_TEST_MAIN(DummyProcess) {
return 0;
}
TEST_F(StabilityPathsMultiProcTest, GetStabilityFileForProcessTest) {
const base::FilePath empty_path;
// Get the path for the current process.
base::FilePath stability_path;
ASSERT_TRUE(GetStabilityFileForProcess(base::Process::Current(), empty_path,
&stability_path));
// Ensure requesting a second time produces the same.
base::FilePath stability_path_two;
ASSERT_TRUE(GetStabilityFileForProcess(base::Process::Current(), empty_path,
&stability_path_two));
EXPECT_EQ(stability_path, stability_path_two);
// Ensure a different process has a different stability path.
base::Process process = SpawnChild("DummyProcess");
base::FilePath stability_path_other;
ASSERT_TRUE(
GetStabilityFileForProcess(process, empty_path, &stability_path_other));
EXPECT_NE(stability_path, stability_path_other);
}
TEST(StabilityPathsTest,
GetStabilityFilePatternMatchesGetStabilityFileForProcessResult) {
// GetStabilityFileForProcess file names must match GetStabilityFilePattern
// according to
// FileEnumerator's algorithm. We test this by writing out some files and
// validating what is matched.
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath user_data_dir = temp_dir.GetPath();
// Create the stability directory.
base::FilePath stability_dir = GetStabilityDir(user_data_dir);
ASSERT_TRUE(base::CreateDirectory(stability_dir));
// Write a stability file.
base::FilePath stability_file;
ASSERT_TRUE(GetStabilityFileForProcess(base::Process::Current(),
user_data_dir, &stability_file));
{
base::ScopedFILE file(base::OpenFile(stability_file, "w"));
ASSERT_TRUE(file.get());
}
// Write a file that shouldn't match.
base::FilePath non_matching_file =
stability_dir.AppendASCII("non_matching.foo");
{
base::ScopedFILE file(base::OpenFile(non_matching_file, "w"));
ASSERT_TRUE(file.get());
}
// Validate only the stability file matches.
base::FileEnumerator enumerator(stability_dir, false /* recursive */,
base::FileEnumerator::FILES,
GetStabilityFilePattern());
ASSERT_EQ(stability_file, enumerator.Next());
ASSERT_TRUE(enumerator.Next().empty());
}
TEST(StabilityPathsTest, GetStabilityFiles) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
// Create files.
std::vector<base::FilePath> expected_paths;
std::set<base::FilePath> excluded_paths;
{
// Matches the pattern.
base::FilePath path = temp_dir.GetPath().AppendASCII("foo1.pma");
base::ScopedFILE file(base::OpenFile(path, "w"));
ASSERT_NE(file.get(), nullptr);
expected_paths.push_back(path);
// Matches the pattern, but is excluded.
path = temp_dir.GetPath().AppendASCII("foo2.pma");
file.reset(base::OpenFile(path, "w"));
ASSERT_NE(file.get(), nullptr);
ASSERT_TRUE(excluded_paths.insert(path).second);
// Matches the pattern.
path = temp_dir.GetPath().AppendASCII("foo3.pma");
file.reset(base::OpenFile(path, "w"));
ASSERT_NE(file.get(), nullptr);
expected_paths.push_back(path);
// Does not match the pattern.
path = temp_dir.GetPath().AppendASCII("bar.baz");
file.reset(base::OpenFile(path, "w"));
ASSERT_NE(file.get(), nullptr);
}
EXPECT_THAT(GetStabilityFiles(temp_dir.GetPath(),
FILE_PATH_LITERAL("foo*.pma"), excluded_paths),
testing::UnorderedElementsAreArray(expected_paths));
}
} // namespace browser_watcher
......@@ -24,7 +24,6 @@
#include "components/browser_watcher/activity_tracker_annotation.h"
#include "components/browser_watcher/minidump_user_streams.h"
#include "components/browser_watcher/stability_metrics.h"
#include "components/browser_watcher/stability_paths.h"
#include "components/browser_watcher/stability_report_extractor.h"
#include "third_party/crashpad/crashpad/minidump/minidump_user_extension_stream_data_source.h"
#include "third_party/crashpad/crashpad/snapshot/annotation_snapshot.h"
......@@ -50,18 +49,6 @@ UniqueMallocPtr UncheckedAllocate(size_t size) {
return UniqueMallocPtr(raw_ptr);
}
base::FilePath GetStabilityFileName(
const base::FilePath& user_data_dir,
crashpad::ProcessSnapshot* process_snapshot) {
DCHECK(process_snapshot);
timeval creation_time = {};
process_snapshot->ProcessStartTime(&creation_time);
return GetStabilityFileForProcess(process_snapshot->ProcessID(),
creation_time, user_data_dir);
}
// A PersistentMemoryAllocator subclass that can take ownership of a buffer
// that's allocated with a malloc-compatible allocation function.
class MallocMemoryAllocator : public base::PersistentMemoryAllocator {
......@@ -135,18 +122,6 @@ bool CollectStabilityReport(
return true;
}
bool CollectPersistentReport(const base::FilePath& path,
StabilityReport* report) {
std::unique_ptr<base::debug::GlobalActivityAnalyzer> global_analyzer =
base::debug::GlobalActivityAnalyzer::CreateWithFile(path);
if (!CollectStabilityReport(std::move(global_analyzer), report))
return false;
MarkStabilityFileDeletedOnCrash(path);
return true;
}
void CollectSystemPerformanceMetrics(StabilityReport* report) {
// Grab system commit memory. Also best effort.
PERFORMANCE_INFORMATION perf_info = {sizeof(perf_info)};
......@@ -290,31 +265,18 @@ StabilityReportUserStreamDataSource::ProduceStreamData(
DCHECK(process_snapshot);
LogCollectOnCrashEvent(CollectOnCrashEvent::kCollectAttempt);
// See whether there is a persistent stability file.
StabilityReport report;
bool collected_report = false;
if (!user_data_dir_.empty()) {
LogCollectOnCrashEvent(CollectOnCrashEvent::kUserDataDirNotEmpty);
base::FilePath stability_file =
GetStabilityFileName(user_data_dir_, process_snapshot);
if (PathExists(stability_file)) {
LogCollectOnCrashEvent(CollectOnCrashEvent::kPathExists);
// See whether there's an activity tracking report beacon in the process'
// annotations.
std::unique_ptr<base::debug::GlobalActivityAnalyzer> global_analyzer =
MaybeGetInMemoryActivityAnalyzer(process_snapshot);
bool collected_report = false;
if (global_analyzer) {
LogCollectOnCrashEvent(CollectOnCrashEvent::kInMemoryAnnotationExists);
collected_report = CollectPersistentReport(stability_file, &report);
}
}
// If there isn't a persistent report, see whether there's a non-persistent
// report beacon in the process' annotations.
if (!collected_report) {
std::unique_ptr<base::debug::GlobalActivityAnalyzer> global_analyzer =
MaybeGetInMemoryActivityAnalyzer(process_snapshot);
if (global_analyzer) {
LogCollectOnCrashEvent(CollectOnCrashEvent::kInMemoryAnnotationExists);
collected_report =
CollectStabilityReport(std::move(global_analyzer), &report);
}
collected_report =
CollectStabilityReport(std::move(global_analyzer), &report);
}
CollectSystemPerformanceMetrics(&report);
......
......@@ -28,8 +28,6 @@
#include "base/task/task_traits.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_paths.h"
#include "components/metrics/system_session_analyzer_win.h"
#include "third_party/crashpad/crashpad/client/crash_report_database.h"
......@@ -160,11 +158,6 @@ enum CollectionInitializationStatus {
INIT_STATUS_MAX = 4
};
void LogCollectionInitStatus(CollectionInitializationStatus status) {
base::UmaHistogramEnumeration("ActivityTracker.Collect.InitStatus", status,
INIT_STATUS_MAX);
}
// Returns a task runner appropriate for running background tasks that perform
// file I/O.
scoped_refptr<base::TaskRunner> CreateBackgroundTaskRunner() {
......@@ -222,82 +215,4 @@ void WatcherMetricsProviderWin::ProvideStabilityMetrics(
RecordExitCodes(registry_path_);
}
void WatcherMetricsProviderWin::AsyncInit(base::OnceClosure done_callback) {
task_runner_->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&WatcherMetricsProviderWin::CollectPostmortemReportsImpl,
weak_ptr_factory_.GetWeakPtr()),
std::move(done_callback));
}
// TODO(manzagop): consider mechanisms for partial collection if this is to be
// used on a critical path.
void WatcherMetricsProviderWin::CollectPostmortemReportsImpl() {
SCOPED_UMA_HISTOGRAM_TIMER("ActivityTracker.Collect.TotalTime");
bool is_stability_debugging_on = base::FeatureList::IsEnabled(
browser_watcher::kExtendedCrashReportingFeature);
if (!is_stability_debugging_on) {
return; // TODO(manzagop): scan for possible data to delete?
}
if (user_data_dir_.empty() || crash_dir_.empty()) {
LogCollectionInitStatus(UNKNOWN_DIR);
return;
}
// Determine which files to harvest.
base::FilePath stability_dir = GetStabilityDir(user_data_dir_);
base::FilePath current_stability_file;
if (!GetStabilityFileForProcess(base::Process::Current(), user_data_dir_,
&current_stability_file)) {
LogCollectionInitStatus(GET_STABILITY_FILE_PATH_FAILED);
return;
}
const std::set<base::FilePath>& excluded_stability_files = {
current_stability_file};
std::vector<base::FilePath> stability_files = GetStabilityFiles(
stability_dir, GetStabilityFilePattern(), excluded_stability_files);
base::UmaHistogramCounts100("ActivityTracker.Collect.StabilityFileCount",
stability_files.size());
// If postmortem collection is disabled, delete the files.
const bool should_collect = base::GetFieldTrialParamByFeatureAsBool(
browser_watcher::kExtendedCrashReportingFeature,
browser_watcher::kCollectPostmortemParam, false);
// 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;
if (should_collect) {
crashpad_database =
crashpad::CrashReportDatabase::InitializeWithoutCreating(crash_dir_);
if (!crashpad_database) {
LOG(ERROR) << "Failed to initialize a CrashPad database.";
LogCollectionInitStatus(CRASHPAD_DATABASE_INIT_FAILED);
// Note: continue to processing the files anyway.
}
}
// Note: this is logged even when Crashpad database initialization fails.
LogCollectionInitStatus(INIT_SUCCESS);
const size_t kSystemSessionsToInspect = 5U;
metrics::SystemSessionAnalyzer analyzer(kSystemSessionsToInspect);
if (should_collect) {
base::string16 product_name, version_number, channel_name;
exe_details_cb_.Run(&product_name, &version_number, &channel_name);
PostmortemReportCollector collector(
base::UTF16ToUTF8(product_name), base::UTF16ToUTF8(version_number),
base::UTF16ToUTF8(channel_name), crashpad_database.get(), &analyzer);
collector.Process(stability_files);
} else {
PostmortemReportCollector collector(&analyzer);
collector.Process(stability_files);
}
}
} // namespace browser_watcher
......@@ -33,7 +33,6 @@ class WatcherMetricsProviderWin : public metrics::MetricsProvider {
~WatcherMetricsProviderWin() override;
// metrics::MetricsProvider implementation.
void AsyncInit(base::OnceClosure done_callback) override;
void OnRecordingEnabled() override;
void OnRecordingDisabled() override;
// Note: this function collects metrics, some of which are related to the
......@@ -50,9 +49,6 @@ class WatcherMetricsProviderWin : public metrics::MetricsProvider {
metrics::SystemProfileProto* system_profile_proto) override;
private:
// TODO(manzagop): avoid collecting reports for clean exits from the fast exit
// path.
void CollectPostmortemReportsImpl();
bool recording_enabled_;
bool cleanup_scheduled_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment