Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Side by Side Diff: chrome/browser/metrics/tracking_synchronizer.cc

Issue 8413009: Changes to upload tracked_objects data from all renderer (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:executable
+ *
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "chrome/browser/metrics/tracking_synchronizer.h"
6
7 #include "base/bind.h"
8 #include "base/json/json_reader.h"
9 #include "base/json/json_writer.h"
10 #include "base/logging.h"
11 #include "base/metrics/histogram.h"
12 #include "base/threading/thread.h"
13 #include "base/tracked_objects.h"
14 #include "chrome/browser/ui/webui/tracing_ui.h"
15 #include "chrome/common/chrome_constants.h"
16 #include "chrome/common/render_messages.h"
17 #include "content/browser/renderer_host/render_process_host.h"
18 #include "content/public/browser/browser_thread.h"
19
20 using base::TimeTicks;
21 using content::BrowserThread;
22
23 namespace chrome_browser_metrics {
24
25 // Negative numbers are never used as sequence numbers. We explicitly pick a
26 // negative number that is "so negative" that even when we add one (as is done
27 // when we generated the next sequence number) that it will still be negative.
28 // We have code that handles wrapping around on an overflow into negative
29 // territory.
30 static const int kNeverUsableSequenceNumber = -2;
31
32 TrackingSynchronizer::TrackingSynchronizer()
33 : last_used_sequence_number_(kNeverUsableSequenceNumber) {
34 DCHECK(tracking_synchronizer_ == NULL);
35 tracking_synchronizer_ = this;
36 }
37
38 TrackingSynchronizer::~TrackingSynchronizer() {
39 // Just in case we have any pending tasks, clear them out.
40 while (!outstanding_requests_.empty()) {
41 RequestContextMap::iterator it = outstanding_requests_.begin();
42 delete it->second;
43 outstanding_requests_.erase(it);
44 }
45
46 tracking_synchronizer_ = NULL;
47 }
48
49 // static
50 TrackingSynchronizer* TrackingSynchronizer::CurrentSynchronizer() {
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
52 DCHECK(tracking_synchronizer_ != NULL);
53 return tracking_synchronizer_;
54 }
55
56 // static
57 void TrackingSynchronizer::FetchTrackingDataAsynchronously(
58 const base::WeakPtr<TrackingUI>& callback_object) {
59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
60
61 TrackingSynchronizer* current_synchronizer = CurrentSynchronizer();
62 if (current_synchronizer == NULL) {
63 // System teardown is happening.
64 return;
65 }
66
67 int sequence_number = current_synchronizer->RegisterAndNotifyAllProcesses(
68 callback_object);
69
70 // Post a task that would be called after waiting for wait_time. This acts
71 // as a watchdog, to cancel the requests for non-responsive processes.
72 BrowserThread::PostDelayedTask(
73 BrowserThread::UI, FROM_HERE,
74 NewRunnableMethod(
75 current_synchronizer,
76 &TrackingSynchronizer::ForceTrackingSynchronizationDoneCallback,
77 sequence_number),
78 60000);
79 }
80
81 // static
82 void TrackingSynchronizer::SetTrackingStatus(bool enable) {
83 // To iterate over all processes, or to send messages to the hosts, we need
84 // to be on the UI thread.
85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
86
87 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
88 !it.IsAtEnd(); it.Advance()) {
89 RenderProcessHost* render_process_host = it.GetCurrentValue();
90 DCHECK(render_process_host);
91 // Ignore processes that don't have a connection, such as crashed tabs.
92 if (!render_process_host->HasConnection())
93 continue;
94
95 render_process_host->Send(new ChromeViewMsg_SetTrackingStatus(enable));
96 }
97 }
98
99 // static
100 void TrackingSynchronizer::IsTrackingEnabled(int process_id) {
101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
102 // To find the process, or to send messages to the hosts, we need to be on the
103 // UI thread.
104 BrowserThread::PostTask(
105 BrowserThread::UI, FROM_HERE,
106 base::Bind(
107 &TrackingSynchronizer::SetTrackingStatusInProcess, process_id));
108 }
109
110 // static
111 void TrackingSynchronizer::SetTrackingStatusInProcess(int process_id) {
112 // To find the process, or to send messages to the hosts, we need to be on the
113 // UI thread.
114 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
115
116 bool enable = tracked_objects::ThreadData::tracking_status();
117
118 RenderProcessHost* process = RenderProcessHost::FromID(process_id);
119 // Ignore processes that don't have a connection, such as crashed tabs.
120 if (!process || !process->HasConnection())
121 return;
122 process->Send(new ChromeViewMsg_SetTrackingStatus(enable));
123 }
124
125 // static
126 void TrackingSynchronizer::DeserializeTrackingList(
127 int sequence_number,
128 const std::string& tracking_data,
129 ChildProcessInfo::ProcessType process_type) {
130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
131 BrowserThread::PostTask(
132 BrowserThread::UI, FROM_HERE,
133 base::Bind(
134 &TrackingSynchronizer::DeserializeTrackingListOnUI,
135 sequence_number, tracking_data, process_type));
136 }
137
138 // static
139 void TrackingSynchronizer::DeserializeTrackingListOnUI(
140 int sequence_number,
141 const std::string& tracking_data,
142 ChildProcessInfo::ProcessType process_type) {
143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
144
145 TrackingSynchronizer* current_synchronizer = CurrentSynchronizer();
146 if (current_synchronizer == NULL)
147 return;
148
149 base::Value* value =
150 base::JSONReader().JsonToValue(tracking_data, false, true);
151 DCHECK(value->GetType() == base::Value::TYPE_DICTIONARY);
152 base::DictionaryValue* dictionary_value =
153 static_cast<DictionaryValue*>(value);
154 dictionary_value->SetString(
155 "process_type", ChildProcessInfo::GetTypeNameInEnglish(process_type));
156
157 current_synchronizer->DecrementPendingProcessesAndSendData(
158 sequence_number, dictionary_value);
159 }
160
161 int TrackingSynchronizer::RegisterAndNotifyAllProcesses(
162 const base::WeakPtr<TrackingUI>& callback_object) {
163 // To iterate over all processes, or to send messages to the hosts, we need
164 // to be on the UI thread.
165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
166
167 int sequence_number = GetNextAvailableSequenceNumber();
168
169 // Initialize processes_pending with one because we are going to send
170 // browser's ThreadData.
171 RequestContext* request = new RequestContext(
172 callback_object, sequence_number, 1, TimeTicks::Now());
173 outstanding_requests_[sequence_number] = request;
174
175 DCHECK_GT(request->processes_pending_, 0);
176 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
177 !it.IsAtEnd(); it.Advance()) {
178 RenderProcessHost* render_process_host = it.GetCurrentValue();
179 DCHECK(render_process_host);
180 // Ignore processes that don't have a connection, such as crashed tabs.
181 if (!render_process_host->HasConnection())
182 continue;
183
184 ++request->processes_pending_;
185 if (!render_process_host->Send(
186 new ChromeViewMsg_GetRendererTrackedData(sequence_number))) {
187 DecrementPendingProcesses(sequence_number);
188 }
189 }
190
191 // Get the ThreadData for the browser process and send it back.
192 base::DictionaryValue* value = tracked_objects::ThreadData::ToValue();
193 const std::string process_type =
194 ChildProcessInfo::GetTypeNameInEnglish(ChildProcessInfo::BROWSER_PROCESS);
195 value->SetString("process_type", process_type);
196 value->SetInteger("process_id", base::GetCurrentProcId());
197 DCHECK_GT(request->processes_pending_, 0);
198 DecrementPendingProcessesAndSendData(sequence_number, value);
199
200 return sequence_number;
201 }
202
203 void TrackingSynchronizer::DecrementPendingProcessesAndSendData(
204 int sequence_number,
205 base::DictionaryValue* value) {
206 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
207
208 RequestContextMap::iterator it =
209 outstanding_requests_.find(sequence_number);
210 if (it == outstanding_requests_.end()) {
211 delete value;
212 return;
213 }
214
215 RequestContext* request = NULL;
216 bool completed = false;
217 request = it->second;
218
219 DCHECK(sequence_number == request->sequence_number_);
220 if (--request->processes_pending_ <= 0)
jar (doing other things) 2011/11/04 21:38:21 nit: I'd prefer if this happened after you did the
ramant (doing other things) 2011/11/04 22:01:38 Done.
221 completed = true;
222
223 if (value && request->callback_object_) {
224 // Transfers ownership of |value| to |callback_object_|.
225 request->callback_object_->ReceivedData(value);
226 } else {
227 delete value;
228 }
229
230 if (completed)
231 ForceTrackingSynchronizationDoneCallback(sequence_number);
232 }
233
234 void TrackingSynchronizer::DecrementPendingProcesses(int sequence_number) {
235 DecrementPendingProcessesAndSendData(sequence_number, NULL);
236 }
237
238 void TrackingSynchronizer::ForceTrackingSynchronizationDoneCallback(
239 int sequence_number) {
240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
241
242 int unresponsive_processes;
243 RequestContextMap::iterator it =
244 outstanding_requests_.find(sequence_number);
245 if (it == outstanding_requests_.end())
246 return;
247
248 RequestContext* request = it->second;
249
250 DCHECK(sequence_number == request->sequence_number_);
251
252 unresponsive_processes = request->processes_pending_;
253
254 delete it->second;
255 outstanding_requests_.erase(it);
256
257 UMA_HISTOGRAM_COUNTS("Tracking.ProcessNotRespondingAsynchronous",
258 unresponsive_processes);
259 }
260
261 int TrackingSynchronizer::GetNextAvailableSequenceNumber() {
262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
263
264 ++last_used_sequence_number_;
265
266 // Watch out for wrapping to a negative number.
267 if (last_used_sequence_number_ < 0)
268 last_used_sequence_number_ = 1;
269 return last_used_sequence_number_;
270 }
271
272 // static
273 TrackingSynchronizer* TrackingSynchronizer::tracking_synchronizer_ = NULL;
274
275 } // namespace chrome_browser_metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698