stability_metrics_helper.cc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. // Copyright 2015 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_helper.h"
  5. #include <stdint.h>
  6. #include <string>
  7. #include "base/check.h"
  8. #include "base/metrics/histogram_functions.h"
  9. #include "base/metrics/histogram_macros.h"
  10. #include "base/system/sys_info.h"
  11. #include "build/build_config.h"
  12. #include "build/buildflag.h"
  13. #include "components/metrics/metrics_pref_names.h"
  14. #include "components/prefs/pref_registry_simple.h"
  15. #include "components/prefs/pref_service.h"
  16. #include "components/variations/hashing.h"
  17. #include "extensions/buildflags/buildflags.h"
  18. #include "third_party/metrics_proto/system_profile.pb.h"
  19. #if BUILDFLAG(IS_WIN)
  20. #include <windows.h> // Needed for STATUS_* codes
  21. #endif
  22. #if BUILDFLAG(IS_CHROMEOS)
  23. #include "components/metrics/system_memory_stats_recorder.h"
  24. #endif
  25. #if BUILDFLAG(IS_ANDROID)
  26. #include "base/android/application_status_listener.h"
  27. #endif
  28. namespace metrics {
  29. namespace {
  30. enum RendererType {
  31. RENDERER_TYPE_RENDERER = 1,
  32. RENDERER_TYPE_EXTENSION,
  33. // NOTE: Add new action types only immediately above this line. Also,
  34. // make sure the enum list in tools/metrics/histograms/histograms.xml is
  35. // updated with any change in here.
  36. RENDERER_TYPE_COUNT
  37. };
  38. #if !BUILDFLAG(IS_ANDROID)
  39. // Converts an exit code into something that can be inserted into our
  40. // histograms (which expect non-negative numbers less than MAX_INT).
  41. int MapCrashExitCodeForHistogram(int exit_code) {
  42. #if BUILDFLAG(IS_WIN)
  43. // Since |abs(STATUS_GUARD_PAGE_VIOLATION) == MAX_INT| it causes problems in
  44. // histograms.cc. Solve this by remapping it to a smaller value, which
  45. // hopefully doesn't conflict with other codes.
  46. if (static_cast<DWORD>(exit_code) == STATUS_GUARD_PAGE_VIOLATION)
  47. return 0x1FCF7EC3; // Randomly picked number.
  48. #endif
  49. return std::abs(exit_code);
  50. }
  51. void RecordChildKills(RendererType histogram_type) {
  52. base::UmaHistogramEnumeration("BrowserRenderProcessHost.ChildKills",
  53. histogram_type, RENDERER_TYPE_COUNT);
  54. }
  55. #endif // !BUILDFLAG(IS_ANDROID)
  56. } // namespace
  57. StabilityMetricsHelper::StabilityMetricsHelper(PrefService* local_state)
  58. : local_state_(local_state) {
  59. DCHECK(local_state_);
  60. }
  61. StabilityMetricsHelper::~StabilityMetricsHelper() {}
  62. #if BUILDFLAG(IS_ANDROID)
  63. void StabilityMetricsHelper::ProvideStabilityMetrics(
  64. SystemProfileProto* system_profile_proto) {
  65. SystemProfileProto_Stability* stability_proto =
  66. system_profile_proto->mutable_stability();
  67. int count = local_state_->GetInteger(prefs::kStabilityPageLoadCount);
  68. if (count) {
  69. stability_proto->set_page_load_count(count);
  70. local_state_->SetInteger(prefs::kStabilityPageLoadCount, 0);
  71. }
  72. count = local_state_->GetInteger(prefs::kStabilityRendererLaunchCount);
  73. if (count) {
  74. stability_proto->set_renderer_launch_count(count);
  75. local_state_->SetInteger(prefs::kStabilityRendererLaunchCount, 0);
  76. }
  77. }
  78. void StabilityMetricsHelper::ClearSavedStabilityMetrics() {
  79. local_state_->SetInteger(prefs::kStabilityPageLoadCount, 0);
  80. local_state_->SetInteger(prefs::kStabilityRendererLaunchCount, 0);
  81. }
  82. #endif // BUILDFLAG(IS_ANDROID)
  83. // static
  84. void StabilityMetricsHelper::RegisterPrefs(PrefRegistrySimple* registry) {
  85. #if BUILDFLAG(IS_ANDROID)
  86. registry->RegisterIntegerPref(prefs::kStabilityPageLoadCount, 0);
  87. registry->RegisterIntegerPref(prefs::kStabilityRendererLaunchCount, 0);
  88. #endif // BUILDFLAG(IS_ANDROID)
  89. }
  90. void StabilityMetricsHelper::IncreaseRendererCrashCount() {
  91. RecordStabilityEvent(StabilityEventType::kRendererCrash);
  92. }
  93. void StabilityMetricsHelper::IncreaseGpuCrashCount() {
  94. RecordStabilityEvent(StabilityEventType::kGpuCrash);
  95. }
  96. void StabilityMetricsHelper::BrowserUtilityProcessLaunched(
  97. const std::string& metrics_name) {
  98. uint32_t hash = variations::HashName(metrics_name);
  99. base::UmaHistogramSparse("ChildProcess.Launched.UtilityProcessHash", hash);
  100. RecordStabilityEvent(StabilityEventType::kUtilityLaunch);
  101. }
  102. void StabilityMetricsHelper::BrowserUtilityProcessCrashed(
  103. const std::string& metrics_name,
  104. int exit_code) {
  105. uint32_t hash = variations::HashName(metrics_name);
  106. base::UmaHistogramSparse("ChildProcess.Crashed.UtilityProcessHash", hash);
  107. base::UmaHistogramSparse("ChildProcess.Crashed.UtilityProcessExitCode",
  108. exit_code);
  109. RecordStabilityEvent(StabilityEventType::kUtilityCrash);
  110. }
  111. void StabilityMetricsHelper::BrowserUtilityProcessLaunchFailed(
  112. const std::string& metrics_name,
  113. int launch_error_code
  114. #if BUILDFLAG(IS_WIN)
  115. ,
  116. DWORD last_error
  117. #endif
  118. ) {
  119. uint32_t hash = variations::HashName(metrics_name);
  120. base::UmaHistogramSparse("ChildProcess.LaunchFailed.UtilityProcessHash",
  121. hash);
  122. base::UmaHistogramSparse("ChildProcess.LaunchFailed.UtilityProcessErrorCode",
  123. launch_error_code);
  124. #if BUILDFLAG(IS_WIN)
  125. base::UmaHistogramSparse("ChildProcess.LaunchFailed.WinLastError",
  126. last_error);
  127. #endif
  128. // TODO(wfh): Decide if this utility process launch failure should also
  129. // trigger a Stability Event.
  130. }
  131. void StabilityMetricsHelper::LogLoadStarted() {
  132. #if BUILDFLAG(IS_ANDROID)
  133. IncrementPrefValue(prefs::kStabilityPageLoadCount);
  134. #endif
  135. RecordStabilityEvent(StabilityEventType::kPageLoad);
  136. }
  137. #if !BUILDFLAG(IS_ANDROID)
  138. void StabilityMetricsHelper::LogRendererCrash(bool was_extension_process,
  139. base::TerminationStatus status,
  140. int exit_code) {
  141. RendererType histogram_type =
  142. was_extension_process ? RENDERER_TYPE_EXTENSION : RENDERER_TYPE_RENDERER;
  143. switch (status) {
  144. case base::TERMINATION_STATUS_NORMAL_TERMINATION:
  145. break;
  146. case base::TERMINATION_STATUS_PROCESS_CRASHED:
  147. case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
  148. case base::TERMINATION_STATUS_OOM:
  149. if (was_extension_process) {
  150. #if !BUILDFLAG(ENABLE_EXTENSIONS)
  151. NOTREACHED();
  152. #endif
  153. RecordStabilityEvent(StabilityEventType::kExtensionCrash);
  154. base::UmaHistogramSparse("CrashExitCodes.Extension",
  155. MapCrashExitCodeForHistogram(exit_code));
  156. } else {
  157. IncreaseRendererCrashCount();
  158. base::UmaHistogramSparse("CrashExitCodes.Renderer",
  159. MapCrashExitCodeForHistogram(exit_code));
  160. }
  161. base::UmaHistogramEnumeration("BrowserRenderProcessHost.ChildCrashes",
  162. histogram_type, RENDERER_TYPE_COUNT);
  163. break;
  164. case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
  165. RecordChildKills(histogram_type);
  166. break;
  167. #if BUILDFLAG(IS_CHROMEOS)
  168. case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
  169. RecordChildKills(histogram_type);
  170. base::UmaHistogramExactLinear("BrowserRenderProcessHost.ChildKills.OOM",
  171. was_extension_process ? 2 : 1, 3);
  172. RecordMemoryStats(was_extension_process
  173. ? RECORD_MEMORY_STATS_EXTENSIONS_OOM_KILLED
  174. : RECORD_MEMORY_STATS_CONTENTS_OOM_KILLED);
  175. break;
  176. #endif
  177. case base::TERMINATION_STATUS_STILL_RUNNING:
  178. base::UmaHistogramEnumeration(
  179. "BrowserRenderProcessHost.DisconnectedAlive", histogram_type,
  180. RENDERER_TYPE_COUNT);
  181. break;
  182. case base::TERMINATION_STATUS_LAUNCH_FAILED:
  183. // TODO(rkaplow): See if we can remove this histogram as we have
  184. // Stability.Counts2 which has the same metrics.
  185. base::UmaHistogramEnumeration(
  186. "BrowserRenderProcessHost.ChildLaunchFailures", histogram_type,
  187. RENDERER_TYPE_COUNT);
  188. base::UmaHistogramSparse(
  189. "BrowserRenderProcessHost.ChildLaunchFailureCodes", exit_code);
  190. LogRendererLaunchFailed(was_extension_process);
  191. break;
  192. #if BUILDFLAG(IS_WIN)
  193. case base::TERMINATION_STATUS_INTEGRITY_FAILURE:
  194. base::UmaHistogramEnumeration(
  195. "BrowserRenderProcessHost.ChildCodeIntegrityFailures", histogram_type,
  196. RENDERER_TYPE_COUNT);
  197. break;
  198. #endif
  199. case base::TERMINATION_STATUS_MAX_ENUM:
  200. NOTREACHED();
  201. break;
  202. }
  203. }
  204. #endif // !BUILDFLAG(IS_ANDROID)
  205. void StabilityMetricsHelper::LogRendererLaunched(bool was_extension_process) {
  206. auto metric = was_extension_process
  207. ? StabilityEventType::kExtensionRendererLaunch
  208. : StabilityEventType::kRendererLaunch;
  209. RecordStabilityEvent(metric);
  210. #if BUILDFLAG(IS_ANDROID)
  211. if (!was_extension_process)
  212. IncrementPrefValue(prefs::kStabilityRendererLaunchCount);
  213. #endif // BUILDFLAG(IS_ANDROID)
  214. }
  215. void StabilityMetricsHelper::LogRendererLaunchFailed(
  216. bool was_extension_process) {
  217. auto metric = was_extension_process
  218. ? StabilityEventType::kExtensionRendererFailedLaunch
  219. : StabilityEventType::kRendererFailedLaunch;
  220. RecordStabilityEvent(metric);
  221. }
  222. void StabilityMetricsHelper::IncrementPrefValue(const char* path) {
  223. int value = local_state_->GetInteger(path);
  224. local_state_->SetInteger(path, value + 1);
  225. }
  226. void StabilityMetricsHelper::LogRendererHang() {
  227. #if BUILDFLAG(IS_ANDROID)
  228. base::android::ApplicationState app_state =
  229. base::android::ApplicationStatusListener::GetState();
  230. bool is_foreground =
  231. app_state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES ||
  232. app_state == base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES;
  233. base::UmaHistogramBoolean("ChildProcess.HungRendererInForeground",
  234. is_foreground);
  235. #endif
  236. base::UmaHistogramMemoryMB(
  237. "ChildProcess.HungRendererAvailableMemoryMB",
  238. base::SysInfo::AmountOfAvailablePhysicalMemory() / 1024 / 1024);
  239. }
  240. // static
  241. void StabilityMetricsHelper::RecordStabilityEvent(
  242. StabilityEventType stability_event_type) {
  243. UMA_STABILITY_HISTOGRAM_ENUMERATION("Stability.Counts2",
  244. stability_event_type);
  245. }
  246. } // namespace metrics