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"
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
{
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.
39 void IncrementPrefValue(const char* path
) {
40 PrefService
* pref
= shell::CastBrowserProcess::GetInstance()->pref_service();
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
);
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() {
74 content::NOTIFICATION_RENDERER_PROCESS_CLOSED
,
75 content::NotificationService::AllSources());
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
);
93 stability_proto
->set_child_process_crash_count(count
);
94 pref
->SetInteger(prefs::kStabilityChildProcessCrashCount
, 0);
97 count
= pref
->GetInteger(prefs::kStabilityRendererCrashCount
);
99 stability_proto
->set_renderer_crash_count(count
);
100 pref
->SetInteger(prefs::kStabilityRendererCrashCount
, 0);
103 count
= pref
->GetInteger(prefs::kStabilityRendererFailedLaunchCount
);
105 stability_proto
->set_renderer_failed_launch_count(count
);
106 pref
->SetInteger(prefs::kStabilityRendererFailedLaunchCount
, 0);
109 count
= pref
->GetInteger(prefs::kStabilityRendererHangCount
);
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
);
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(
134 const content::NotificationSource
& source
,
135 const content::NotificationDetails
& details
) {
137 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED
: {
138 content::RenderProcessHost::RendererClosedDetails
* process_details
=
139 content::Details
<content::RenderProcessHost::RendererClosedDetails
>(
141 content::RenderProcessHost
* host
=
142 content::Source
<content::RenderProcessHost
>(source
).ptr();
144 host
, process_details
->status
, process_details
->exit_code
);
148 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG
:
158 void CastStabilityMetricsProvider::BrowserChildProcessCrashed(
159 const content::ChildProcessData
& data
,
161 IncrementPrefValue(prefs::kStabilityChildProcessCrashCount
);
164 void CastStabilityMetricsProvider::LogRendererCrash(
165 content::RenderProcessHost
* host
,
166 base::TerminationStatus status
,
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