stability_metrics_provider.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/metrics/stability_metrics_provider.h"
  5. #include <string>
  6. #include "base/logging.h"
  7. #include "base/metrics/histogram_macros.h"
  8. #include "build/build_config.h"
  9. #include "components/metrics/metrics_pref_names.h"
  10. #include "components/metrics/stability_metrics_helper.h"
  11. #include "components/prefs/pref_registry_simple.h"
  12. #include "components/prefs/pref_service.h"
  13. #include "components/prefs/scoped_user_pref_update.h"
  14. #include "third_party/metrics_proto/system_profile.pb.h"
  15. #if BUILDFLAG(IS_ANDROID)
  16. #include "base/android/build_info.h"
  17. #endif
  18. #if BUILDFLAG(IS_WIN)
  19. #include "components/metrics/system_session_analyzer/system_session_analyzer_win.h"
  20. #endif
  21. namespace metrics {
  22. namespace {
  23. #if BUILDFLAG(IS_ANDROID)
  24. bool HasGmsCoreVersionChanged(PrefService* local_state) {
  25. std::string previous_version =
  26. local_state->GetString(prefs::kStabilityGmsCoreVersion);
  27. std::string current_version =
  28. base::android::BuildInfo::GetInstance()->gms_version_code();
  29. // If the last version is empty, treat it as consistent.
  30. if (previous_version.empty())
  31. return false;
  32. return previous_version != current_version;
  33. }
  34. void UpdateGmsCoreVersionPref(PrefService* local_state) {
  35. std::string current_version =
  36. base::android::BuildInfo::GetInstance()->gms_version_code();
  37. local_state->SetString(prefs::kStabilityGmsCoreVersion, current_version);
  38. }
  39. #endif
  40. } // namespace
  41. StabilityMetricsProvider::StabilityMetricsProvider(PrefService* local_state)
  42. : local_state_(local_state) {}
  43. StabilityMetricsProvider::~StabilityMetricsProvider() = default;
  44. // static
  45. void StabilityMetricsProvider::RegisterPrefs(PrefRegistrySimple* registry) {
  46. registry->RegisterIntegerPref(prefs::kStabilityFileMetricsUnsentFilesCount,
  47. 0);
  48. registry->RegisterIntegerPref(prefs::kStabilityFileMetricsUnsentSamplesCount,
  49. 0);
  50. #if BUILDFLAG(IS_ANDROID)
  51. registry->RegisterIntegerPref(prefs::kStabilityLaunchCount, 0);
  52. registry->RegisterStringPref(prefs::kStabilityGmsCoreVersion, "");
  53. registry->RegisterIntegerPref(prefs::kStabilityCrashCountDueToGmsCoreUpdate,
  54. 0);
  55. #endif
  56. #if BUILDFLAG(IS_WIN)
  57. registry->RegisterIntegerPref(prefs::kStabilitySystemCrashCount, 0);
  58. #endif
  59. }
  60. void StabilityMetricsProvider::Init() {
  61. #if BUILDFLAG(IS_ANDROID)
  62. // This method has to be called after HasGmsCoreVersionChanged() to avoid
  63. // overwriting thie result.
  64. UpdateGmsCoreVersionPref(local_state_);
  65. #endif
  66. }
  67. void StabilityMetricsProvider::ClearSavedStabilityMetrics() {
  68. // The 0 is a valid value for the below prefs, clears pref instead
  69. // of setting to default value.
  70. local_state_->ClearPref(prefs::kStabilityFileMetricsUnsentFilesCount);
  71. local_state_->ClearPref(prefs::kStabilityFileMetricsUnsentSamplesCount);
  72. #if BUILDFLAG(IS_ANDROID)
  73. local_state_->SetInteger(prefs::kStabilityLaunchCount, 0);
  74. #endif
  75. #if BUILDFLAG(IS_WIN)
  76. local_state_->SetInteger(prefs::kStabilitySystemCrashCount, 0);
  77. #endif
  78. }
  79. void StabilityMetricsProvider::ProvideStabilityMetrics(
  80. SystemProfileProto* system_profile) {
  81. #if BUILDFLAG(IS_ANDROID)
  82. SystemProfileProto::Stability* stability =
  83. system_profile->mutable_stability();
  84. int pref_value = 0;
  85. if (GetAndClearPrefValue(prefs::kStabilityLaunchCount, &pref_value))
  86. stability->set_launch_count(pref_value);
  87. if (GetAndClearPrefValue(prefs::kStabilityCrashCountDueToGmsCoreUpdate,
  88. &pref_value)) {
  89. stability->set_crash_count_due_to_gms_core_update(pref_value);
  90. }
  91. #endif
  92. if (local_state_->HasPrefPath(prefs::kStabilityFileMetricsUnsentFilesCount)) {
  93. UMA_STABILITY_HISTOGRAM_COUNTS_100(
  94. "Stability.Internals.FileMetricsProvider.BrowserMetrics."
  95. "UnsentFilesCount",
  96. local_state_->GetInteger(prefs::kStabilityFileMetricsUnsentFilesCount));
  97. local_state_->ClearPref(prefs::kStabilityFileMetricsUnsentFilesCount);
  98. }
  99. if (local_state_->HasPrefPath(
  100. prefs::kStabilityFileMetricsUnsentSamplesCount)) {
  101. UMA_STABILITY_HISTOGRAM_CUSTOM_COUNTS(
  102. "Stability.Internals.FileMetricsProvider.BrowserMetrics."
  103. "UnsentSamplesCount",
  104. local_state_->GetInteger(
  105. prefs::kStabilityFileMetricsUnsentSamplesCount),
  106. 0, 1000000, 50);
  107. local_state_->ClearPref(prefs::kStabilityFileMetricsUnsentSamplesCount);
  108. }
  109. #if BUILDFLAG(IS_WIN)
  110. int pref_value = 0;
  111. if (GetAndClearPrefValue(prefs::kStabilitySystemCrashCount, &pref_value)) {
  112. UMA_STABILITY_HISTOGRAM_COUNTS_100("Stability.Internals.SystemCrashCount",
  113. pref_value);
  114. }
  115. #endif
  116. }
  117. void StabilityMetricsProvider::LogCrash(base::Time last_live_timestamp) {
  118. #if BUILDFLAG(IS_ANDROID)
  119. // On Android, if there is an update for GMS Core when Chrome is running,
  120. // Chrome will be killed, counting as a crash. This is expected and should not
  121. // be counted in stability crash counts. Thus these crashes are added to a
  122. // specific bucket for crashes caused by GMS Core updates.
  123. if (HasGmsCoreVersionChanged(local_state_)) {
  124. IncrementPrefValue(prefs::kStabilityCrashCountDueToGmsCoreUpdate);
  125. return;
  126. }
  127. #endif
  128. StabilityMetricsHelper::RecordStabilityEvent(
  129. StabilityEventType::kBrowserCrash);
  130. #if BUILDFLAG(IS_WIN)
  131. MaybeLogSystemCrash(last_live_timestamp);
  132. #endif
  133. }
  134. void StabilityMetricsProvider::LogLaunch() {
  135. #if BUILDFLAG(IS_ANDROID)
  136. IncrementPrefValue(prefs::kStabilityLaunchCount);
  137. #endif
  138. StabilityMetricsHelper::RecordStabilityEvent(StabilityEventType::kLaunch);
  139. }
  140. #if BUILDFLAG(IS_WIN)
  141. bool StabilityMetricsProvider::IsUncleanSystemSession(
  142. base::Time last_live_timestamp) {
  143. DCHECK_NE(base::Time(), last_live_timestamp);
  144. // There's a non-null last live timestamp, see if this occurred in
  145. // a Windows system session that ended uncleanly. The expectation is that
  146. // |last_live_timestamp| will have occurred in the immediately previous system
  147. // session, but if the system has been restarted many times since Chrome last
  148. // ran, that's not necessarily true. Log traversal can be expensive, so we
  149. // limit the analyzer to reaching back three previous system sessions to bound
  150. // the cost of the traversal.
  151. SystemSessionAnalyzer analyzer(3);
  152. SystemSessionAnalyzer::Status status =
  153. analyzer.IsSessionUnclean(last_live_timestamp);
  154. return status == SystemSessionAnalyzer::UNCLEAN;
  155. }
  156. void StabilityMetricsProvider::MaybeLogSystemCrash(
  157. base::Time last_live_timestamp) {
  158. if (last_live_timestamp != base::Time() &&
  159. IsUncleanSystemSession(last_live_timestamp)) {
  160. IncrementPrefValue(prefs::kStabilitySystemCrashCount);
  161. }
  162. }
  163. #endif
  164. void StabilityMetricsProvider::IncrementPrefValue(const char* path) {
  165. int value = local_state_->GetInteger(path);
  166. local_state_->SetInteger(path, value + 1);
  167. }
  168. int StabilityMetricsProvider::GetAndClearPrefValue(const char* path,
  169. int* value) {
  170. *value = local_state_->GetInteger(path);
  171. if (*value != 0)
  172. local_state_->SetInteger(path, 0);
  173. return *value;
  174. }
  175. } // namespace metrics