Add ENABLE_MEDIA_ROUTER define to builds other than Android and iOS.
[chromium-blink-merge.git] / chrome / browser / metrics / chrome_stability_metrics_provider.cc
bloba5e31427ff092e2820a66d63b41e5c6df3e83c35
1 // Copyright 2014 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.
5 #include "chrome/browser/metrics/chrome_stability_metrics_provider.h"
7 #include <vector>
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/metrics/sparse_histogram.h"
12 #include "base/prefs/pref_registry_simple.h"
13 #include "base/prefs/pref_service.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/common/chrome_constants.h"
17 #include "chrome/common/pref_names.h"
18 #include "components/metrics/proto/system_profile.pb.h"
19 #include "content/public/browser/child_process_data.h"
20 #include "content/public/browser/notification_service.h"
21 #include "content/public/browser/render_process_host.h"
22 #include "content/public/browser/user_metrics.h"
23 #include "content/public/browser/web_contents.h"
25 #if defined(ENABLE_EXTENSIONS)
26 #include "extensions/browser/process_map.h"
27 #endif
29 #if defined(ENABLE_PLUGINS)
30 #include "chrome/browser/metrics/plugin_metrics_provider.h"
31 #endif
33 #if defined(OS_WIN)
34 #include <windows.h> // Needed for STATUS_* codes
35 #include "chrome/installer/util/install_util.h"
36 #include "components/browser_watcher/crash_reporting_metrics_win.h"
37 #endif
39 namespace {
41 void IncrementPrefValue(const char* path) {
42 PrefService* pref = g_browser_process->local_state();
43 DCHECK(pref);
44 int value = pref->GetInteger(path);
45 pref->SetInteger(path, value + 1);
48 void IncrementLongPrefsValue(const char* path) {
49 PrefService* pref = g_browser_process->local_state();
50 DCHECK(pref);
51 int64 value = pref->GetInt64(path);
52 pref->SetInt64(path, value + 1);
55 // Converts an exit code into something that can be inserted into our
56 // histograms (which expect non-negative numbers less than MAX_INT).
57 int MapCrashExitCodeForHistogram(int exit_code) {
58 #if defined(OS_WIN)
59 // Since |abs(STATUS_GUARD_PAGE_VIOLATION) == MAX_INT| it causes problems in
60 // histograms.cc. Solve this by remapping it to a smaller value, which
61 // hopefully doesn't conflict with other codes.
62 if (exit_code == STATUS_GUARD_PAGE_VIOLATION)
63 return 0x1FCF7EC3; // Randomly picked number.
64 #endif
66 return std::abs(exit_code);
69 #if defined(OS_WIN)
70 void CountBrowserCrashDumpAttempts() {
71 enum Outcome {
72 OUTCOME_SUCCESS,
73 OUTCOME_FAILURE,
74 OUTCOME_UNKNOWN,
75 OUTCOME_MAX_VALUE
78 browser_watcher::CrashReportingMetrics::Values metrics =
79 browser_watcher::CrashReportingMetrics(
80 InstallUtil::IsChromeSxSProcess()
81 ? chrome::kBrowserCrashDumpAttemptsRegistryPathSxS
82 : chrome::kBrowserCrashDumpAttemptsRegistryPath)
83 .RetrieveAndResetMetrics();
85 for (int i = 0; i < metrics.crash_dump_attempts; ++i) {
86 Outcome outcome = OUTCOME_UNKNOWN;
87 if (i < metrics.successful_crash_dumps)
88 outcome = OUTCOME_SUCCESS;
89 else if (i < metrics.successful_crash_dumps + metrics.failed_crash_dumps)
90 outcome = OUTCOME_FAILURE;
92 UMA_STABILITY_HISTOGRAM_ENUMERATION("CrashReport.BreakpadCrashDumpOutcome",
93 outcome, OUTCOME_MAX_VALUE);
96 for (int i = 0; i < metrics.dump_without_crash_attempts; ++i) {
97 Outcome outcome = OUTCOME_UNKNOWN;
98 if (i < metrics.successful_dumps_without_crash) {
99 outcome = OUTCOME_SUCCESS;
100 } else if (i < metrics.successful_dumps_without_crash +
101 metrics.failed_dumps_without_crash) {
102 outcome = OUTCOME_FAILURE;
105 UMA_STABILITY_HISTOGRAM_ENUMERATION(
106 "CrashReport.BreakpadDumpWithoutCrashOutcome", outcome,
107 OUTCOME_MAX_VALUE);
110 #endif // defined(OS_WIN)
112 } // namespace
114 ChromeStabilityMetricsProvider::ChromeStabilityMetricsProvider() {
115 BrowserChildProcessObserver::Add(this);
118 ChromeStabilityMetricsProvider::~ChromeStabilityMetricsProvider() {
119 BrowserChildProcessObserver::Remove(this);
122 void ChromeStabilityMetricsProvider::OnRecordingEnabled() {
123 registrar_.Add(this,
124 content::NOTIFICATION_LOAD_START,
125 content::NotificationService::AllSources());
126 registrar_.Add(this,
127 content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
128 content::NotificationService::AllSources());
129 registrar_.Add(this,
130 content::NOTIFICATION_RENDER_WIDGET_HOST_HANG,
131 content::NotificationService::AllSources());
134 void ChromeStabilityMetricsProvider::OnRecordingDisabled() {
135 registrar_.RemoveAll();
138 void ChromeStabilityMetricsProvider::ProvideStabilityMetrics(
139 metrics::SystemProfileProto* system_profile_proto) {
140 PrefService* pref = g_browser_process->local_state();
141 metrics::SystemProfileProto_Stability* stability_proto =
142 system_profile_proto->mutable_stability();
144 int count = pref->GetInteger(prefs::kStabilityPageLoadCount);
145 if (count) {
146 stability_proto->set_page_load_count(count);
147 pref->SetInteger(prefs::kStabilityPageLoadCount, 0);
150 count = pref->GetInteger(prefs::kStabilityChildProcessCrashCount);
151 if (count) {
152 stability_proto->set_child_process_crash_count(count);
153 pref->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
156 count = pref->GetInteger(prefs::kStabilityRendererCrashCount);
157 if (count) {
158 stability_proto->set_renderer_crash_count(count);
159 pref->SetInteger(prefs::kStabilityRendererCrashCount, 0);
162 count = pref->GetInteger(prefs::kStabilityExtensionRendererCrashCount);
163 if (count) {
164 stability_proto->set_extension_renderer_crash_count(count);
165 pref->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0);
168 count = pref->GetInteger(prefs::kStabilityRendererHangCount);
169 if (count) {
170 stability_proto->set_renderer_hang_count(count);
171 pref->SetInteger(prefs::kStabilityRendererHangCount, 0);
174 #if defined(OS_WIN)
175 CountBrowserCrashDumpAttempts();
176 #endif // defined(OS_WIN)
179 void ChromeStabilityMetricsProvider::ClearSavedStabilityMetrics() {
180 PrefService* local_state = g_browser_process->local_state();
182 // Clear all the prefs used in this class in UMA reports (which doesn't
183 // include |kUninstallMetricsPageLoadCount| as it's not sent up by UMA).
184 local_state->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
185 local_state->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0);
186 local_state->SetInteger(prefs::kStabilityPageLoadCount, 0);
187 local_state->SetInteger(prefs::kStabilityRendererCrashCount, 0);
188 local_state->SetInteger(prefs::kStabilityRendererHangCount, 0);
191 // static
192 void ChromeStabilityMetricsProvider::RegisterPrefs(
193 PrefRegistrySimple* registry) {
194 registry->RegisterIntegerPref(prefs::kStabilityChildProcessCrashCount, 0);
195 registry->RegisterIntegerPref(prefs::kStabilityExtensionRendererCrashCount,
197 registry->RegisterIntegerPref(prefs::kStabilityPageLoadCount, 0);
198 registry->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0);
199 registry->RegisterIntegerPref(prefs::kStabilityRendererHangCount, 0);
201 registry->RegisterInt64Pref(prefs::kUninstallMetricsPageLoadCount, 0);
204 void ChromeStabilityMetricsProvider::Observe(
205 int type,
206 const content::NotificationSource& source,
207 const content::NotificationDetails& details) {
208 switch (type) {
209 case content::NOTIFICATION_LOAD_START: {
210 content::NavigationController* controller =
211 content::Source<content::NavigationController>(source).ptr();
212 content::WebContents* web_contents = controller->GetWebContents();
213 LogLoadStarted(web_contents);
214 break;
217 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
218 content::RenderProcessHost::RendererClosedDetails* process_details =
219 content::Details<content::RenderProcessHost::RendererClosedDetails>(
220 details).ptr();
221 content::RenderProcessHost* host =
222 content::Source<content::RenderProcessHost>(source).ptr();
223 LogRendererCrash(
224 host, process_details->status, process_details->exit_code);
225 break;
228 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG:
229 LogRendererHang();
230 break;
232 default:
233 NOTREACHED();
234 break;
238 void ChromeStabilityMetricsProvider::BrowserChildProcessCrashed(
239 const content::ChildProcessData& data) {
240 #if defined(ENABLE_PLUGINS)
241 // Exclude plugin crashes from the count below because we report them via
242 // a separate UMA metric.
243 if (PluginMetricsProvider::IsPluginProcess(data.process_type))
244 return;
245 #endif
247 IncrementPrefValue(prefs::kStabilityChildProcessCrashCount);
250 void ChromeStabilityMetricsProvider::LogLoadStarted(
251 content::WebContents* web_contents) {
252 content::RecordAction(base::UserMetricsAction("PageLoad"));
253 // TODO(asvitkine): Check if this is used for anything and if not, remove.
254 LOCAL_HISTOGRAM_BOOLEAN("Chrome.UmaPageloadCounter", true);
255 IncrementPrefValue(prefs::kStabilityPageLoadCount);
256 IncrementLongPrefsValue(prefs::kUninstallMetricsPageLoadCount);
257 // We need to save the prefs, as page load count is a critical stat, and it
258 // might be lost due to a crash :-(.
261 void ChromeStabilityMetricsProvider::LogRendererCrash(
262 content::RenderProcessHost* host,
263 base::TerminationStatus status,
264 int exit_code) {
265 bool was_extension_process = false;
266 #if defined(ENABLE_EXTENSIONS)
267 was_extension_process =
268 extensions::ProcessMap::Get(host->GetBrowserContext())->Contains(
269 host->GetID());
270 #endif
271 if (status == base::TERMINATION_STATUS_PROCESS_CRASHED ||
272 status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
273 if (was_extension_process) {
274 IncrementPrefValue(prefs::kStabilityExtensionRendererCrashCount);
276 UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Extension",
277 MapCrashExitCodeForHistogram(exit_code));
278 } else {
279 IncrementPrefValue(prefs::kStabilityRendererCrashCount);
281 UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Renderer",
282 MapCrashExitCodeForHistogram(exit_code));
285 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildCrashes",
286 was_extension_process ? 2 : 1);
287 } else if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
288 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildKills",
289 was_extension_process ? 2 : 1);
290 } else if (status == base::TERMINATION_STATUS_STILL_RUNNING) {
291 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.DisconnectedAlive",
292 was_extension_process ? 2 : 1);
296 void ChromeStabilityMetricsProvider::LogRendererHang() {
297 IncrementPrefValue(prefs::kStabilityRendererHangCount);