Commit 2c3614ba authored by Sigurdur Asgeirsson's avatar Sigurdur Asgeirsson Committed by Commit Bot

Grab system and process memory metrics into crumbs at crash time.

Also grab the attempted allocation size when available.

Bug: 748630
Change-Id: Icdf48d6a0cebf27bab2c5965847f607966b03f50
Reviewed-on: https://chromium-review.googlesource.com/585357
Commit-Queue: Sigurður Ásgeirsson <siggi@chromium.org>
Reviewed-by: default avatarChris Hamilton <chrisha@chromium.org>
Reviewed-by: default avatarPierre-Antoine Manzagol (departed) <manzagop@chromium.org>
Cr-Commit-Position: refs/heads/master@{#492013}
parent c00100dc
...@@ -142,6 +142,27 @@ void PrintProcessState(FILE* out, ...@@ -142,6 +142,27 @@ void PrintProcessState(FILE* out,
const browser_watcher::ProcessState& process) { const browser_watcher::ProcessState& process) {
fprintf(out, "Process %lld (%d threads)\n", process.process_id(), fprintf(out, "Process %lld (%d threads)\n", process.process_id(),
process.threads_size()); process.threads_size());
if (process.has_memory_state() &&
process.memory_state().has_windows_memory()) {
const auto& windows_memory = process.memory_state().windows_memory();
if (windows_memory.has_process_private_usage()) {
fprintf(out, "process_private_usage: %u pages\n",
windows_memory.process_private_usage());
}
if (windows_memory.has_process_peak_workingset_size()) {
fprintf(out, "process_peak_workingset_size: %u pages\n",
windows_memory.process_peak_workingset_size());
}
if (windows_memory.has_process_peak_pagefile_usage()) {
fprintf(out, "process_peak_pagefile_usage: %u pages\n",
windows_memory.process_peak_pagefile_usage());
}
if (windows_memory.has_process_allocation_attempt()) {
fprintf(out, "process_allocation_attempt: %u bytes\n",
windows_memory.process_allocation_attempt());
}
}
for (const browser_watcher::ThreadState& thread : process.threads()) { for (const browser_watcher::ThreadState& thread : process.threads()) {
fprintf(out, "Thread %lld (%s) : %d activities\n", thread.thread_id(), fprintf(out, "Thread %lld (%s) : %d activities\n", thread.thread_id(),
thread.thread_name().c_str(), thread.activity_count()); thread.thread_name().c_str(), thread.activity_count());
......
...@@ -171,8 +171,23 @@ message ThreadState { ...@@ -171,8 +171,23 @@ message ThreadState {
} }
// The state of a process. // The state of a process.
// Next id: 4 // Next id: 5
message ProcessState { message ProcessState {
message MemoryState {
message WindowsMemory {
// The private byte usage of the process. Unit is 4K pages.
optional uint32 process_private_usage = 1;
// The peak working set usage of the process. Unit is 4K pages.
optional uint32 process_peak_workingset_size = 2;
// The peak pagefile usage of the process. Unit is 4K pages.
optional uint32 process_peak_pagefile_usage = 3;
// The allocation request that caused OOM, bytes.
optional uint32 process_allocation_attempt = 4;
}
optional WindowsMemory windows_memory = 1;
}
// The identifier of the process. // The identifier of the process.
optional int64 process_id = 3; optional int64 process_id = 3;
...@@ -181,6 +196,8 @@ message ProcessState { ...@@ -181,6 +196,8 @@ message ProcessState {
repeated CodeModule modules = 1; repeated CodeModule modules = 1;
repeated ThreadState threads = 2; repeated ThreadState threads = 2;
// TODO(manzagop): add experiment state. // TODO(manzagop): add experiment state.
optional MemoryState memory_state = 4;
} }
// Description of a field trial or experiment that the user is currently // Description of a field trial or experiment that the user is currently
...@@ -197,10 +214,23 @@ message FieldTrial { ...@@ -197,10 +214,23 @@ message FieldTrial {
optional fixed32 group_id = 2; optional fixed32 group_id = 2;
} }
// Records the state of system memory at the time of crash.
// Next id: 2
message SystemMemoryState {
message WindowsMemory {
// The system commit limit. Unit is number of 4K pages.
optional uint32 system_commit_limit = 1;
// The amount of system commit remaining. Unit is number of 4K pages.
optional uint32 system_commit_remaining = 2;
}
optional WindowsMemory windows_memory = 1;
}
// A stability report contains information pertaining to the execution of a // A stability report contains information pertaining to the execution of a
// single logical instance of a "chrome browser". It is comprised of information // single logical instance of a "chrome browser". It is comprised of information
// about the system state and about the chrome browser's processes. // about the system state and about the chrome browser's processes.
// Next id: 7 // Next id: 8
message StabilityReport { message StabilityReport {
// Whether the report is complete. Reports can be incomplete when the // Whether the report is complete. Reports can be incomplete when the
// recording size quota is hit. // recording size quota is hit.
...@@ -220,4 +250,6 @@ message StabilityReport { ...@@ -220,4 +250,6 @@ message StabilityReport {
// The field trials the user is currently enrolled in. // The field trials the user is currently enrolled in.
repeated FieldTrial field_trials = 5; repeated FieldTrial field_trials = 5;
optional SystemMemoryState system_memory_state = 7;
} }
...@@ -7,10 +7,17 @@ ...@@ -7,10 +7,17 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include <windows.h>
// Must be included after windows.h.
#include <psapi.h>
#include "base/files/file.h" #include "base/files/file.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/process/memory.h"
#include "base/process/process.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "components/browser_watcher/minidump_user_streams.h" #include "components/browser_watcher/minidump_user_streams.h"
...@@ -18,6 +25,7 @@ ...@@ -18,6 +25,7 @@
#include "components/browser_watcher/stability_paths.h" #include "components/browser_watcher/stability_paths.h"
#include "components/browser_watcher/stability_report_extractor.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/minidump/minidump_user_extension_stream_data_source.h"
#include "third_party/crashpad/crashpad/snapshot/exception_snapshot.h"
#include "third_party/crashpad/crashpad/snapshot/process_snapshot.h" #include "third_party/crashpad/crashpad/snapshot/process_snapshot.h"
namespace browser_watcher { namespace browser_watcher {
...@@ -76,25 +84,89 @@ bool BufferExtensionStreamDataSource::ReadStreamData(Delegate* delegate) { ...@@ -76,25 +84,89 @@ bool BufferExtensionStreamDataSource::ReadStreamData(Delegate* delegate) {
// TODO(manzagop): Collection should factor in whether this is a true crash or // TODO(manzagop): Collection should factor in whether this is a true crash or
// dump without crashing. // dump without crashing.
std::unique_ptr<BufferExtensionStreamDataSource> CollectReport( bool CollectStabilityReport(const base::FilePath& path,
const base::FilePath& path) { StabilityReport* report) {
StabilityReport report; CollectionStatus status = Extract(path, report);
CollectionStatus status = Extract(path, &report);
UMA_HISTOGRAM_ENUMERATION("ActivityTracker.CollectCrash.Status", status, UMA_HISTOGRAM_ENUMERATION("ActivityTracker.CollectCrash.Status", status,
COLLECTION_STATUS_MAX); COLLECTION_STATUS_MAX);
if (status != SUCCESS) if (status != SUCCESS)
return nullptr; return false;
LogCollectOnCrashEvent(CollectOnCrashEvent::kReportExtractionSuccess);
LogCollectOnCrashEvent(CollectOnCrashEvent::kReportExtractionSuccess);
MarkStabilityFileDeletedOnCrash(path); MarkStabilityFileDeletedOnCrash(path);
std::unique_ptr<BufferExtensionStreamDataSource> source( return true;
new BufferExtensionStreamDataSource(kStabilityReportStreamType)); }
if (!source->Init(report))
return nullptr;
LogCollectOnCrashEvent(CollectOnCrashEvent::kSuccess); void CollectSystemMemoryMetrics(StabilityReport* report) {
return source; // Grab system commit memory. Also best effort.
PERFORMANCE_INFORMATION perf_info = {sizeof(perf_info)};
if (GetPerformanceInfo(&perf_info, sizeof(perf_info))) {
auto* memory_state =
report->mutable_system_memory_state()->mutable_windows_memory();
memory_state->set_system_commit_limit(perf_info.CommitLimit);
memory_state->set_system_commit_remaining(perf_info.CommitLimit -
perf_info.CommitTotal);
}
}
void CollectProcessMemoryMetrics(crashpad::ProcessSnapshot* process_snapshot,
StabilityReport* report) {
const crashpad::ExceptionSnapshot* exception = process_snapshot->Exception();
if (!exception)
return;
// Find or create the ProcessState for the process in question.
base::ProcessId pid = process_snapshot->ProcessID();
ProcessState* process_state = nullptr;
for (int i = 0; i < report->process_states_size(); ++i) {
ProcessState* temp = report->mutable_process_states(i);
if (temp->has_process_id() && temp->process_id() == pid) {
process_state = temp;
break;
}
}
if (!process_state) {
process_state = report->add_process_states();
process_state->set_process_id(pid);
}
auto* memory_state =
process_state->mutable_memory_state()->mutable_windows_memory();
// Grab the requested allocation size in case of OOM exception.
if (exception->Exception() == base::win::kOomExceptionCode) {
const auto& codes = exception->Codes();
if (codes.size()) {
// The first parameter, if present, is the size of the allocation attempt.
memory_state->set_process_allocation_attempt(codes[0]);
}
}
base::Process process(base::Process::OpenWithAccess(
pid, PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ));
if (process.IsValid()) {
PROCESS_MEMORY_COUNTERS_EX process_memory = {sizeof(process_memory)};
if (GetProcessMemoryInfo(
process.Handle(),
reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&process_memory),
sizeof(process_memory))) {
// This is in units of bytes, re-scale to pages for consistency with
// system metrics.
const uint64_t kPageSize = 4096;
memory_state->set_process_private_usage(process_memory.PrivateUsage /
kPageSize);
memory_state->set_process_peak_workingset_size(
process_memory.PeakWorkingSetSize / kPageSize);
memory_state->set_process_peak_pagefile_usage(
process_memory.PeakPagefileUsage / kPageSize);
}
}
} }
} // namespace } // namespace
...@@ -109,20 +181,32 @@ StabilityReportUserStreamDataSource::ProduceStreamData( ...@@ -109,20 +181,32 @@ StabilityReportUserStreamDataSource::ProduceStreamData(
DCHECK(process_snapshot); DCHECK(process_snapshot);
LogCollectOnCrashEvent(CollectOnCrashEvent::kCollectAttempt); LogCollectOnCrashEvent(CollectOnCrashEvent::kCollectAttempt);
if (user_data_dir_.empty()) StabilityReport report;
return nullptr; bool collected_report = false;
if (!user_data_dir_.empty()) {
LogCollectOnCrashEvent(CollectOnCrashEvent::kUserDataDirNotEmpty); LogCollectOnCrashEvent(CollectOnCrashEvent::kUserDataDirNotEmpty);
base::FilePath stability_file = base::FilePath stability_file =
GetStabilityFileName(user_data_dir_, process_snapshot); GetStabilityFileName(user_data_dir_, process_snapshot);
if (!PathExists(stability_file)) { if (PathExists(stability_file)) {
// Either this is not an instrumented process (currently only browser
// processes can be instrumented), or the stability file cannot be found.
return nullptr;
}
LogCollectOnCrashEvent(CollectOnCrashEvent::kPathExists); LogCollectOnCrashEvent(CollectOnCrashEvent::kPathExists);
return CollectReport(stability_file); collected_report = CollectStabilityReport(stability_file, &report);
}
}
CollectSystemMemoryMetrics(&report);
CollectProcessMemoryMetrics(process_snapshot, &report);
std::unique_ptr<BufferExtensionStreamDataSource> source(
new BufferExtensionStreamDataSource(kStabilityReportStreamType));
if (!source->Init(report))
return nullptr;
if (collected_report)
LogCollectOnCrashEvent(CollectOnCrashEvent::kSuccess);
return source;
} }
} // namespace browser_watcher } // namespace browser_watcher
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