123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- // 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 <string>
- #include "base/check.h"
- #include "base/metrics/histogram_functions.h"
- #include "base/metrics/histogram_macros.h"
- #include "base/system/sys_info.h"
- #include "build/build_config.h"
- #include "build/buildflag.h"
- #include "components/metrics/metrics_pref_names.h"
- #include "components/prefs/pref_registry_simple.h"
- #include "components/prefs/pref_service.h"
- #include "components/variations/hashing.h"
- #include "extensions/buildflags/buildflags.h"
- #include "third_party/metrics_proto/system_profile.pb.h"
- #if BUILDFLAG(IS_WIN)
- #include <windows.h> // Needed for STATUS_* codes
- #endif
- #if BUILDFLAG(IS_CHROMEOS)
- #include "components/metrics/system_memory_stats_recorder.h"
- #endif
- #if BUILDFLAG(IS_ANDROID)
- #include "base/android/application_status_listener.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
- };
- #if !BUILDFLAG(IS_ANDROID)
- // 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 BUILDFLAG(IS_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(RendererType histogram_type) {
- base::UmaHistogramEnumeration("BrowserRenderProcessHost.ChildKills",
- histogram_type, RENDERER_TYPE_COUNT);
- }
- #endif // !BUILDFLAG(IS_ANDROID)
- } // namespace
- StabilityMetricsHelper::StabilityMetricsHelper(PrefService* local_state)
- : local_state_(local_state) {
- DCHECK(local_state_);
- }
- StabilityMetricsHelper::~StabilityMetricsHelper() {}
- #if BUILDFLAG(IS_ANDROID)
- 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::kStabilityRendererLaunchCount);
- if (count) {
- stability_proto->set_renderer_launch_count(count);
- local_state_->SetInteger(prefs::kStabilityRendererLaunchCount, 0);
- }
- }
- void StabilityMetricsHelper::ClearSavedStabilityMetrics() {
- local_state_->SetInteger(prefs::kStabilityPageLoadCount, 0);
- local_state_->SetInteger(prefs::kStabilityRendererLaunchCount, 0);
- }
- #endif // BUILDFLAG(IS_ANDROID)
- // static
- void StabilityMetricsHelper::RegisterPrefs(PrefRegistrySimple* registry) {
- #if BUILDFLAG(IS_ANDROID)
- registry->RegisterIntegerPref(prefs::kStabilityPageLoadCount, 0);
- registry->RegisterIntegerPref(prefs::kStabilityRendererLaunchCount, 0);
- #endif // BUILDFLAG(IS_ANDROID)
- }
- void StabilityMetricsHelper::IncreaseRendererCrashCount() {
- RecordStabilityEvent(StabilityEventType::kRendererCrash);
- }
- void StabilityMetricsHelper::IncreaseGpuCrashCount() {
- RecordStabilityEvent(StabilityEventType::kGpuCrash);
- }
- void StabilityMetricsHelper::BrowserUtilityProcessLaunched(
- const std::string& metrics_name) {
- uint32_t hash = variations::HashName(metrics_name);
- base::UmaHistogramSparse("ChildProcess.Launched.UtilityProcessHash", hash);
- RecordStabilityEvent(StabilityEventType::kUtilityLaunch);
- }
- void StabilityMetricsHelper::BrowserUtilityProcessCrashed(
- const std::string& metrics_name,
- int exit_code) {
- uint32_t hash = variations::HashName(metrics_name);
- base::UmaHistogramSparse("ChildProcess.Crashed.UtilityProcessHash", hash);
- base::UmaHistogramSparse("ChildProcess.Crashed.UtilityProcessExitCode",
- exit_code);
- RecordStabilityEvent(StabilityEventType::kUtilityCrash);
- }
- void StabilityMetricsHelper::BrowserUtilityProcessLaunchFailed(
- const std::string& metrics_name,
- int launch_error_code
- #if BUILDFLAG(IS_WIN)
- ,
- DWORD last_error
- #endif
- ) {
- uint32_t hash = variations::HashName(metrics_name);
- base::UmaHistogramSparse("ChildProcess.LaunchFailed.UtilityProcessHash",
- hash);
- base::UmaHistogramSparse("ChildProcess.LaunchFailed.UtilityProcessErrorCode",
- launch_error_code);
- #if BUILDFLAG(IS_WIN)
- base::UmaHistogramSparse("ChildProcess.LaunchFailed.WinLastError",
- last_error);
- #endif
- // TODO(wfh): Decide if this utility process launch failure should also
- // trigger a Stability Event.
- }
- void StabilityMetricsHelper::LogLoadStarted() {
- #if BUILDFLAG(IS_ANDROID)
- IncrementPrefValue(prefs::kStabilityPageLoadCount);
- #endif
- RecordStabilityEvent(StabilityEventType::kPageLoad);
- }
- #if !BUILDFLAG(IS_ANDROID)
- void StabilityMetricsHelper::LogRendererCrash(bool was_extension_process,
- base::TerminationStatus status,
- int exit_code) {
- RendererType histogram_type =
- was_extension_process ? RENDERER_TYPE_EXTENSION : RENDERER_TYPE_RENDERER;
- switch (status) {
- case base::TERMINATION_STATUS_NORMAL_TERMINATION:
- break;
- case base::TERMINATION_STATUS_PROCESS_CRASHED:
- case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
- case base::TERMINATION_STATUS_OOM:
- if (was_extension_process) {
- #if !BUILDFLAG(ENABLE_EXTENSIONS)
- NOTREACHED();
- #endif
- RecordStabilityEvent(StabilityEventType::kExtensionCrash);
- base::UmaHistogramSparse("CrashExitCodes.Extension",
- MapCrashExitCodeForHistogram(exit_code));
- } else {
- IncreaseRendererCrashCount();
- base::UmaHistogramSparse("CrashExitCodes.Renderer",
- MapCrashExitCodeForHistogram(exit_code));
- }
- base::UmaHistogramEnumeration("BrowserRenderProcessHost.ChildCrashes",
- histogram_type, RENDERER_TYPE_COUNT);
- break;
- case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
- RecordChildKills(histogram_type);
- break;
- #if BUILDFLAG(IS_CHROMEOS)
- case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
- RecordChildKills(histogram_type);
- base::UmaHistogramExactLinear("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);
- break;
- #endif
- case base::TERMINATION_STATUS_STILL_RUNNING:
- base::UmaHistogramEnumeration(
- "BrowserRenderProcessHost.DisconnectedAlive", histogram_type,
- RENDERER_TYPE_COUNT);
- break;
- case base::TERMINATION_STATUS_LAUNCH_FAILED:
- // TODO(rkaplow): See if we can remove this histogram as we have
- // Stability.Counts2 which has the same metrics.
- base::UmaHistogramEnumeration(
- "BrowserRenderProcessHost.ChildLaunchFailures", histogram_type,
- RENDERER_TYPE_COUNT);
- base::UmaHistogramSparse(
- "BrowserRenderProcessHost.ChildLaunchFailureCodes", exit_code);
- LogRendererLaunchFailed(was_extension_process);
- break;
- #if BUILDFLAG(IS_WIN)
- case base::TERMINATION_STATUS_INTEGRITY_FAILURE:
- base::UmaHistogramEnumeration(
- "BrowserRenderProcessHost.ChildCodeIntegrityFailures", histogram_type,
- RENDERER_TYPE_COUNT);
- break;
- #endif
- case base::TERMINATION_STATUS_MAX_ENUM:
- NOTREACHED();
- break;
- }
- }
- #endif // !BUILDFLAG(IS_ANDROID)
- void StabilityMetricsHelper::LogRendererLaunched(bool was_extension_process) {
- auto metric = was_extension_process
- ? StabilityEventType::kExtensionRendererLaunch
- : StabilityEventType::kRendererLaunch;
- RecordStabilityEvent(metric);
- #if BUILDFLAG(IS_ANDROID)
- if (!was_extension_process)
- IncrementPrefValue(prefs::kStabilityRendererLaunchCount);
- #endif // BUILDFLAG(IS_ANDROID)
- }
- void StabilityMetricsHelper::LogRendererLaunchFailed(
- bool was_extension_process) {
- auto metric = was_extension_process
- ? StabilityEventType::kExtensionRendererFailedLaunch
- : StabilityEventType::kRendererFailedLaunch;
- RecordStabilityEvent(metric);
- }
- void StabilityMetricsHelper::IncrementPrefValue(const char* path) {
- int value = local_state_->GetInteger(path);
- local_state_->SetInteger(path, value + 1);
- }
- void StabilityMetricsHelper::LogRendererHang() {
- #if BUILDFLAG(IS_ANDROID)
- base::android::ApplicationState app_state =
- base::android::ApplicationStatusListener::GetState();
- bool is_foreground =
- app_state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES ||
- app_state == base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES;
- base::UmaHistogramBoolean("ChildProcess.HungRendererInForeground",
- is_foreground);
- #endif
- base::UmaHistogramMemoryMB(
- "ChildProcess.HungRendererAvailableMemoryMB",
- base::SysInfo::AmountOfAvailablePhysicalMemory() / 1024 / 1024);
- }
- // static
- void StabilityMetricsHelper::RecordStabilityEvent(
- StabilityEventType stability_event_type) {
- UMA_STABILITY_HISTOGRAM_ENUMERATION("Stability.Counts2",
- stability_event_type);
- }
- } // namespace metrics
|