209 lines
7.1 KiB
C++
209 lines
7.1 KiB
C++
|
|
// Copyright 2017 The Chromium Authors
|
||
|
|
// 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 <string>
|
||
|
|
|
||
|
|
#include "base/logging.h"
|
||
|
|
#include "base/metrics/histogram_macros.h"
|
||
|
|
#include "build/build_config.h"
|
||
|
|
#include "components/metrics/metrics_pref_names.h"
|
||
|
|
#include "components/metrics/stability_metrics_helper.h"
|
||
|
|
#include "components/prefs/pref_registry_simple.h"
|
||
|
|
#include "components/prefs/pref_service.h"
|
||
|
|
#include "components/prefs/scoped_user_pref_update.h"
|
||
|
|
#include "third_party/metrics_proto/system_profile.pb.h"
|
||
|
|
|
||
|
|
#if BUILDFLAG(IS_ANDROID)
|
||
|
|
#include "base/android/build_info.h"
|
||
|
|
#endif
|
||
|
|
#if BUILDFLAG(IS_WIN)
|
||
|
|
#include "components/metrics/system_session_analyzer/system_session_analyzer_win.h"
|
||
|
|
#endif
|
||
|
|
|
||
|
|
namespace metrics {
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
|
||
|
|
#if BUILDFLAG(IS_ANDROID)
|
||
|
|
bool HasGmsCoreVersionChanged(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())
|
||
|
|
return false;
|
||
|
|
|
||
|
|
return previous_version != current_version;
|
||
|
|
}
|
||
|
|
|
||
|
|
void UpdateGmsCoreVersionPref(PrefService* local_state) {
|
||
|
|
std::string current_version =
|
||
|
|
base::android::BuildInfo::GetInstance()->gms_version_code();
|
||
|
|
local_state->SetString(prefs::kStabilityGmsCoreVersion, current_version);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
} // namespace
|
||
|
|
|
||
|
|
StabilityMetricsProvider::StabilityMetricsProvider(PrefService* local_state)
|
||
|
|
: local_state_(local_state) {}
|
||
|
|
|
||
|
|
StabilityMetricsProvider::~StabilityMetricsProvider() = default;
|
||
|
|
|
||
|
|
// static
|
||
|
|
void StabilityMetricsProvider::RegisterPrefs(PrefRegistrySimple* registry) {
|
||
|
|
registry->RegisterIntegerPref(prefs::kStabilityFileMetricsUnsentFilesCount,
|
||
|
|
0);
|
||
|
|
registry->RegisterIntegerPref(prefs::kStabilityFileMetricsUnsentSamplesCount,
|
||
|
|
0);
|
||
|
|
|
||
|
|
#if BUILDFLAG(IS_ANDROID)
|
||
|
|
registry->RegisterIntegerPref(prefs::kStabilityLaunchCount, 0);
|
||
|
|
registry->RegisterStringPref(prefs::kStabilityGmsCoreVersion, "");
|
||
|
|
registry->RegisterIntegerPref(prefs::kStabilityCrashCountDueToGmsCoreUpdate,
|
||
|
|
0);
|
||
|
|
#endif
|
||
|
|
#if BUILDFLAG(IS_WIN)
|
||
|
|
registry->RegisterIntegerPref(prefs::kStabilitySystemCrashCount, 0);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void StabilityMetricsProvider::Init() {
|
||
|
|
#if BUILDFLAG(IS_ANDROID)
|
||
|
|
// This method has to be called after HasGmsCoreVersionChanged() to avoid
|
||
|
|
// overwriting thie result.
|
||
|
|
UpdateGmsCoreVersionPref(local_state_);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void StabilityMetricsProvider::ClearSavedStabilityMetrics() {
|
||
|
|
// The 0 is a valid value for the below prefs, clears pref instead
|
||
|
|
// of setting to default value.
|
||
|
|
local_state_->ClearPref(prefs::kStabilityFileMetricsUnsentFilesCount);
|
||
|
|
local_state_->ClearPref(prefs::kStabilityFileMetricsUnsentSamplesCount);
|
||
|
|
|
||
|
|
#if BUILDFLAG(IS_ANDROID)
|
||
|
|
local_state_->SetInteger(prefs::kStabilityLaunchCount, 0);
|
||
|
|
#endif
|
||
|
|
#if BUILDFLAG(IS_WIN)
|
||
|
|
local_state_->SetInteger(prefs::kStabilitySystemCrashCount, 0);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void StabilityMetricsProvider::ProvideStabilityMetrics(
|
||
|
|
SystemProfileProto* system_profile) {
|
||
|
|
#if BUILDFLAG(IS_ANDROID)
|
||
|
|
SystemProfileProto::Stability* stability =
|
||
|
|
system_profile->mutable_stability();
|
||
|
|
|
||
|
|
int pref_value = 0;
|
||
|
|
if (GetAndClearPrefValue(prefs::kStabilityLaunchCount, &pref_value))
|
||
|
|
stability->set_launch_count(pref_value);
|
||
|
|
if (GetAndClearPrefValue(prefs::kStabilityCrashCountDueToGmsCoreUpdate,
|
||
|
|
&pref_value)) {
|
||
|
|
stability->set_crash_count_due_to_gms_core_update(pref_value);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (local_state_->HasPrefPath(prefs::kStabilityFileMetricsUnsentFilesCount)) {
|
||
|
|
UMA_STABILITY_HISTOGRAM_COUNTS_100(
|
||
|
|
"Stability.Internals.FileMetricsProvider.BrowserMetrics."
|
||
|
|
"UnsentFilesCount",
|
||
|
|
local_state_->GetInteger(prefs::kStabilityFileMetricsUnsentFilesCount));
|
||
|
|
local_state_->ClearPref(prefs::kStabilityFileMetricsUnsentFilesCount);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (local_state_->HasPrefPath(
|
||
|
|
prefs::kStabilityFileMetricsUnsentSamplesCount)) {
|
||
|
|
UMA_STABILITY_HISTOGRAM_CUSTOM_COUNTS(
|
||
|
|
"Stability.Internals.FileMetricsProvider.BrowserMetrics."
|
||
|
|
"UnsentSamplesCount",
|
||
|
|
local_state_->GetInteger(
|
||
|
|
prefs::kStabilityFileMetricsUnsentSamplesCount),
|
||
|
|
0, 1000000, 50);
|
||
|
|
local_state_->ClearPref(prefs::kStabilityFileMetricsUnsentSamplesCount);
|
||
|
|
}
|
||
|
|
|
||
|
|
#if BUILDFLAG(IS_WIN)
|
||
|
|
int pref_value = 0;
|
||
|
|
if (GetAndClearPrefValue(prefs::kStabilitySystemCrashCount, &pref_value)) {
|
||
|
|
UMA_STABILITY_HISTOGRAM_COUNTS_100("Stability.Internals.SystemCrashCount",
|
||
|
|
pref_value);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void StabilityMetricsProvider::LogCrash(base::Time last_live_timestamp) {
|
||
|
|
#if BUILDFLAG(IS_ANDROID)
|
||
|
|
// On Android, if there is an update for GMS Core when Chrome is running,
|
||
|
|
// Chrome will be killed, counting as a crash. This is expected and should not
|
||
|
|
// be counted in stability crash counts. Thus these crashes are added to a
|
||
|
|
// specific bucket for crashes caused by GMS Core updates.
|
||
|
|
if (HasGmsCoreVersionChanged(local_state_)) {
|
||
|
|
IncrementPrefValue(prefs::kStabilityCrashCountDueToGmsCoreUpdate);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
StabilityMetricsHelper::RecordStabilityEvent(
|
||
|
|
StabilityEventType::kBrowserCrash);
|
||
|
|
|
||
|
|
#if BUILDFLAG(IS_WIN)
|
||
|
|
MaybeLogSystemCrash(last_live_timestamp);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
void StabilityMetricsProvider::LogLaunch() {
|
||
|
|
#if BUILDFLAG(IS_ANDROID)
|
||
|
|
IncrementPrefValue(prefs::kStabilityLaunchCount);
|
||
|
|
#endif
|
||
|
|
StabilityMetricsHelper::RecordStabilityEvent(StabilityEventType::kLaunch);
|
||
|
|
}
|
||
|
|
|
||
|
|
#if BUILDFLAG(IS_WIN)
|
||
|
|
bool StabilityMetricsProvider::IsUncleanSystemSession(
|
||
|
|
base::Time last_live_timestamp) {
|
||
|
|
DCHECK_NE(base::Time(), last_live_timestamp);
|
||
|
|
// There's a non-null last live timestamp, see if this occurred in
|
||
|
|
// a Windows system session that ended uncleanly. The expectation is that
|
||
|
|
// |last_live_timestamp| will have occurred in the immediately previous system
|
||
|
|
// session, but if the system has been restarted many times since Chrome last
|
||
|
|
// ran, that's not necessarily true. Log traversal can be expensive, so we
|
||
|
|
// limit the analyzer to reaching back three previous system sessions to bound
|
||
|
|
// the cost of the traversal.
|
||
|
|
SystemSessionAnalyzer analyzer(3);
|
||
|
|
|
||
|
|
SystemSessionAnalyzer::Status status =
|
||
|
|
analyzer.IsSessionUnclean(last_live_timestamp);
|
||
|
|
|
||
|
|
return status == SystemSessionAnalyzer::UNCLEAN;
|
||
|
|
}
|
||
|
|
|
||
|
|
void StabilityMetricsProvider::MaybeLogSystemCrash(
|
||
|
|
base::Time last_live_timestamp) {
|
||
|
|
if (last_live_timestamp != base::Time() &&
|
||
|
|
IsUncleanSystemSession(last_live_timestamp)) {
|
||
|
|
IncrementPrefValue(prefs::kStabilitySystemCrashCount);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
void StabilityMetricsProvider::IncrementPrefValue(const char* path) {
|
||
|
|
int value = local_state_->GetInteger(path);
|
||
|
|
local_state_->SetInteger(path, value + 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
int StabilityMetricsProvider::GetAndClearPrefValue(const char* path,
|
||
|
|
int* value) {
|
||
|
|
*value = local_state_->GetInteger(path);
|
||
|
|
if (*value != 0)
|
||
|
|
local_state_->SetInteger(path, 0);
|
||
|
|
return *value;
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace metrics
|