OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/net/passive_log_collector.h" | 5 #include "chrome/browser/net/passive_log_collector.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
10 #include "chrome/browser/chrome_thread.h" | 10 #include "chrome/browser/chrome_thread.h" |
11 | 11 |
12 namespace { | 12 namespace { |
13 const size_t kMaxNumEntriesPerLog = 50; | 13 const size_t kMaxNumEntriesPerLog = 50; |
14 const size_t kMaxConnectJobGraveyardSize = 3; | 14 const size_t kMaxConnectJobGraveyardSize = 3; |
15 const size_t kMaxRequestGraveyardSize = 25; | 15 const size_t kMaxRequestGraveyardSize = 25; |
16 const size_t kMaxLiveRequests = 200; | 16 const size_t kMaxLiveRequests = 200; |
17 | 17 |
18 // Sort function on source ID. | 18 // Sort function on source ID. |
19 bool OrderBySourceID(const PassiveLogCollector::RequestInfo& a, | 19 bool OrderBySourceID(const PassiveLogCollector::RequestInfo& a, |
20 const PassiveLogCollector::RequestInfo& b) { | 20 const PassiveLogCollector::RequestInfo& b) { |
21 return a.entries[0].source.id < b.entries[0].source.id; | 21 return a.entries[0].source.id < b.entries[0].source.id; |
22 } | 22 } |
23 | 23 |
24 void AddEntryToRequestInfo(const net::CapturingNetLog::Entry& entry, | 24 void AddEntryToRequestInfo(const PassiveLogCollector::Entry& entry, |
25 bool is_unbounded, | 25 bool is_unbounded, |
26 PassiveLogCollector::RequestInfo* out_info) { | 26 PassiveLogCollector::RequestInfo* out_info) { |
27 // Start dropping new entries when the log has gotten too big. | 27 // Start dropping new entries when the log has gotten too big. |
28 if (out_info->entries.size() + 1 <= kMaxNumEntriesPerLog || is_unbounded) { | 28 if (out_info->entries.size() + 1 <= kMaxNumEntriesPerLog || is_unbounded) { |
29 out_info->entries.push_back(entry); | 29 out_info->entries.push_back(entry); |
30 } else { | 30 } else { |
31 out_info->num_entries_truncated += 1; | 31 out_info->num_entries_truncated += 1; |
32 out_info->entries[kMaxNumEntriesPerLog - 1] = entry; | 32 out_info->entries[kMaxNumEntriesPerLog - 1] = entry; |
33 } | 33 } |
34 } | 34 } |
35 | 35 |
36 void AppendToRequestInfo(const PassiveLogCollector::RequestInfo& info, | 36 void AppendToRequestInfo(const PassiveLogCollector::RequestInfo& info, |
37 bool is_unbounded, | 37 bool is_unbounded, |
38 PassiveLogCollector::RequestInfo* out_info) { | 38 PassiveLogCollector::RequestInfo* out_info) { |
39 for (size_t i = 0; i < info.entries.size(); ++i) | 39 for (size_t i = 0; i < info.entries.size(); ++i) |
40 AddEntryToRequestInfo(info.entries[i], is_unbounded, out_info); | 40 AddEntryToRequestInfo(info.entries[i], is_unbounded, out_info); |
41 } | 41 } |
42 | 42 |
| 43 // Appends all of the logged events in |input| to |out|. |
| 44 void AppendAllEntriesFromRequests( |
| 45 const PassiveLogCollector::RequestInfoList& input, |
| 46 PassiveLogCollector::EntryList* out) { |
| 47 for (size_t i = 0; i < input.size(); ++i) { |
| 48 const PassiveLogCollector::EntryList& entries = input[i].entries; |
| 49 out->insert(out->end(), entries.begin(), entries.end()); |
| 50 } |
| 51 } |
| 52 |
| 53 // Comparator to sort entries by their |order| property, ascending. |
| 54 bool SortByOrderComparator(const PassiveLogCollector::Entry& a, |
| 55 const PassiveLogCollector::Entry& b) { |
| 56 return a.order < b.order; |
| 57 } |
| 58 |
43 } // namespace | 59 } // namespace |
44 | 60 |
45 //---------------------------------------------------------------------------- | 61 //---------------------------------------------------------------------------- |
46 // PassiveLogCollector | 62 // PassiveLogCollector |
47 //---------------------------------------------------------------------------- | 63 //---------------------------------------------------------------------------- |
48 | 64 |
49 PassiveLogCollector::PassiveLogCollector() | 65 PassiveLogCollector::PassiveLogCollector() |
50 : url_request_tracker_(&connect_job_tracker_), | 66 : url_request_tracker_(&connect_job_tracker_), |
51 socket_stream_tracker_(&connect_job_tracker_) { | 67 socket_stream_tracker_(&connect_job_tracker_), |
| 68 num_events_seen_(0) { |
52 } | 69 } |
53 | 70 |
54 PassiveLogCollector::~PassiveLogCollector() { | 71 PassiveLogCollector::~PassiveLogCollector() { |
55 } | 72 } |
56 | 73 |
57 void PassiveLogCollector::OnAddEntry( | 74 void PassiveLogCollector::OnAddEntry( |
58 net::NetLog::EventType type, | 75 net::NetLog::EventType type, |
59 const base::TimeTicks& time, | 76 const base::TimeTicks& time, |
60 const net::NetLog::Source& source, | 77 const net::NetLog::Source& source, |
61 net::NetLog::EventPhase phase, | 78 net::NetLog::EventPhase phase, |
62 net::NetLog::EventParameters* extra_parameters) { | 79 net::NetLog::EventParameters* extra_parameters) { |
63 // Package the parameters into a single struct for convenience. | 80 // Package the parameters into a single struct for convenience. |
64 net::CapturingNetLog::Entry entry(type, time, source, phase, | 81 Entry entry(num_events_seen_++, type, time, source, phase, extra_parameters); |
65 extra_parameters); | |
66 | 82 |
67 switch (entry.source.type) { | 83 switch (entry.source.type) { |
68 case net::NetLog::SOURCE_URL_REQUEST: | 84 case net::NetLog::SOURCE_URL_REQUEST: |
69 url_request_tracker_.OnAddEntry(entry); | 85 url_request_tracker_.OnAddEntry(entry); |
70 break; | 86 break; |
71 case net::NetLog::SOURCE_SOCKET_STREAM: | 87 case net::NetLog::SOURCE_SOCKET_STREAM: |
72 socket_stream_tracker_.OnAddEntry(entry); | 88 socket_stream_tracker_.OnAddEntry(entry); |
73 break; | 89 break; |
74 case net::NetLog::SOURCE_CONNECT_JOB: | 90 case net::NetLog::SOURCE_CONNECT_JOB: |
75 connect_job_tracker_.OnAddEntry(entry); | 91 connect_job_tracker_.OnAddEntry(entry); |
76 break; | 92 break; |
77 case net::NetLog::SOURCE_INIT_PROXY_RESOLVER: | 93 case net::NetLog::SOURCE_INIT_PROXY_RESOLVER: |
78 init_proxy_resolver_tracker_.OnAddEntry(entry); | 94 init_proxy_resolver_tracker_.OnAddEntry(entry); |
79 break; | 95 break; |
80 default: | 96 default: |
81 // Drop all other logged events. | 97 // Drop all other logged events. |
82 break; | 98 break; |
83 } | 99 } |
84 } | 100 } |
85 | 101 |
86 void PassiveLogCollector::Clear() { | 102 void PassiveLogCollector::Clear() { |
87 connect_job_tracker_.Clear(); | 103 connect_job_tracker_.Clear(); |
88 url_request_tracker_.Clear(); | 104 url_request_tracker_.Clear(); |
89 socket_stream_tracker_.Clear(); | 105 socket_stream_tracker_.Clear(); |
90 } | 106 } |
91 | 107 |
| 108 void PassiveLogCollector::GetAllCapturedEvents(EntryList* out) const { |
| 109 out->clear(); |
| 110 |
| 111 // Append all of the captured entries held by the various trackers to |
| 112 // |out|. |
| 113 socket_stream_tracker_.AppendAllEntries(out); |
| 114 url_request_tracker_.AppendAllEntries(out); |
| 115 |
| 116 const EntryList& proxy_entries = |
| 117 init_proxy_resolver_tracker_.entries(); |
| 118 out->insert(out->end(), proxy_entries.begin(), proxy_entries.end()); |
| 119 |
| 120 // Now sort the list of entries by their insertion time (ascending). |
| 121 std::sort(out->begin(), out->end(), &SortByOrderComparator); |
| 122 } |
| 123 |
92 //---------------------------------------------------------------------------- | 124 //---------------------------------------------------------------------------- |
93 // RequestTrackerBase | 125 // RequestTrackerBase |
94 //---------------------------------------------------------------------------- | 126 //---------------------------------------------------------------------------- |
95 | 127 |
96 PassiveLogCollector::RequestTrackerBase::RequestTrackerBase( | 128 PassiveLogCollector::RequestTrackerBase::RequestTrackerBase( |
97 size_t max_graveyard_size) | 129 size_t max_graveyard_size) |
98 : max_graveyard_size_(max_graveyard_size), | 130 : max_graveyard_size_(max_graveyard_size), |
99 next_graveyard_index_(0), | 131 next_graveyard_index_(0), |
100 is_unbounded_(false) { | 132 is_unbounded_(false) { |
101 } | 133 } |
102 | 134 |
103 void PassiveLogCollector::RequestTrackerBase::OnAddEntry( | 135 void PassiveLogCollector::RequestTrackerBase::OnAddEntry(const Entry& entry) { |
104 const net::CapturingNetLog::Entry& entry) { | |
105 RequestInfo& info = live_requests_[entry.source.id]; | 136 RequestInfo& info = live_requests_[entry.source.id]; |
106 Action result = DoAddEntry(entry, &info); | 137 Action result = DoAddEntry(entry, &info); |
107 | 138 |
108 switch (result) { | 139 switch (result) { |
109 case ACTION_MOVE_TO_GRAVEYARD: | 140 case ACTION_MOVE_TO_GRAVEYARD: |
110 InsertIntoGraveyard(info); | 141 InsertIntoGraveyard(info); |
111 // (fall-through) | 142 // (fall-through) |
112 case ACTION_DELETE: | 143 case ACTION_DELETE: |
113 RemoveFromLiveRequests(entry.source.id); | 144 RemoveFromLiveRequests(entry.source.id); |
114 break; | 145 break; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 ClearRecentlyDeceased(); | 223 ClearRecentlyDeceased(); |
193 | 224 |
194 is_unbounded_ = unbounded; | 225 is_unbounded_ = unbounded; |
195 } | 226 } |
196 | 227 |
197 void PassiveLogCollector::RequestTrackerBase::Clear() { | 228 void PassiveLogCollector::RequestTrackerBase::Clear() { |
198 ClearRecentlyDeceased(); | 229 ClearRecentlyDeceased(); |
199 live_requests_.clear(); | 230 live_requests_.clear(); |
200 } | 231 } |
201 | 232 |
| 233 void PassiveLogCollector::RequestTrackerBase::AppendAllEntries( |
| 234 EntryList* out) const { |
| 235 AppendAllEntriesFromRequests(GetLiveRequests(), out); |
| 236 AppendAllEntriesFromRequests(GetRecentlyDeceased(), out); |
| 237 } |
| 238 |
202 void PassiveLogCollector::RequestTrackerBase::InsertIntoGraveyard( | 239 void PassiveLogCollector::RequestTrackerBase::InsertIntoGraveyard( |
203 const RequestInfo& info) { | 240 const RequestInfo& info) { |
204 if (is_unbounded_) { | 241 if (is_unbounded_) { |
205 graveyard_.push_back(info); | 242 graveyard_.push_back(info); |
206 return; | 243 return; |
207 } | 244 } |
208 | 245 |
209 // Otherwise enforce a bound on the graveyard size, by treating it as a | 246 // Otherwise enforce a bound on the graveyard size, by treating it as a |
210 // circular buffer. | 247 // circular buffer. |
211 if (graveyard_.size() < max_graveyard_size_) { | 248 if (graveyard_.size() < max_graveyard_size_) { |
(...skipping 11 matching lines...) Expand all Loading... |
223 // ConnectJobTracker | 260 // ConnectJobTracker |
224 //---------------------------------------------------------------------------- | 261 //---------------------------------------------------------------------------- |
225 | 262 |
226 const size_t PassiveLogCollector::ConnectJobTracker::kMaxGraveyardSize = 3; | 263 const size_t PassiveLogCollector::ConnectJobTracker::kMaxGraveyardSize = 3; |
227 | 264 |
228 PassiveLogCollector::ConnectJobTracker::ConnectJobTracker() | 265 PassiveLogCollector::ConnectJobTracker::ConnectJobTracker() |
229 : RequestTrackerBase(kMaxGraveyardSize) { | 266 : RequestTrackerBase(kMaxGraveyardSize) { |
230 } | 267 } |
231 | 268 |
232 PassiveLogCollector::RequestTrackerBase::Action | 269 PassiveLogCollector::RequestTrackerBase::Action |
233 PassiveLogCollector::ConnectJobTracker::DoAddEntry( | 270 PassiveLogCollector::ConnectJobTracker::DoAddEntry(const Entry& entry, |
234 const net::CapturingNetLog::Entry& entry, | 271 RequestInfo* out_info) { |
235 RequestInfo* out_info) { | |
236 // Save the entry (possibly truncating). | 272 // Save the entry (possibly truncating). |
237 AddEntryToRequestInfo(entry, is_unbounded(), out_info); | 273 AddEntryToRequestInfo(entry, is_unbounded(), out_info); |
238 | 274 |
239 // If this is the end of the connect job, move the request to the graveyard. | 275 // If this is the end of the connect job, move the request to the graveyard. |
240 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB && | 276 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB && |
241 entry.phase == net::NetLog::PHASE_END) { | 277 entry.phase == net::NetLog::PHASE_END) { |
242 return ACTION_MOVE_TO_GRAVEYARD; | 278 return ACTION_MOVE_TO_GRAVEYARD; |
243 } | 279 } |
244 | 280 |
245 return ACTION_NONE; | 281 return ACTION_NONE; |
246 } | 282 } |
247 | 283 |
248 //---------------------------------------------------------------------------- | 284 //---------------------------------------------------------------------------- |
249 // RequestTracker | 285 // RequestTracker |
250 //---------------------------------------------------------------------------- | 286 //---------------------------------------------------------------------------- |
251 | 287 |
252 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardSize = 25; | 288 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardSize = 25; |
253 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardURLSize = 1000; | 289 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardURLSize = 1000; |
254 | 290 |
255 PassiveLogCollector::RequestTracker::RequestTracker( | 291 PassiveLogCollector::RequestTracker::RequestTracker( |
256 ConnectJobTracker* connect_job_tracker) | 292 ConnectJobTracker* connect_job_tracker) |
257 : RequestTrackerBase(kMaxGraveyardSize), | 293 : RequestTrackerBase(kMaxGraveyardSize), |
258 connect_job_tracker_(connect_job_tracker) { | 294 connect_job_tracker_(connect_job_tracker) { |
259 } | 295 } |
260 | 296 |
261 PassiveLogCollector::RequestTrackerBase::Action | 297 PassiveLogCollector::RequestTrackerBase::Action |
262 PassiveLogCollector::RequestTracker::DoAddEntry( | 298 PassiveLogCollector::RequestTracker::DoAddEntry(const Entry& entry, |
263 const net::CapturingNetLog::Entry& entry, | 299 RequestInfo* out_info) { |
264 RequestInfo* out_info) { | |
265 | 300 |
266 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID) { | 301 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID) { |
267 // If this was notification that a ConnectJob was bound to the request, | 302 // If this was notification that a ConnectJob was bound to the request, |
268 // copy all the logged data for that ConnectJob. | 303 // copy all the logged data for that ConnectJob. |
269 AddConnectJobInfo(entry, out_info); | 304 AddConnectJobInfo(entry, out_info); |
270 } else { | 305 } else { |
271 // Otherwise just append this entry to the request info. | 306 // Otherwise just append this entry to the request info. |
272 AddEntryToRequestInfo(entry, is_unbounded(), out_info); | 307 AddEntryToRequestInfo(entry, is_unbounded(), out_info); |
273 } | 308 } |
274 | 309 |
(...skipping 16 matching lines...) Expand all Loading... |
291 // adds to clutter. | 326 // adds to clutter. |
292 return ACTION_DELETE; | 327 return ACTION_DELETE; |
293 } | 328 } |
294 return ACTION_MOVE_TO_GRAVEYARD; | 329 return ACTION_MOVE_TO_GRAVEYARD; |
295 } | 330 } |
296 | 331 |
297 return ACTION_NONE; | 332 return ACTION_NONE; |
298 } | 333 } |
299 | 334 |
300 void PassiveLogCollector::RequestTracker::AddConnectJobInfo( | 335 void PassiveLogCollector::RequestTracker::AddConnectJobInfo( |
301 const net::CapturingNetLog::Entry& entry, | 336 const Entry& entry, |
302 RequestInfo* live_entry) { | 337 RequestInfo* live_entry) { |
303 // We have just been notified of which ConnectJob the | 338 // We have just been notified of which ConnectJob the |
304 // URLRequest/SocketStream was assigned. Lookup all the data we captured | 339 // URLRequest/SocketStream was assigned. Lookup all the data we captured |
305 // for the ConnectJob, and append it to the URLRequest/SocketStream's | 340 // for the ConnectJob, and append it to the URLRequest/SocketStream's |
306 // RequestInfo. | 341 // RequestInfo. |
307 | 342 |
308 int connect_job_id = static_cast<net::NetLogIntegerParameter*>( | 343 int connect_job_id = static_cast<net::NetLogIntegerParameter*>( |
309 entry.extra_parameters.get())->value(); | 344 entry.extra_parameters.get())->value(); |
310 | 345 |
311 const RequestInfo* connect_job_info = | 346 const RequestInfo* connect_job_info = |
312 connect_job_tracker_->GetRequestInfoFromGraveyard(connect_job_id); | 347 connect_job_tracker_->GetRequestInfoFromGraveyard(connect_job_id); |
313 | 348 |
314 if (connect_job_info) { | 349 if (connect_job_info) { |
315 // Append the ConnectJob information we found. | 350 // Append the ConnectJob information we found. |
316 AppendToRequestInfo(*connect_job_info, is_unbounded(), live_entry); | 351 AppendToRequestInfo(*connect_job_info, is_unbounded(), live_entry); |
317 } else { | 352 } else { |
318 // If we couldn't find the information for the ConnectJob, append a | 353 // If we couldn't find the information for the ConnectJob, append a |
319 // generic message instead. | 354 // generic message instead. |
320 net::CapturingNetLog::Entry e(entry); | 355 Entry e(entry); |
321 e.type = net::NetLog::TYPE_TODO_STRING; | 356 e.type = net::NetLog::TYPE_TODO_STRING; |
322 e.extra_parameters = new net::NetLogStringParameter( | 357 e.extra_parameters = new net::NetLogStringParameter( |
323 StringPrintf("Used ConnectJob id=%d", connect_job_id)); | 358 StringPrintf("Used ConnectJob id=%d", connect_job_id)); |
324 AddEntryToRequestInfo(e, is_unbounded(), live_entry); | 359 AddEntryToRequestInfo(e, is_unbounded(), live_entry); |
325 } | 360 } |
326 } | 361 } |
327 | 362 |
328 //---------------------------------------------------------------------------- | 363 //---------------------------------------------------------------------------- |
329 // InitProxyResolverTracker | 364 // InitProxyResolverTracker |
330 //---------------------------------------------------------------------------- | 365 //---------------------------------------------------------------------------- |
331 | 366 |
332 PassiveLogCollector::InitProxyResolverTracker::InitProxyResolverTracker() {} | 367 PassiveLogCollector::InitProxyResolverTracker::InitProxyResolverTracker() {} |
333 | 368 |
334 void PassiveLogCollector::InitProxyResolverTracker::OnAddEntry( | 369 void PassiveLogCollector::InitProxyResolverTracker::OnAddEntry( |
335 const net::CapturingNetLog::Entry& entry) { | 370 const Entry& entry) { |
336 if (entry.type == net::NetLog::TYPE_INIT_PROXY_RESOLVER && | 371 if (entry.type == net::NetLog::TYPE_INIT_PROXY_RESOLVER && |
337 entry.phase == net::NetLog::PHASE_BEGIN) { | 372 entry.phase == net::NetLog::PHASE_BEGIN) { |
338 // If this is the start of a new InitProxyResolver, overwrite the old data. | 373 // If this is the start of a new InitProxyResolver, overwrite the old data. |
339 entries_.clear(); | 374 entries_.clear(); |
340 entries_.push_back(entry); | 375 entries_.push_back(entry); |
341 } else { | 376 } else { |
342 // Otherwise append it to the log for the latest InitProxyResolver. | 377 // Otherwise append it to the log for the latest InitProxyResolver. |
343 if (!entries_.empty() && entries_[0].source.id != entry.source.id) { | 378 if (!entries_.empty() && entries_[0].source.id != entry.source.id) { |
344 // If this entry doesn't match what we think was the latest | 379 // If this entry doesn't match what we think was the latest |
345 // InitProxyResolver, drop it. (This shouldn't happen, but we will guard | 380 // InitProxyResolver, drop it. (This shouldn't happen, but we will guard |
346 // against it). | 381 // against it). |
347 return; | 382 return; |
348 } | 383 } |
349 entries_.push_back(entry); | 384 entries_.push_back(entry); |
350 } | 385 } |
351 | 386 |
352 // Safety net: INIT_PROXY_RESOLVER shouldn't generate many messages, but in | 387 // Safety net: INIT_PROXY_RESOLVER shouldn't generate many messages, but in |
353 // case something goes wrong, avoid exploding the memory usage. | 388 // case something goes wrong, avoid exploding the memory usage. |
354 if (entries_.size() > kMaxNumEntriesPerLog) | 389 if (entries_.size() > kMaxNumEntriesPerLog) |
355 entries_.clear(); | 390 entries_.clear(); |
356 } | 391 } |
357 | 392 |
OLD | NEW |