diff options
Diffstat (limited to 'chromium/components/metrics/stability_metrics_helper.cc')
-rw-r--r-- | chromium/components/metrics/stability_metrics_helper.cc | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/chromium/components/metrics/stability_metrics_helper.cc b/chromium/components/metrics/stability_metrics_helper.cc new file mode 100644 index 00000000000..52b91f0f127 --- /dev/null +++ b/chromium/components/metrics/stability_metrics_helper.cc @@ -0,0 +1,221 @@ +// 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 "components/metrics/stability_metrics_helper.h" + +#include <stdint.h> + +#include <vector> + +#include "base/logging.h" +#include "base/metrics/histogram.h" +#include "base/metrics/sparse_histogram.h" +#include "build/build_config.h" +#include "components/metrics/metrics_pref_names.h" +#include "components/metrics/proto/system_profile.pb.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" + +#if defined(OS_WIN) +#include <windows.h> // Needed for STATUS_* codes +#endif + +#if defined(OS_CHROMEOS) +#include "components/metrics/system_memory_stats_recorder.h" +#endif + +namespace metrics { + +namespace { + +enum RendererType { + RENDERER_TYPE_RENDERER = 1, + RENDERER_TYPE_EXTENSION, + // NOTE: Add new action types only immediately above this line. Also, + // make sure the enum list in tools/metrics/histograms/histograms.xml is + // updated with any change in here. + RENDERER_TYPE_COUNT +}; + +// Converts an exit code into something that can be inserted into our +// histograms (which expect non-negative numbers less than MAX_INT). +int MapCrashExitCodeForHistogram(int exit_code) { +#if defined(OS_WIN) + // Since |abs(STATUS_GUARD_PAGE_VIOLATION) == MAX_INT| it causes problems in + // histograms.cc. Solve this by remapping it to a smaller value, which + // hopefully doesn't conflict with other codes. + if (static_cast<DWORD>(exit_code) == STATUS_GUARD_PAGE_VIOLATION) + return 0x1FCF7EC3; // Randomly picked number. +#endif + + return std::abs(exit_code); +} + +void RecordChildKills(int histogram_type) { + UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.ChildKills", + histogram_type, RENDERER_TYPE_COUNT); +} + +} // namespace + +StabilityMetricsHelper::StabilityMetricsHelper(PrefService* local_state) + : local_state_(local_state) { + DCHECK(local_state_); +} + +StabilityMetricsHelper::~StabilityMetricsHelper() {} + +void StabilityMetricsHelper::ProvideStabilityMetrics( + SystemProfileProto* system_profile_proto) { + SystemProfileProto_Stability* stability_proto = + system_profile_proto->mutable_stability(); + + int count = local_state_->GetInteger(prefs::kStabilityPageLoadCount); + if (count) { + stability_proto->set_page_load_count(count); + local_state_->SetInteger(prefs::kStabilityPageLoadCount, 0); + } + + count = local_state_->GetInteger(prefs::kStabilityChildProcessCrashCount); + if (count) { + stability_proto->set_child_process_crash_count(count); + local_state_->SetInteger(prefs::kStabilityChildProcessCrashCount, 0); + } + + count = local_state_->GetInteger(prefs::kStabilityRendererCrashCount); + if (count) { + stability_proto->set_renderer_crash_count(count); + local_state_->SetInteger(prefs::kStabilityRendererCrashCount, 0); + } + + count = local_state_->GetInteger(prefs::kStabilityRendererFailedLaunchCount); + if (count) { + stability_proto->set_renderer_failed_launch_count(count); + local_state_->SetInteger(prefs::kStabilityRendererFailedLaunchCount, 0); + } + + count = + local_state_->GetInteger(prefs::kStabilityExtensionRendererCrashCount); + if (count) { + stability_proto->set_extension_renderer_crash_count(count); + local_state_->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0); + } + + count = local_state_->GetInteger( + prefs::kStabilityExtensionRendererFailedLaunchCount); + if (count) { + stability_proto->set_extension_renderer_failed_launch_count(count); + local_state_->SetInteger( + prefs::kStabilityExtensionRendererFailedLaunchCount, 0); + } + + count = local_state_->GetInteger(prefs::kStabilityRendererHangCount); + if (count) { + stability_proto->set_renderer_hang_count(count); + local_state_->SetInteger(prefs::kStabilityRendererHangCount, 0); + } +} + +void StabilityMetricsHelper::ClearSavedStabilityMetrics() { + // Clear all the prefs used in this class in UMA reports (which doesn't + // include |kUninstallMetricsPageLoadCount| as it's not sent up by UMA). + local_state_->SetInteger(prefs::kStabilityChildProcessCrashCount, 0); + local_state_->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0); + local_state_->SetInteger(prefs::kStabilityExtensionRendererFailedLaunchCount, + 0); + local_state_->SetInteger(prefs::kStabilityPageLoadCount, 0); + local_state_->SetInteger(prefs::kStabilityRendererCrashCount, 0); + local_state_->SetInteger(prefs::kStabilityRendererFailedLaunchCount, 0); + local_state_->SetInteger(prefs::kStabilityRendererHangCount, 0); +} + +// static +void StabilityMetricsHelper::RegisterPrefs(PrefRegistrySimple* registry) { + registry->RegisterIntegerPref(prefs::kStabilityChildProcessCrashCount, 0); + registry->RegisterIntegerPref(prefs::kStabilityExtensionRendererCrashCount, + 0); + registry->RegisterIntegerPref( + prefs::kStabilityExtensionRendererFailedLaunchCount, 0); + registry->RegisterIntegerPref(prefs::kStabilityPageLoadCount, 0); + registry->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0); + registry->RegisterIntegerPref(prefs::kStabilityRendererFailedLaunchCount, 0); + registry->RegisterIntegerPref(prefs::kStabilityRendererHangCount, 0); + + registry->RegisterInt64Pref(prefs::kUninstallMetricsPageLoadCount, 0); +} + +void StabilityMetricsHelper::BrowserChildProcessCrashed() { + IncrementPrefValue(prefs::kStabilityChildProcessCrashCount); +} + +void StabilityMetricsHelper::LogLoadStarted() { + base::RecordAction(base::UserMetricsAction("PageLoad")); + // TODO(asvitkine): Check if this is used for anything and if not, remove. + LOCAL_HISTOGRAM_BOOLEAN("Chrome.UmaPageloadCounter", true); + IncrementPrefValue(prefs::kStabilityPageLoadCount); + IncrementLongPrefsValue(prefs::kUninstallMetricsPageLoadCount); + // We need to save the prefs, as page load count is a critical stat, and it + // might be lost due to a crash :-(. +} + +void StabilityMetricsHelper::LogRendererCrash(bool was_extension_process, + base::TerminationStatus status, + int exit_code) { + int histogram_type = + was_extension_process ? RENDERER_TYPE_EXTENSION : RENDERER_TYPE_RENDERER; + if (status == base::TERMINATION_STATUS_PROCESS_CRASHED || + status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) { + if (was_extension_process) { + IncrementPrefValue(prefs::kStabilityExtensionRendererCrashCount); + + UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Extension", + MapCrashExitCodeForHistogram(exit_code)); + } else { + IncrementPrefValue(prefs::kStabilityRendererCrashCount); + + UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Renderer", + MapCrashExitCodeForHistogram(exit_code)); + } + + UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.ChildCrashes", + histogram_type, RENDERER_TYPE_COUNT); + } else if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) { + RecordChildKills(histogram_type); +#if defined(OS_CHROMEOS) + } else if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM) { + RecordChildKills(histogram_type); + UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.ChildKills.OOM", + was_extension_process ? 2 : 1, 3); + RecordMemoryStats(was_extension_process + ? RECORD_MEMORY_STATS_EXTENSIONS_OOM_KILLED + : RECORD_MEMORY_STATS_CONTENTS_OOM_KILLED); +#endif + } else if (status == base::TERMINATION_STATUS_STILL_RUNNING) { + UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.DisconnectedAlive", + histogram_type, RENDERER_TYPE_COUNT); + } else if (status == base::TERMINATION_STATUS_LAUNCH_FAILED) { + UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.ChildLaunchFailures", + histogram_type, RENDERER_TYPE_COUNT); + if (was_extension_process) + IncrementPrefValue(prefs::kStabilityExtensionRendererFailedLaunchCount); + else + IncrementPrefValue(prefs::kStabilityRendererFailedLaunchCount); + } +} + +void StabilityMetricsHelper::IncrementPrefValue(const char* path) { + int value = local_state_->GetInteger(path); + local_state_->SetInteger(path, value + 1); +} + +void StabilityMetricsHelper::IncrementLongPrefsValue(const char* path) { + int64_t value = local_state_->GetInt64(path); + local_state_->SetInt64(path, value + 1); +} + +void StabilityMetricsHelper::LogRendererHang() { + IncrementPrefValue(prefs::kStabilityRendererHangCount); +} + +} // namespace metrics |