123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- // 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 <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
|