OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chromecast/metrics/cast_stability_metrics_provider.h" | |
6 | |
7 #include <vector> | |
8 | |
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" | |
24 | |
25 namespace chromecast { | |
26 namespace metrics { | |
27 | |
28 namespace { | |
29 | |
30 void IncrementPrefValue(const char* path) { | |
31 PrefService* pref = ChromecastConfig::GetInstance()->pref_service(); | |
32 DCHECK(pref); | |
33 int value = pref->GetInteger(path); | |
34 pref->SetInteger(path, value + 1); | |
35 } | |
36 | |
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); | |
41 } | |
42 | |
43 } // namespace | |
44 | |
45 // static | |
46 void CastStabilityMetricsProvider::RegisterPrefs(PrefRegistrySimple* registry) { | |
47 registry->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0); | |
48 registry->RegisterIntegerPref(prefs::kStabilityRendererHangCount, 0); | |
49 registry->RegisterIntegerPref(prefs::kStabilityChildProcessCrashCount, 0); | |
50 } | |
51 | |
52 CastStabilityMetricsProvider::CastStabilityMetricsProvider() { | |
53 BrowserChildProcessObserver::Add(this); | |
54 } | |
55 | |
56 CastStabilityMetricsProvider::~CastStabilityMetricsProvider() { | |
57 BrowserChildProcessObserver::Remove(this); | |
58 } | |
59 | |
60 void CastStabilityMetricsProvider::OnRecordingEnabled() { | |
61 registrar_.Add(this, | |
62 content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
63 content::NotificationService::AllSources()); | |
64 registrar_.Add(this, | |
65 content::NOTIFICATION_RENDER_WIDGET_HOST_HANG, | |
66 content::NotificationService::AllSources()); | |
67 } | |
68 | |
69 void CastStabilityMetricsProvider::OnRecordingDisabled() { | |
70 registrar_.RemoveAll(); | |
71 } | |
72 | |
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(); | |
78 | |
79 int count = pref->GetInteger(prefs::kStabilityChildProcessCrashCount); | |
80 if (count) { | |
81 stability_proto->set_child_process_crash_count(count); | |
82 pref->SetInteger(prefs::kStabilityChildProcessCrashCount, 0); | |
83 } | |
84 | |
85 count = pref->GetInteger(prefs::kStabilityRendererCrashCount); | |
86 if (count) { | |
87 stability_proto->set_renderer_crash_count(count); | |
88 pref->SetInteger(prefs::kStabilityRendererCrashCount, 0); | |
89 } | |
90 | |
91 count = pref->GetInteger(prefs::kStabilityRendererHangCount); | |
92 if (count) { | |
93 stability_proto->set_renderer_hang_count(count); | |
94 pref->SetInteger(prefs::kStabilityRendererHangCount, 0); | |
95 } | |
96 } | |
97 | |
98 void CastStabilityMetricsProvider::Observe( | |
99 int type, | |
100 const content::NotificationSource& source, | |
101 const content::NotificationDetails& details) { | |
102 switch (type) { | |
103 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { | |
104 content::RenderProcessHost::RendererClosedDetails* process_details = | |
105 content::Details<content::RenderProcessHost::RendererClosedDetails>( | |
106 details).ptr(); | |
107 content::RenderProcessHost* host = | |
108 content::Source<content::RenderProcessHost>(source).ptr(); | |
109 LogRendererCrash( | |
110 host, process_details->status, process_details->exit_code); | |
111 break; | |
112 } | |
113 | |
114 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG: | |
115 LogRendererHang(); | |
116 break; | |
117 | |
118 default: | |
119 NOTREACHED(); | |
120 break; | |
121 } | |
122 } | |
123 | |
124 void CastStabilityMetricsProvider::BrowserChildProcessCrashed( | |
125 const content::ChildProcessData& data) { | |
126 IncrementPrefValue(prefs::kStabilityChildProcessCrashCount); | |
127 } | |
128 | |
129 void CastStabilityMetricsProvider::LogRendererCrash( | |
130 content::RenderProcessHost* host, | |
131 base::TerminationStatus status, | |
132 int exit_code) { | |
133 if (status == base::TERMINATION_STATUS_PROCESS_CRASHED || | |
134 status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) { | |
135 IncrementPrefValue(prefs::kStabilityRendererCrashCount); | |
136 | |
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); | |
144 } | |
145 } | |
146 | |
147 void CastStabilityMetricsProvider::LogRendererHang() { | |
148 IncrementPrefValue(prefs::kStabilityRendererHangCount); | |
149 } | |
150 | |
151 } // namespace metrics | |
152 } // namespace chromecast | |
OLD | NEW |