blob: c71af184fbd552ac8f316ff1b5d9b94a039543e4 [file] [log] [blame]
// 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/metrics/stability_metrics_provider.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "third_party/metrics_proto/system_profile.pb.h"
#if defined(OS_ANDROID)
#include "base/android/build_info.h"
#endif
namespace metrics {
namespace {
#if defined(OS_ANDROID)
bool UpdateGmsCoreVersionPref(PrefService* local_state) {
std::string previous_version =
local_state->GetString(prefs::kStabilityGmsCoreVersion);
std::string current_version =
base::android::BuildInfo::GetInstance()->gms_version_code();
// If the last version is empty, treat it as consistent.
if (previous_version.empty()) {
local_state->SetString(prefs::kStabilityGmsCoreVersion, current_version);
return true;
}
if (previous_version == current_version)
return true;
local_state->SetString(prefs::kStabilityGmsCoreVersion, current_version);
return false;
}
#endif
} // namespace
StabilityMetricsProvider::StabilityMetricsProvider(PrefService* local_state)
: local_state_(local_state) {}
StabilityMetricsProvider::~StabilityMetricsProvider() = default;
// static
void StabilityMetricsProvider::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterIntegerPref(prefs::kStabilityCrashCount, 0);
registry->RegisterIntegerPref(prefs::kStabilityIncompleteSessionEndCount, 0);
registry->RegisterBooleanPref(prefs::kStabilitySessionEndCompleted, true);
registry->RegisterIntegerPref(prefs::kStabilityLaunchCount, 0);
registry->RegisterIntegerPref(prefs::kStabilityBreakpadRegistrationFail, 0);
registry->RegisterIntegerPref(prefs::kStabilityBreakpadRegistrationSuccess,
0);
registry->RegisterIntegerPref(prefs::kStabilityDebuggerPresent, 0);
registry->RegisterIntegerPref(prefs::kStabilityDebuggerNotPresent, 0);
registry->RegisterIntegerPref(prefs::kStabilityDeferredCount, 0);
registry->RegisterIntegerPref(prefs::kStabilityDiscardCount, 0);
registry->RegisterIntegerPref(prefs::kStabilityVersionMismatchCount, 0);
#if defined(OS_ANDROID)
registry->RegisterStringPref(prefs::kStabilityGmsCoreVersion, "");
registry->RegisterIntegerPref(prefs::kStabilityCrashCountWithoutGmsCoreUpdate,
0);
#endif
}
void StabilityMetricsProvider::ClearSavedStabilityMetrics() {
local_state_->SetInteger(prefs::kStabilityCrashCount, 0);
local_state_->SetInteger(prefs::kStabilityIncompleteSessionEndCount, 0);
local_state_->SetInteger(prefs::kStabilityBreakpadRegistrationSuccess, 0);
local_state_->SetInteger(prefs::kStabilityBreakpadRegistrationFail, 0);
local_state_->SetInteger(prefs::kStabilityDebuggerPresent, 0);
local_state_->SetInteger(prefs::kStabilityDebuggerNotPresent, 0);
local_state_->SetInteger(prefs::kStabilityLaunchCount, 0);
local_state_->SetBoolean(prefs::kStabilitySessionEndCompleted, true);
local_state_->SetInteger(prefs::kStabilityDeferredCount, 0);
// Note: kStabilityDiscardCount is not cleared as its intent is to measure
// the number of times data is discarded, even across versions.
local_state_->SetInteger(prefs::kStabilityVersionMismatchCount, 0);
}
void StabilityMetricsProvider::ProvideStabilityMetrics(
SystemProfileProto* system_profile) {
SystemProfileProto::Stability* stability =
system_profile->mutable_stability();
int pref_value = 0;
if (GetPrefValue(prefs::kStabilityLaunchCount, &pref_value))
stability->set_launch_count(pref_value);
if (GetPrefValue(prefs::kStabilityCrashCount, &pref_value))
stability->set_crash_count(pref_value);
#if defined(OS_ANDROID)
if (GetPrefValue(prefs::kStabilityCrashCountWithoutGmsCoreUpdate,
&pref_value)) {
stability->set_crash_count_without_gms_core_update(pref_value);
}
#endif
if (GetPrefValue(prefs::kStabilityIncompleteSessionEndCount, &pref_value))
stability->set_incomplete_shutdown_count(pref_value);
if (GetPrefValue(prefs::kStabilityBreakpadRegistrationSuccess, &pref_value))
stability->set_breakpad_registration_success_count(pref_value);
if (GetPrefValue(prefs::kStabilityBreakpadRegistrationFail, &pref_value))
stability->set_breakpad_registration_failure_count(pref_value);
if (GetPrefValue(prefs::kStabilityDebuggerPresent, &pref_value))
stability->set_debugger_present_count(pref_value);
if (GetPrefValue(prefs::kStabilityDebuggerNotPresent, &pref_value))
stability->set_debugger_not_present_count(pref_value);
// Note: only logging the following histograms for non-zero values.
if (GetPrefValue(prefs::kStabilityDeferredCount, &pref_value)) {
UMA_STABILITY_HISTOGRAM_COUNTS_100(
"Stability.Internals.InitialStabilityLogDeferredCount", pref_value);
}
// Note: only logging the following histograms for non-zero values.
if (GetPrefValue(prefs::kStabilityDiscardCount, &pref_value)) {
UMA_STABILITY_HISTOGRAM_COUNTS_100("Stability.Internals.DataDiscardCount",
pref_value);
}
// Note: only logging the following histograms for non-zero values.
if (GetPrefValue(prefs::kStabilityVersionMismatchCount, &pref_value)) {
UMA_STABILITY_HISTOGRAM_COUNTS_100(
"Stability.Internals.VersionMismatchCount", pref_value);
}
}
void StabilityMetricsProvider::RecordBreakpadRegistration(bool success) {
if (!success)
IncrementPrefValue(prefs::kStabilityBreakpadRegistrationFail);
else
IncrementPrefValue(prefs::kStabilityBreakpadRegistrationSuccess);
}
void StabilityMetricsProvider::RecordBreakpadHasDebugger(bool has_debugger) {
if (!has_debugger)
IncrementPrefValue(prefs::kStabilityDebuggerNotPresent);
else
IncrementPrefValue(prefs::kStabilityDebuggerPresent);
}
void StabilityMetricsProvider::CheckLastSessionEndCompleted() {
if (!local_state_->GetBoolean(prefs::kStabilitySessionEndCompleted)) {
IncrementPrefValue(prefs::kStabilityIncompleteSessionEndCount);
// This is marked false when we get a WM_ENDSESSION.
MarkSessionEndCompleted(true);
}
}
void StabilityMetricsProvider::MarkSessionEndCompleted(bool end_completed) {
local_state_->SetBoolean(prefs::kStabilitySessionEndCompleted, end_completed);
}
void StabilityMetricsProvider::LogCrash() {
IncrementPrefValue(prefs::kStabilityCrashCount);
#if defined(OS_ANDROID)
// On Android, if there is an update for GMS core when Chrome is running,
// Chrome will be killed and restart. This is expected and we should only
// report crash if the GMS core version has not been changed.
if (UpdateGmsCoreVersionPref(local_state_))
IncrementPrefValue(prefs::kStabilityCrashCountWithoutGmsCoreUpdate);
#endif
}
void StabilityMetricsProvider::LogStabilityLogDeferred() {
IncrementPrefValue(prefs::kStabilityDeferredCount);
}
void StabilityMetricsProvider::LogStabilityDataDiscarded() {
IncrementPrefValue(prefs::kStabilityDiscardCount);
}
void StabilityMetricsProvider::LogLaunch() {
IncrementPrefValue(prefs::kStabilityLaunchCount);
}
void StabilityMetricsProvider::LogStabilityVersionMismatch() {
IncrementPrefValue(prefs::kStabilityVersionMismatchCount);
}
void StabilityMetricsProvider::IncrementPrefValue(const char* path) {
int value = local_state_->GetInteger(path);
local_state_->SetInteger(path, value + 1);
}
int StabilityMetricsProvider::GetPrefValue(const char* path, int* value) {
*value = local_state_->GetInteger(path);
if (*value != 0)
local_state_->SetInteger(path, 0);
return *value;
}
} // namespace metrics