Add UMA to exception handler exception catching

Includes mini_chromium DEPS roll for:
88e0a3e Add stub of sparse_histogram.h

R=mark@chromium.org
BUG=crashpad:100

Change-Id: I4c541a33be0f7f47e972af638d4765bd06682acf
Reviewed-on: https://chromium-review.googlesource.com/386385
Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
Scott Graham 2016-09-19 10:44:02 -07:00
parent 23d31c4fea
commit b48e9bfbab
5 changed files with 101 additions and 1 deletions

2
DEPS
View File

@ -25,7 +25,7 @@ deps = {
'93cc6e2c23e4d5ebd179f388e67aa907d0dfd43d',
'crashpad/third_party/mini_chromium/mini_chromium':
Var('chromium_git') + '/chromium/mini_chromium@' +
'438bd4f4d8d38dd5c31e78a0d605cc4cf6be5229',
'88e0a3e1a965c698d7ead8bcfc0cfb6aacdc3524',
'buildtools':
Var('chromium_git') + '/chromium/buildtools.git@' +
'f8fc76ea5ce4a60cda2fa5d7df3d4a62935b3113',

View File

@ -32,6 +32,7 @@
#include "util/mach/mach_message.h"
#include "util/mach/scoped_task_suspend.h"
#include "util/mach/symbolic_constants_mach.h"
#include "util/misc/metrics.h"
#include "util/misc/tri_state.h"
#include "util/misc/uuid.h"
@ -64,6 +65,8 @@ kern_return_t CrashReportExceptionHandler::CatchMachException(
mach_msg_type_number_t* new_state_count,
const mach_msg_trailer_t* trailer,
bool* destroy_complex_request) {
Metrics::ExceptionEncountered();
Metrics::ExceptionCode(exception);
*destroy_complex_request = true;
// The expected behavior is EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES,
@ -74,6 +77,8 @@ kern_return_t CrashReportExceptionHandler::CatchMachException(
"unexpected exception behavior %s, rejecting",
ExceptionBehaviorToString(
behavior, kUseFullName | kUnknownIsNumeric | kUseOr).c_str());
Metrics::ExceptionCaptureResult(
Metrics::CaptureResult::kUnexpectedExceptionBehavior);
return KERN_FAILURE;
} else if (behavior != (EXCEPTION_STATE_IDENTITY | kMachExceptionCodes)) {
LOG(WARNING) << base::StringPrintf(
@ -84,6 +89,8 @@ kern_return_t CrashReportExceptionHandler::CatchMachException(
if (task == mach_task_self()) {
LOG(ERROR) << "cannot suspend myself";
Metrics::ExceptionCaptureResult(
Metrics::CaptureResult::kFailedDueToSuspendSelf);
return KERN_FAILURE;
}
@ -91,6 +98,7 @@ kern_return_t CrashReportExceptionHandler::CatchMachException(
ProcessSnapshotMac process_snapshot;
if (!process_snapshot.Initialize(task)) {
Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSnapshotFailed);
return KERN_FAILURE;
}
@ -126,6 +134,8 @@ kern_return_t CrashReportExceptionHandler::CatchMachException(
*flavor,
old_state,
old_state_count)) {
Metrics::ExceptionCaptureResult(
Metrics::CaptureResult::kExceptionInitializationFailed);
return KERN_FAILURE;
}
@ -145,6 +155,8 @@ kern_return_t CrashReportExceptionHandler::CatchMachException(
CrashReportDatabase::OperationStatus database_status =
database_->PrepareNewCrashReport(&new_report);
if (database_status != CrashReportDatabase::kNoError) {
Metrics::ExceptionCaptureResult(
Metrics::CaptureResult::kPrepareNewCrashReportFailed);
return KERN_FAILURE;
}
@ -158,6 +170,8 @@ kern_return_t CrashReportExceptionHandler::CatchMachException(
MinidumpFileWriter minidump;
minidump.InitializeFromSnapshot(&process_snapshot);
if (!minidump.WriteEverything(&file_writer)) {
Metrics::ExceptionCaptureResult(
Metrics::CaptureResult::kMinidumpWriteFailed);
return KERN_FAILURE;
}
@ -166,6 +180,8 @@ kern_return_t CrashReportExceptionHandler::CatchMachException(
UUID uuid;
database_status = database_->FinishedWritingCrashReport(new_report, &uuid);
if (database_status != CrashReportDatabase::kNoError) {
Metrics::ExceptionCaptureResult(
Metrics::CaptureResult::kFinishedWritingCrashReportFailed);
return KERN_FAILURE;
}
@ -223,6 +239,7 @@ kern_return_t CrashReportExceptionHandler::CatchMachException(
ExcServerCopyState(
behavior, old_state, old_state_count, new_state, new_state_count);
Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSuccess);
return ExcServerSuccessfulReturnValue(exception, behavior, false);
}

View File

@ -20,6 +20,7 @@
#include "minidump/minidump_file_writer.h"
#include "snapshot/win/process_snapshot_win.h"
#include "util/file/file_writer.h"
#include "util/misc/metrics.h"
#include "util/win/registration_protocol_win.h"
#include "util/win/scoped_process_suspend.h"
@ -46,6 +47,8 @@ unsigned int CrashReportExceptionHandler::ExceptionHandlerServerException(
WinVMAddress debug_critical_section_address) {
const unsigned int kFailedTerminationCode = 0xffff7002;
Metrics::ExceptionEncountered();
ScopedProcessSuspend suspend(process);
ProcessSnapshotWin process_snapshot;
@ -54,6 +57,7 @@ unsigned int CrashReportExceptionHandler::ExceptionHandlerServerException(
exception_information_address,
debug_critical_section_address)) {
LOG(WARNING) << "ProcessSnapshotWin::Initialize failed";
Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSnapshotFailed);
return kFailedTerminationCode;
}
@ -62,6 +66,8 @@ unsigned int CrashReportExceptionHandler::ExceptionHandlerServerException(
const unsigned int termination_code =
process_snapshot.Exception()->Exception();
Metrics::ExceptionCode(termination_code);
CrashpadInfoClientOptions client_options;
process_snapshot.GetCrashpadOptions(&client_options);
if (client_options.crashpad_handler_behavior != TriState::kDisabled) {
@ -82,6 +88,8 @@ unsigned int CrashReportExceptionHandler::ExceptionHandlerServerException(
database_->PrepareNewCrashReport(&new_report);
if (database_status != CrashReportDatabase::kNoError) {
LOG(ERROR) << "PrepareNewCrashReport failed";
Metrics::ExceptionCaptureResult(
Metrics::CaptureResult::kPrepareNewCrashReportFailed);
return termination_code;
}
@ -96,6 +104,8 @@ unsigned int CrashReportExceptionHandler::ExceptionHandlerServerException(
minidump.InitializeFromSnapshot(&process_snapshot);
if (!minidump.WriteEverything(&file_writer)) {
LOG(ERROR) << "WriteEverything failed";
Metrics::ExceptionCaptureResult(
Metrics::CaptureResult::kMinidumpWriteFailed);
return termination_code;
}
@ -105,12 +115,15 @@ unsigned int CrashReportExceptionHandler::ExceptionHandlerServerException(
database_status = database_->FinishedWritingCrashReport(new_report, &uuid);
if (database_status != CrashReportDatabase::kNoError) {
LOG(ERROR) << "FinishedWritingCrashReport failed";
Metrics::ExceptionCaptureResult(
Metrics::CaptureResult::kFinishedWritingCrashReportFailed);
return termination_code;
}
upload_thread_->ReportPending();
}
Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSuccess);
return termination_code;
}

View File

@ -15,13 +15,32 @@
#include "util/misc/metrics.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
namespace crashpad {
// static
void Metrics::CrashReportSize(FileHandle file) {
const FileOffset size = LoggingFileSizeByHandle(file);
UMA_HISTOGRAM_CUSTOM_COUNTS(
"Crashpad.CrashReportSize", size, 0, 5 * 1024 * 1024, 50);
}
// static
void Metrics::ExceptionCaptureResult(CaptureResult result) {
UMA_HISTOGRAM_ENUMERATION(
"Crashpad.ExceptionCaptureResult", result, CaptureResult::kMaxValue);
}
// static
void Metrics::ExceptionCode(uint32_t code) {
UMA_HISTOGRAM_SPARSE_SLOWLY("Crashpad.ExceptionCode",
static_cast<int32_t>(code));
}
// static
void Metrics::ExceptionEncountered() {
UMA_HISTOGRAM_COUNTS("Crashpad.ExceptionEncountered", 1);
}
} // namespace crashpad

View File

@ -15,6 +15,8 @@
#ifndef CRASHPAD_UTIL_MISC_METRICS_H_
#define CRASHPAD_UTIL_MISC_METRICS_H_
#include <inttypes.h>
#include "base/macros.h"
#include "util/file/file_io.h"
@ -32,6 +34,55 @@ class Metrics {
//! when a new report is written to disk.
static void CrashReportSize(FileHandle file);
//! \brief The result of capturing an exception. These are used as metrics
//! enumeration values so new values should always be added at the end.
enum class CaptureResult : int {
//! \brief The exception capture succeeded normally.
kSuccess = 0,
//! \brief Unexpected exception behavior.
//!
//! This value is only used on Mac OS X.
kUnexpectedExceptionBehavior = 1,
//! \brief Failed due to attempt to suspend self.
//!
//! This value is only used on Mac OS X.
kFailedDueToSuspendSelf = 2,
//! \brief The process snapshot could not be captured.
kSnapshotFailed = 3,
//! \brief The exception could not be initialized.
kExceptionInitializationFailed = 4,
//! \brief The attempt to prepare a new crash report in the crash database
//! failed.
kPrepareNewCrashReportFailed = 5,
//! \brief Writing the minidump to disk failed.
kMinidumpWriteFailed = 6,
//! \brief There was a database error in attempt to complete the report.
kFinishedWritingCrashReportFailed = 7,
//! \brief The number of values in this enumeration; not a valid value.
kMaxValue
};
//! \brief Reports on the outcome of capturing a report in the exception
//! handler.
static void ExceptionCaptureResult(CaptureResult result);
//! \brief The exception code for an exception was retrieved.
//!
//! These values are OS-specific, and correspond to
//! MINIDUMP_EXCEPTION::ExceptionCode.
static void ExceptionCode(uint32_t exception_code);
//! \brief The exception handler server started capturing an exception.
static void ExceptionEncountered();
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Metrics);
};