Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chromecast / browser / metrics / cast_stability_metrics_provider.cc
blobab21ac231171200e1981ac7c79b5ffdb7bcb4be0
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 "chromecast/browser/metrics/cast_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 "chromecast/base/pref_names.h"
15 #include "chromecast/browser/cast_browser_process.h"
16 #include "chromecast/browser/metrics/cast_metrics_service_client.h"
17 #include "components/metrics/metrics_service.h"
18 #include "components/metrics/proto/system_profile.pb.h"
19 #include "content/public/browser/child_process_data.h"
20 #include "content/public/browser/navigation_controller.h"
21 #include "content/public/browser/notification_service.h"
22 #include "content/public/browser/notification_types.h"
23 #include "content/public/browser/render_process_host.h"
25 namespace chromecast {
26 namespace metrics {
28 namespace {
30 enum RendererType {
31 RENDERER_TYPE_RENDERER = 1,
32 RENDERER_TYPE_EXTENSION, // Not used, but needed for correct histogram count.
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
39 void IncrementPrefValue(const char* path) {
40 PrefService* pref = shell::CastBrowserProcess::GetInstance()->pref_service();
41 DCHECK(pref);
42 int value = pref->GetInteger(path);
43 pref->SetInteger(path, value + 1);
46 // Converts an exit code into something that can be inserted into our
47 // histograms (which expect non-negative numbers less than MAX_INT).
48 int MapCrashExitCodeForHistogram(int exit_code) {
49 return std::abs(exit_code);
52 } // namespace
54 // static
55 void CastStabilityMetricsProvider::RegisterPrefs(PrefRegistrySimple* registry) {
56 registry->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0);
57 registry->RegisterIntegerPref(prefs::kStabilityRendererFailedLaunchCount, 0);
58 registry->RegisterIntegerPref(prefs::kStabilityRendererHangCount, 0);
59 registry->RegisterIntegerPref(prefs::kStabilityChildProcessCrashCount, 0);
62 CastStabilityMetricsProvider::CastStabilityMetricsProvider(
63 ::metrics::MetricsService* metrics_service)
64 : metrics_service_(metrics_service) {
65 BrowserChildProcessObserver::Add(this);
68 CastStabilityMetricsProvider::~CastStabilityMetricsProvider() {
69 BrowserChildProcessObserver::Remove(this);
72 void CastStabilityMetricsProvider::OnRecordingEnabled() {
73 registrar_.Add(this,
74 content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
75 content::NotificationService::AllSources());
76 registrar_.Add(this,
77 content::NOTIFICATION_RENDER_WIDGET_HOST_HANG,
78 content::NotificationService::AllSources());
81 void CastStabilityMetricsProvider::OnRecordingDisabled() {
82 registrar_.RemoveAll();
85 void CastStabilityMetricsProvider::ProvideStabilityMetrics(
86 ::metrics::SystemProfileProto* system_profile_proto) {
87 PrefService* pref = shell::CastBrowserProcess::GetInstance()->pref_service();
88 ::metrics::SystemProfileProto_Stability* stability_proto =
89 system_profile_proto->mutable_stability();
91 int count = pref->GetInteger(prefs::kStabilityChildProcessCrashCount);
92 if (count) {
93 stability_proto->set_child_process_crash_count(count);
94 pref->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
97 count = pref->GetInteger(prefs::kStabilityRendererCrashCount);
98 if (count) {
99 stability_proto->set_renderer_crash_count(count);
100 pref->SetInteger(prefs::kStabilityRendererCrashCount, 0);
103 count = pref->GetInteger(prefs::kStabilityRendererFailedLaunchCount);
104 if (count) {
105 stability_proto->set_renderer_failed_launch_count(count);
106 pref->SetInteger(prefs::kStabilityRendererFailedLaunchCount, 0);
109 count = pref->GetInteger(prefs::kStabilityRendererHangCount);
110 if (count) {
111 stability_proto->set_renderer_hang_count(count);
112 pref->SetInteger(prefs::kStabilityRendererHangCount, 0);
116 void CastStabilityMetricsProvider::LogExternalCrash(
117 const std::string& crash_type) {
118 if (crash_type == "user")
119 IncrementPrefValue(prefs::kStabilityOtherUserCrashCount);
120 else if (crash_type == "kernel")
121 IncrementPrefValue(prefs::kStabilityKernelCrashCount);
122 else if (crash_type == "uncleanshutdown")
123 IncrementPrefValue(prefs::kStabilitySystemUncleanShutdownCount);
124 else
125 NOTREACHED() << "Unexpected crash type " << crash_type;
127 // Wake up metrics logs sending if necessary now that new
128 // log data is available.
129 metrics_service_->OnApplicationNotIdle();
132 void CastStabilityMetricsProvider::Observe(
133 int type,
134 const content::NotificationSource& source,
135 const content::NotificationDetails& details) {
136 switch (type) {
137 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
138 content::RenderProcessHost::RendererClosedDetails* process_details =
139 content::Details<content::RenderProcessHost::RendererClosedDetails>(
140 details).ptr();
141 content::RenderProcessHost* host =
142 content::Source<content::RenderProcessHost>(source).ptr();
143 LogRendererCrash(
144 host, process_details->status, process_details->exit_code);
145 break;
148 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG:
149 LogRendererHang();
150 break;
152 default:
153 NOTREACHED();
154 break;
158 void CastStabilityMetricsProvider::BrowserChildProcessCrashed(
159 const content::ChildProcessData& data,
160 int exit_code) {
161 IncrementPrefValue(prefs::kStabilityChildProcessCrashCount);
164 void CastStabilityMetricsProvider::LogRendererCrash(
165 content::RenderProcessHost* host,
166 base::TerminationStatus status,
167 int exit_code) {
168 if (status == base::TERMINATION_STATUS_PROCESS_CRASHED ||
169 status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
170 IncrementPrefValue(prefs::kStabilityRendererCrashCount);
172 UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Renderer",
173 MapCrashExitCodeForHistogram(exit_code));
174 UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.ChildCrashes",
175 RENDERER_TYPE_RENDERER, RENDERER_TYPE_COUNT);
176 } else if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
177 UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.ChildKills",
178 RENDERER_TYPE_RENDERER, RENDERER_TYPE_COUNT);
179 } else if (status == base::TERMINATION_STATUS_STILL_RUNNING) {
180 UMA_HISTOGRAM_ENUMERATION("BrowserRenderProcessHost.DisconnectedAlive",
181 RENDERER_TYPE_RENDERER, RENDERER_TYPE_COUNT);
182 } else if (status == base::TERMINATION_STATUS_LAUNCH_FAILED) {
183 IncrementPrefValue(prefs::kStabilityRendererFailedLaunchCount);
187 void CastStabilityMetricsProvider::LogRendererHang() {
188 IncrementPrefValue(prefs::kStabilityRendererHangCount);
191 } // namespace metrics
192 } // namespace chromecast