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/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/common/chromecast_config.h"
15 #include "chromecast/common/pref_names.h"
16 #include "chromecast/metrics/cast_metrics_service_client.h"
17 #include "components/metrics/proto/system_profile.pb.h"
18 #include "content/public/browser/child_process_data.h"
19 #include "content/public/browser/navigation_controller.h"
20 #include "content/public/browser/notification_service.h"
21 #include "content/public/browser/notification_types.h"
22 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/user_metrics.h"
25 namespace chromecast
{
30 void IncrementPrefValue(const char* path
) {
31 PrefService
* pref
= ChromecastConfig::GetInstance()->pref_service();
33 int value
= pref
->GetInteger(path
);
34 pref
->SetInteger(path
, value
+ 1);
37 // Converts an exit code into something that can be inserted into our
38 // histograms (which expect non-negative numbers less than MAX_INT).
39 int MapCrashExitCodeForHistogram(int exit_code
) {
40 return std::abs(exit_code
);
46 void CastStabilityMetricsProvider::RegisterPrefs(PrefRegistrySimple
* registry
) {
47 registry
->RegisterIntegerPref(prefs::kStabilityRendererCrashCount
, 0);
48 registry
->RegisterIntegerPref(prefs::kStabilityRendererHangCount
, 0);
49 registry
->RegisterIntegerPref(prefs::kStabilityChildProcessCrashCount
, 0);
52 CastStabilityMetricsProvider::CastStabilityMetricsProvider() {
53 BrowserChildProcessObserver::Add(this);
56 CastStabilityMetricsProvider::~CastStabilityMetricsProvider() {
57 BrowserChildProcessObserver::Remove(this);
60 void CastStabilityMetricsProvider::OnRecordingEnabled() {
62 content::NOTIFICATION_RENDERER_PROCESS_CLOSED
,
63 content::NotificationService::AllSources());
65 content::NOTIFICATION_RENDER_WIDGET_HOST_HANG
,
66 content::NotificationService::AllSources());
69 void CastStabilityMetricsProvider::OnRecordingDisabled() {
70 registrar_
.RemoveAll();
73 void CastStabilityMetricsProvider::ProvideStabilityMetrics(
74 ::metrics::SystemProfileProto
* system_profile_proto
) {
75 PrefService
* pref
= ChromecastConfig::GetInstance()->pref_service();
76 ::metrics::SystemProfileProto_Stability
* stability_proto
=
77 system_profile_proto
->mutable_stability();
79 int count
= pref
->GetInteger(prefs::kStabilityChildProcessCrashCount
);
81 stability_proto
->set_child_process_crash_count(count
);
82 pref
->SetInteger(prefs::kStabilityChildProcessCrashCount
, 0);
85 count
= pref
->GetInteger(prefs::kStabilityRendererCrashCount
);
87 stability_proto
->set_renderer_crash_count(count
);
88 pref
->SetInteger(prefs::kStabilityRendererCrashCount
, 0);
91 count
= pref
->GetInteger(prefs::kStabilityRendererHangCount
);
93 stability_proto
->set_renderer_hang_count(count
);
94 pref
->SetInteger(prefs::kStabilityRendererHangCount
, 0);
98 void CastStabilityMetricsProvider::Observe(
100 const content::NotificationSource
& source
,
101 const content::NotificationDetails
& details
) {
103 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED
: {
104 content::RenderProcessHost::RendererClosedDetails
* process_details
=
105 content::Details
<content::RenderProcessHost::RendererClosedDetails
>(
107 content::RenderProcessHost
* host
=
108 content::Source
<content::RenderProcessHost
>(source
).ptr();
110 host
, process_details
->status
, process_details
->exit_code
);
114 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG
:
124 void CastStabilityMetricsProvider::BrowserChildProcessCrashed(
125 const content::ChildProcessData
& data
) {
126 IncrementPrefValue(prefs::kStabilityChildProcessCrashCount
);
129 void CastStabilityMetricsProvider::LogRendererCrash(
130 content::RenderProcessHost
* host
,
131 base::TerminationStatus status
,
133 if (status
== base::TERMINATION_STATUS_PROCESS_CRASHED
||
134 status
== base::TERMINATION_STATUS_ABNORMAL_TERMINATION
) {
135 IncrementPrefValue(prefs::kStabilityRendererCrashCount
);
137 UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Renderer",
138 MapCrashExitCodeForHistogram(exit_code
));
139 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildCrashes", 1);
140 } else if (status
== base::TERMINATION_STATUS_PROCESS_WAS_KILLED
) {
141 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildKills", 1);
142 } else if (status
== base::TERMINATION_STATUS_STILL_RUNNING
) {
143 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.DisconnectedAlive", 1);
147 void CastStabilityMetricsProvider::LogRendererHang() {
148 IncrementPrefValue(prefs::kStabilityRendererHangCount
);
151 } // namespace metrics
152 } // namespace chromecast