Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / metrics / chrome_stability_metrics_provider.cc
bloba26d263d3f6913906dcaef38f4e92358f05fdc64
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 #if defined(OS_CHROMEOS)
40 #include "chrome/browser/memory/system_memory_stats_recorder.h"
41 #endif
43 namespace {
45 void IncrementPrefValue(const char* path) {
46 PrefService* pref = g_browser_process->local_state();
47 DCHECK(pref);
48 int value = pref->GetInteger(path);
49 pref->SetInteger(path, value + 1);
52 void IncrementLongPrefsValue(const char* path) {
53 PrefService* pref = g_browser_process->local_state();
54 DCHECK(pref);
55 int64 value = pref->GetInt64(path);
56 pref->SetInt64(path, value + 1);
59 // Converts an exit code into something that can be inserted into our
60 // histograms (which expect non-negative numbers less than MAX_INT).
61 int MapCrashExitCodeForHistogram(int exit_code) {
62 #if defined(OS_WIN)
63 // Since |abs(STATUS_GUARD_PAGE_VIOLATION) == MAX_INT| it causes problems in
64 // histograms.cc. Solve this by remapping it to a smaller value, which
65 // hopefully doesn't conflict with other codes.
66 if (exit_code == STATUS_GUARD_PAGE_VIOLATION)
67 return 0x1FCF7EC3; // Randomly picked number.
68 #endif
70 return std::abs(exit_code);
73 #if defined(OS_WIN)
74 void CountBrowserCrashDumpAttempts() {
75 enum Outcome {
76 OUTCOME_SUCCESS,
77 OUTCOME_FAILURE,
78 OUTCOME_UNKNOWN,
79 OUTCOME_MAX_VALUE
82 browser_watcher::CrashReportingMetrics::Values metrics =
83 browser_watcher::CrashReportingMetrics(
84 InstallUtil::IsChromeSxSProcess()
85 ? chrome::kBrowserCrashDumpAttemptsRegistryPathSxS
86 : chrome::kBrowserCrashDumpAttemptsRegistryPath)
87 .RetrieveAndResetMetrics();
89 for (int i = 0; i < metrics.crash_dump_attempts; ++i) {
90 Outcome outcome = OUTCOME_UNKNOWN;
91 if (i < metrics.successful_crash_dumps)
92 outcome = OUTCOME_SUCCESS;
93 else if (i < metrics.successful_crash_dumps + metrics.failed_crash_dumps)
94 outcome = OUTCOME_FAILURE;
96 UMA_STABILITY_HISTOGRAM_ENUMERATION("CrashReport.BreakpadCrashDumpOutcome",
97 outcome, OUTCOME_MAX_VALUE);
100 for (int i = 0; i < metrics.dump_without_crash_attempts; ++i) {
101 Outcome outcome = OUTCOME_UNKNOWN;
102 if (i < metrics.successful_dumps_without_crash) {
103 outcome = OUTCOME_SUCCESS;
104 } else if (i < metrics.successful_dumps_without_crash +
105 metrics.failed_dumps_without_crash) {
106 outcome = OUTCOME_FAILURE;
109 UMA_STABILITY_HISTOGRAM_ENUMERATION(
110 "CrashReport.BreakpadDumpWithoutCrashOutcome", outcome,
111 OUTCOME_MAX_VALUE);
114 #endif // defined(OS_WIN)
116 void RecordChildKills(bool was_extension_process) {
117 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildKills",
118 was_extension_process ? 2 : 1);
121 } // namespace
123 ChromeStabilityMetricsProvider::ChromeStabilityMetricsProvider() {
124 BrowserChildProcessObserver::Add(this);
127 ChromeStabilityMetricsProvider::~ChromeStabilityMetricsProvider() {
128 BrowserChildProcessObserver::Remove(this);
131 void ChromeStabilityMetricsProvider::OnRecordingEnabled() {
132 registrar_.Add(this,
133 content::NOTIFICATION_LOAD_START,
134 content::NotificationService::AllSources());
135 registrar_.Add(this,
136 content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
137 content::NotificationService::AllSources());
138 registrar_.Add(this,
139 content::NOTIFICATION_RENDER_WIDGET_HOST_HANG,
140 content::NotificationService::AllSources());
143 void ChromeStabilityMetricsProvider::OnRecordingDisabled() {
144 registrar_.RemoveAll();
147 void ChromeStabilityMetricsProvider::ProvideStabilityMetrics(
148 metrics::SystemProfileProto* system_profile_proto) {
149 PrefService* pref = g_browser_process->local_state();
150 metrics::SystemProfileProto_Stability* stability_proto =
151 system_profile_proto->mutable_stability();
153 int count = pref->GetInteger(prefs::kStabilityPageLoadCount);
154 if (count) {
155 stability_proto->set_page_load_count(count);
156 pref->SetInteger(prefs::kStabilityPageLoadCount, 0);
159 count = pref->GetInteger(prefs::kStabilityChildProcessCrashCount);
160 if (count) {
161 stability_proto->set_child_process_crash_count(count);
162 pref->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
165 count = pref->GetInteger(prefs::kStabilityRendererCrashCount);
166 if (count) {
167 stability_proto->set_renderer_crash_count(count);
168 pref->SetInteger(prefs::kStabilityRendererCrashCount, 0);
171 count = pref->GetInteger(prefs::kStabilityExtensionRendererCrashCount);
172 if (count) {
173 stability_proto->set_extension_renderer_crash_count(count);
174 pref->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0);
177 count = pref->GetInteger(prefs::kStabilityRendererHangCount);
178 if (count) {
179 stability_proto->set_renderer_hang_count(count);
180 pref->SetInteger(prefs::kStabilityRendererHangCount, 0);
183 #if defined(OS_WIN)
184 CountBrowserCrashDumpAttempts();
185 #endif // defined(OS_WIN)
188 void ChromeStabilityMetricsProvider::ClearSavedStabilityMetrics() {
189 PrefService* local_state = g_browser_process->local_state();
191 // Clear all the prefs used in this class in UMA reports (which doesn't
192 // include |kUninstallMetricsPageLoadCount| as it's not sent up by UMA).
193 local_state->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
194 local_state->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0);
195 local_state->SetInteger(prefs::kStabilityPageLoadCount, 0);
196 local_state->SetInteger(prefs::kStabilityRendererCrashCount, 0);
197 local_state->SetInteger(prefs::kStabilityRendererHangCount, 0);
200 // static
201 void ChromeStabilityMetricsProvider::RegisterPrefs(
202 PrefRegistrySimple* registry) {
203 registry->RegisterIntegerPref(prefs::kStabilityChildProcessCrashCount, 0);
204 registry->RegisterIntegerPref(prefs::kStabilityExtensionRendererCrashCount,
206 registry->RegisterIntegerPref(prefs::kStabilityPageLoadCount, 0);
207 registry->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0);
208 registry->RegisterIntegerPref(prefs::kStabilityRendererHangCount, 0);
210 registry->RegisterInt64Pref(prefs::kUninstallMetricsPageLoadCount, 0);
213 void ChromeStabilityMetricsProvider::Observe(
214 int type,
215 const content::NotificationSource& source,
216 const content::NotificationDetails& details) {
217 switch (type) {
218 case content::NOTIFICATION_LOAD_START: {
219 content::NavigationController* controller =
220 content::Source<content::NavigationController>(source).ptr();
221 content::WebContents* web_contents = controller->GetWebContents();
222 LogLoadStarted(web_contents);
223 break;
226 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
227 content::RenderProcessHost::RendererClosedDetails* process_details =
228 content::Details<content::RenderProcessHost::RendererClosedDetails>(
229 details).ptr();
230 content::RenderProcessHost* host =
231 content::Source<content::RenderProcessHost>(source).ptr();
232 LogRendererCrash(
233 host, process_details->status, process_details->exit_code);
234 break;
237 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG:
238 LogRendererHang();
239 break;
241 default:
242 NOTREACHED();
243 break;
247 void ChromeStabilityMetricsProvider::BrowserChildProcessCrashed(
248 const content::ChildProcessData& data,
249 int exit_code) {
250 #if defined(ENABLE_PLUGINS)
251 // Exclude plugin crashes from the count below because we report them via
252 // a separate UMA metric.
253 if (PluginMetricsProvider::IsPluginProcess(data.process_type))
254 return;
255 #endif
257 IncrementPrefValue(prefs::kStabilityChildProcessCrashCount);
260 void ChromeStabilityMetricsProvider::LogLoadStarted(
261 content::WebContents* web_contents) {
262 content::RecordAction(base::UserMetricsAction("PageLoad"));
263 // TODO(asvitkine): Check if this is used for anything and if not, remove.
264 LOCAL_HISTOGRAM_BOOLEAN("Chrome.UmaPageloadCounter", true);
265 IncrementPrefValue(prefs::kStabilityPageLoadCount);
266 IncrementLongPrefsValue(prefs::kUninstallMetricsPageLoadCount);
267 // We need to save the prefs, as page load count is a critical stat, and it
268 // might be lost due to a crash :-(.
271 void ChromeStabilityMetricsProvider::LogRendererCrash(
272 content::RenderProcessHost* host,
273 base::TerminationStatus status,
274 int exit_code) {
275 bool was_extension_process = false;
276 #if defined(ENABLE_EXTENSIONS)
277 was_extension_process =
278 extensions::ProcessMap::Get(host->GetBrowserContext())->Contains(
279 host->GetID());
280 #endif
281 if (status == base::TERMINATION_STATUS_PROCESS_CRASHED ||
282 status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
283 if (was_extension_process) {
284 IncrementPrefValue(prefs::kStabilityExtensionRendererCrashCount);
286 UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Extension",
287 MapCrashExitCodeForHistogram(exit_code));
288 } else {
289 IncrementPrefValue(prefs::kStabilityRendererCrashCount);
291 UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Renderer",
292 MapCrashExitCodeForHistogram(exit_code));
295 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildCrashes",
296 was_extension_process ? 2 : 1);
297 } else if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
298 RecordChildKills(was_extension_process);
299 #if defined(OS_CHROMEOS)
300 } else if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM) {
301 RecordChildKills(was_extension_process);
302 UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.ChildKills.OOM",
303 was_extension_process ? 2 : 1,
305 memory::RecordMemoryStats(
306 was_extension_process
307 ? memory::RECORD_MEMORY_STATS_EXTENSIONS_OOM_KILLED
308 : memory::RECORD_MEMORY_STATS_CONTENTS_OOM_KILLED);
309 #endif
310 } else if (status == base::TERMINATION_STATUS_STILL_RUNNING) {
311 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.DisconnectedAlive",
312 was_extension_process ? 2 : 1);
316 void ChromeStabilityMetricsProvider::LogRendererHang() {
317 IncrementPrefValue(prefs::kStabilityRendererHangCount);