blob: edad9a78ccabad5372222ce9f8f83bc8cefc6129 [file] [log] [blame]
blundell8ae15622015-09-28 08:34:161// 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
5#include "components/metrics/stability_metrics_helper.h"
6
avi26062922015-12-26 00:14:187#include <stdint.h>
8
blundell8ae15622015-09-28 08:34:169#include <vector>
10
11#include "base/logging.h"
asvitkine30330812016-08-30 04:01:0812#include "base/metrics/histogram_macros.h"
blundell8ae15622015-09-28 08:34:1613#include "base/metrics/sparse_histogram.h"
bratell0a7406f2017-03-28 07:46:3714#include "base/metrics/user_metrics.h"
avi26062922015-12-26 00:14:1815#include "build/build_config.h"
Ran Ji3537ffa32017-09-21 04:39:0116#include "build/buildflag.h"
blundell8ae15622015-09-28 08:34:1617#include "components/metrics/metrics_pref_names.h"
brettwf00b9b42016-02-01 22:11:3818#include "components/prefs/pref_registry_simple.h"
19#include "components/prefs/pref_service.h"
Ran Ji3537ffa32017-09-21 04:39:0120#include "extensions/features/features.h"
Steven Holtef9d5ed62017-10-21 02:02:3021#include "third_party/metrics_proto/system_profile.pb.h"
blundell8ae15622015-09-28 08:34:1622
23#if defined(OS_WIN)
24#include <windows.h> // Needed for STATUS_* codes
25#endif
26
27#if defined(OS_CHROMEOS)
28#include "components/metrics/system_memory_stats_recorder.h"
29#endif
30
31namespace metrics {
32
33namespace {
34
35enum RendererType {
36 RENDERER_TYPE_RENDERER = 1,
37 RENDERER_TYPE_EXTENSION,
38 // NOTE: Add new action types only immediately above this line. Also,
39 // make sure the enum list in tools/metrics/histograms/histograms.xml is
40 // updated with any change in here.
41 RENDERER_TYPE_COUNT
42};
43
44// Converts an exit code into something that can be inserted into our
45// histograms (which expect non-negative numbers less than MAX_INT).
46int MapCrashExitCodeForHistogram(int exit_code) {
47#if defined(OS_WIN)
48 // Since |abs(STATUS_GUARD_PAGE_VIOLATION) == MAX_INT| it causes problems in
49 // histograms.cc. Solve this by remapping it to a smaller value, which
50 // hopefully doesn't conflict with other codes.
thakis7bf6418e2015-12-09 22:41:0051 if (static_cast<DWORD>(exit_code) == STATUS_GUARD_PAGE_VIOLATION)
blundell8ae15622015-09-28 08:34:1652 return 0x1FCF7EC3; // Randomly picked number.
53#endif
54
55 return std::abs(exit_code);
56}
57
Wei-Yin Chen (陳威尹)223326c2017-07-21 02:08:2858void RecordChildKills(RendererType histogram_type) {
blundell8ae15622015-09-28 08:34:1659 UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.ChildKills",
60 histogram_type, RENDERER_TYPE_COUNT);
61}
62
63} // namespace
64
65StabilityMetricsHelper::StabilityMetricsHelper(PrefService* local_state)
66 : local_state_(local_state) {
67 DCHECK(local_state_);
68}
69
70StabilityMetricsHelper::~StabilityMetricsHelper() {}
71
72void StabilityMetricsHelper::ProvideStabilityMetrics(
73 SystemProfileProto* system_profile_proto) {
74 SystemProfileProto_Stability* stability_proto =
75 system_profile_proto->mutable_stability();
76
77 int count = local_state_->GetInteger(prefs::kStabilityPageLoadCount);
78 if (count) {
79 stability_proto->set_page_load_count(count);
80 local_state_->SetInteger(prefs::kStabilityPageLoadCount, 0);
81 }
82
83 count = local_state_->GetInteger(prefs::kStabilityChildProcessCrashCount);
84 if (count) {
85 stability_proto->set_child_process_crash_count(count);
86 local_state_->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
87 }
88
89 count = local_state_->GetInteger(prefs::kStabilityRendererCrashCount);
90 if (count) {
91 stability_proto->set_renderer_crash_count(count);
92 local_state_->SetInteger(prefs::kStabilityRendererCrashCount, 0);
93 }
94
95 count = local_state_->GetInteger(prefs::kStabilityRendererFailedLaunchCount);
96 if (count) {
97 stability_proto->set_renderer_failed_launch_count(count);
98 local_state_->SetInteger(prefs::kStabilityRendererFailedLaunchCount, 0);
99 }
100
wfh86b6c8c2016-07-15 20:48:35101 count = local_state_->GetInteger(prefs::kStabilityRendererLaunchCount);
102 if (count) {
103 stability_proto->set_renderer_launch_count(count);
104 local_state_->SetInteger(prefs::kStabilityRendererLaunchCount, 0);
105 }
106
blundell8ae15622015-09-28 08:34:16107 count =
108 local_state_->GetInteger(prefs::kStabilityExtensionRendererCrashCount);
109 if (count) {
110 stability_proto->set_extension_renderer_crash_count(count);
111 local_state_->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0);
112 }
113
114 count = local_state_->GetInteger(
115 prefs::kStabilityExtensionRendererFailedLaunchCount);
116 if (count) {
117 stability_proto->set_extension_renderer_failed_launch_count(count);
118 local_state_->SetInteger(
119 prefs::kStabilityExtensionRendererFailedLaunchCount, 0);
120 }
121
122 count = local_state_->GetInteger(prefs::kStabilityRendererHangCount);
123 if (count) {
124 stability_proto->set_renderer_hang_count(count);
125 local_state_->SetInteger(prefs::kStabilityRendererHangCount, 0);
126 }
wfh86b6c8c2016-07-15 20:48:35127
wfhe982eb42016-07-20 17:45:00128 count =
129 local_state_->GetInteger(prefs::kStabilityExtensionRendererLaunchCount);
wfh86b6c8c2016-07-15 20:48:35130 if (count) {
wfhe982eb42016-07-20 17:45:00131 stability_proto->set_extension_renderer_launch_count(count);
132 local_state_->SetInteger(prefs::kStabilityExtensionRendererLaunchCount, 0);
wfh86b6c8c2016-07-15 20:48:35133 }
blundell8ae15622015-09-28 08:34:16134}
135
136void StabilityMetricsHelper::ClearSavedStabilityMetrics() {
137 // Clear all the prefs used in this class in UMA reports (which doesn't
138 // include |kUninstallMetricsPageLoadCount| as it's not sent up by UMA).
139 local_state_->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
140 local_state_->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0);
141 local_state_->SetInteger(prefs::kStabilityExtensionRendererFailedLaunchCount,
142 0);
wfh86b6c8c2016-07-15 20:48:35143 local_state_->SetInteger(prefs::kStabilityExtensionRendererLaunchCount, 0);
blundell8ae15622015-09-28 08:34:16144 local_state_->SetInteger(prefs::kStabilityPageLoadCount, 0);
145 local_state_->SetInteger(prefs::kStabilityRendererCrashCount, 0);
146 local_state_->SetInteger(prefs::kStabilityRendererFailedLaunchCount, 0);
147 local_state_->SetInteger(prefs::kStabilityRendererHangCount, 0);
wfh86b6c8c2016-07-15 20:48:35148 local_state_->SetInteger(prefs::kStabilityRendererLaunchCount, 0);
blundell8ae15622015-09-28 08:34:16149}
150
151// static
152void StabilityMetricsHelper::RegisterPrefs(PrefRegistrySimple* registry) {
153 registry->RegisterIntegerPref(prefs::kStabilityChildProcessCrashCount, 0);
154 registry->RegisterIntegerPref(prefs::kStabilityExtensionRendererCrashCount,
155 0);
156 registry->RegisterIntegerPref(
157 prefs::kStabilityExtensionRendererFailedLaunchCount, 0);
wfh86b6c8c2016-07-15 20:48:35158 registry->RegisterIntegerPref(prefs::kStabilityExtensionRendererLaunchCount,
159 0);
blundell8ae15622015-09-28 08:34:16160 registry->RegisterIntegerPref(prefs::kStabilityPageLoadCount, 0);
161 registry->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0);
162 registry->RegisterIntegerPref(prefs::kStabilityRendererFailedLaunchCount, 0);
163 registry->RegisterIntegerPref(prefs::kStabilityRendererHangCount, 0);
wfh86b6c8c2016-07-15 20:48:35164 registry->RegisterIntegerPref(prefs::kStabilityRendererLaunchCount, 0);
blundell8ae15622015-09-28 08:34:16165
166 registry->RegisterInt64Pref(prefs::kUninstallMetricsPageLoadCount, 0);
167}
168
Ran Ji3537ffa32017-09-21 04:39:01169// static
170void StabilityMetricsHelper::IncreaseRendererCrashCount(
171 PrefService* local_state) {
172 // It doesn't use IncrementPrefValue() because the function is static.
173 int value = local_state->GetInteger(prefs::kStabilityRendererCrashCount);
174 local_state->SetInteger(prefs::kStabilityRendererCrashCount, value + 1);
175}
176
blundell8ae15622015-09-28 08:34:16177void StabilityMetricsHelper::BrowserChildProcessCrashed() {
178 IncrementPrefValue(prefs::kStabilityChildProcessCrashCount);
179}
180
181void StabilityMetricsHelper::LogLoadStarted() {
182 base::RecordAction(base::UserMetricsAction("PageLoad"));
blundell8ae15622015-09-28 08:34:16183 IncrementPrefValue(prefs::kStabilityPageLoadCount);
184 IncrementLongPrefsValue(prefs::kUninstallMetricsPageLoadCount);
185 // We need to save the prefs, as page load count is a critical stat, and it
186 // might be lost due to a crash :-(.
187}
188
189void StabilityMetricsHelper::LogRendererCrash(bool was_extension_process,
190 base::TerminationStatus status,
191 int exit_code) {
Wei-Yin Chen (陳威尹)223326c2017-07-21 02:08:28192 RendererType histogram_type =
blundell8ae15622015-09-28 08:34:16193 was_extension_process ? RENDERER_TYPE_EXTENSION : RENDERER_TYPE_RENDERER;
blundell8ae15622015-09-28 08:34:16194
wfh1633bec62016-08-12 02:07:24195 switch (status) {
196 case base::TERMINATION_STATUS_NORMAL_TERMINATION:
197 break;
198 case base::TERMINATION_STATUS_PROCESS_CRASHED:
199 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
200 case base::TERMINATION_STATUS_OOM:
201 if (was_extension_process) {
Ran Ji3537ffa32017-09-21 04:39:01202#if !BUILDFLAG(ENABLE_EXTENSIONS)
203 NOTREACHED();
204#endif
wfh1633bec62016-08-12 02:07:24205 IncrementPrefValue(prefs::kStabilityExtensionRendererCrashCount);
blundell8ae15622015-09-28 08:34:16206
wfh1633bec62016-08-12 02:07:24207 UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Extension",
208 MapCrashExitCodeForHistogram(exit_code));
209 } else {
210 IncrementPrefValue(prefs::kStabilityRendererCrashCount);
blundell8ae15622015-09-28 08:34:16211
wfh1633bec62016-08-12 02:07:24212 UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Renderer",
213 MapCrashExitCodeForHistogram(exit_code));
214 }
215
216 UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.ChildCrashes",
217 histogram_type, RENDERER_TYPE_COUNT);
218 break;
219 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
220 RecordChildKills(histogram_type);
221 break;
222#if defined(OS_ANDROID)
223 case base::TERMINATION_STATUS_OOM_PROTECTED:
224 // TODO(wfh): Check if this should be a Kill or a Crash on Android.
225 break;
blundell8ae15622015-09-28 08:34:16226#endif
wfh1633bec62016-08-12 02:07:24227#if defined(OS_CHROMEOS)
228 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
229 RecordChildKills(histogram_type);
230 UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.ChildKills.OOM",
231 was_extension_process ? 2 : 1, 3);
232 RecordMemoryStats(was_extension_process
233 ? RECORD_MEMORY_STATS_EXTENSIONS_OOM_KILLED
234 : RECORD_MEMORY_STATS_CONTENTS_OOM_KILLED);
235 break;
236#endif
237 case base::TERMINATION_STATUS_STILL_RUNNING:
238 UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.DisconnectedAlive",
239 histogram_type, RENDERER_TYPE_COUNT);
240 break;
241 case base::TERMINATION_STATUS_LAUNCH_FAILED:
242 UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.ChildLaunchFailures",
243 histogram_type, RENDERER_TYPE_COUNT);
244 UMA_HISTOGRAM_SPARSE_SLOWLY(
245 "BrowserRenderProcessHost.ChildLaunchFailureCodes", exit_code);
246 if (was_extension_process)
247 IncrementPrefValue(prefs::kStabilityExtensionRendererFailedLaunchCount);
248 else
249 IncrementPrefValue(prefs::kStabilityRendererFailedLaunchCount);
250 break;
251 case base::TERMINATION_STATUS_MAX_ENUM:
252 NOTREACHED();
253 break;
blundell8ae15622015-09-28 08:34:16254 }
255}
256
wfh86b6c8c2016-07-15 20:48:35257void StabilityMetricsHelper::LogRendererLaunched(bool was_extension_process) {
258 if (was_extension_process)
259 IncrementPrefValue(prefs::kStabilityExtensionRendererLaunchCount);
260 else
261 IncrementPrefValue(prefs::kStabilityRendererLaunchCount);
262}
263
blundell8ae15622015-09-28 08:34:16264void StabilityMetricsHelper::IncrementPrefValue(const char* path) {
265 int value = local_state_->GetInteger(path);
266 local_state_->SetInteger(path, value + 1);
267}
268
269void StabilityMetricsHelper::IncrementLongPrefsValue(const char* path) {
avi26062922015-12-26 00:14:18270 int64_t value = local_state_->GetInt64(path);
blundell8ae15622015-09-28 08:34:16271 local_state_->SetInt64(path, value + 1);
272}
273
274void StabilityMetricsHelper::LogRendererHang() {
275 IncrementPrefValue(prefs::kStabilityRendererHangCount);
276}
277
278} // namespace metrics