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/browser/cast_browser_process.h"
15 #include "chromecast/browser/metrics/cast_metrics_service_client.h"
16 #include "chromecast/common/pref_names.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
{
30 void IncrementPrefValue(const char* path
) {
31 PrefService
* pref
= shell::CastBrowserProcess::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 ::metrics::MetricsService
* metrics_service
)
54 : metrics_service_(metrics_service
) {
55 BrowserChildProcessObserver::Add(this);
58 CastStabilityMetricsProvider::~CastStabilityMetricsProvider() {
59 BrowserChildProcessObserver::Remove(this);
62 void CastStabilityMetricsProvider::OnRecordingEnabled() {
64 content::NOTIFICATION_RENDERER_PROCESS_CLOSED
,
65 content::NotificationService::AllSources());
67 content::NOTIFICATION_RENDER_WIDGET_HOST_HANG
,
68 content::NotificationService::AllSources());
71 void CastStabilityMetricsProvider::OnRecordingDisabled() {
72 registrar_
.RemoveAll();
75 void CastStabilityMetricsProvider::ProvideStabilityMetrics(
76 ::metrics::SystemProfileProto
* system_profile_proto
) {
77 PrefService
* pref
= shell::CastBrowserProcess::GetInstance()->pref_service();
78 ::metrics::SystemProfileProto_Stability
* stability_proto
=
79 system_profile_proto
->mutable_stability();
81 int count
= pref
->GetInteger(prefs::kStabilityChildProcessCrashCount
);
83 stability_proto
->set_child_process_crash_count(count
);
84 pref
->SetInteger(prefs::kStabilityChildProcessCrashCount
, 0);
87 count
= pref
->GetInteger(prefs::kStabilityRendererCrashCount
);
89 stability_proto
->set_renderer_crash_count(count
);
90 pref
->SetInteger(prefs::kStabilityRendererCrashCount
, 0);
93 count
= pref
->GetInteger(prefs::kStabilityRendererHangCount
);
95 stability_proto
->set_renderer_hang_count(count
);
96 pref
->SetInteger(prefs::kStabilityRendererHangCount
, 0);
100 void CastStabilityMetricsProvider::LogExternalCrash(
101 const std::string
& crash_type
) {
102 if (crash_type
== "user")
103 IncrementPrefValue(prefs::kStabilityOtherUserCrashCount
);
104 else if (crash_type
== "kernel")
105 IncrementPrefValue(prefs::kStabilityKernelCrashCount
);
106 else if (crash_type
== "uncleanshutdown")
107 IncrementPrefValue(prefs::kStabilitySystemUncleanShutdownCount
);
109 NOTREACHED() << "Unexpected crash type " << crash_type
;
111 // Wake up metrics logs sending if necessary now that new
112 // log data is available.
113 metrics_service_
->OnApplicationNotIdle();
116 void CastStabilityMetricsProvider::Observe(
118 const content::NotificationSource
& source
,
119 const content::NotificationDetails
& details
) {
121 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED
: {
122 content::RenderProcessHost::RendererClosedDetails
* process_details
=
123 content::Details
<content::RenderProcessHost::RendererClosedDetails
>(
125 content::RenderProcessHost
* host
=
126 content::Source
<content::RenderProcessHost
>(source
).ptr();
128 host
, process_details
->status
, process_details
->exit_code
);
132 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG
:
142 void CastStabilityMetricsProvider::BrowserChildProcessCrashed(
143 const content::ChildProcessData
& data
,
145 IncrementPrefValue(prefs::kStabilityChildProcessCrashCount
);
148 void CastStabilityMetricsProvider::LogRendererCrash(
149 content::RenderProcessHost
* host
,
150 base::TerminationStatus status
,
152 if (status
== base::TERMINATION_STATUS_PROCESS_CRASHED
||
153 status
== base::TERMINATION_STATUS_ABNORMAL_TERMINATION
) {
154 IncrementPrefValue(prefs::kStabilityRendererCrashCount
);
156 UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Renderer",
157 MapCrashExitCodeForHistogram(exit_code
));
158 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildCrashes", 1);
159 } else if (status
== base::TERMINATION_STATUS_PROCESS_WAS_KILLED
) {
160 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildKills", 1);
161 } else if (status
== base::TERMINATION_STATUS_STILL_RUNNING
) {
162 UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.DisconnectedAlive", 1);
166 void CastStabilityMetricsProvider::LogRendererHang() {
167 IncrementPrefValue(prefs::kStabilityRendererHangCount
);
170 } // namespace metrics
171 } // namespace chromecast