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

Side by Side Diff: chrome/browser/net/passive_log_collector.cc

Issue 2363003: Rework the logging for sockets/connectjobs.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 6 months 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
OLDNEW
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/compiler_specific.h"
9 #include "base/string_util.h" 10 #include "base/string_util.h"
10 #include "base/format_macros.h" 11 #include "base/format_macros.h"
11 #include "chrome/browser/chrome_thread.h" 12 #include "chrome/browser/chrome_thread.h"
12 #include "net/url_request/url_request_netlog_params.h" 13 #include "net/url_request/url_request_netlog_params.h"
13 14
14 namespace { 15 namespace {
15 16
16 const size_t kMaxNumEntriesPerLog = 50; 17 // TODO(eroman): Do something with the truncation count.
17 const size_t kMaxConnectJobGraveyardSize = 3;
18 const size_t kMaxRequestGraveyardSize = 25;
19 const size_t kMaxLiveRequests = 200;
20 18
21 // Sort function on source ID. 19 const size_t kMaxNumEntriesPerLog = 30;
22 bool OrderBySourceID(const PassiveLogCollector::RequestInfo& a, 20 const size_t kMaxRequestsPerTracker = 200;
23 const PassiveLogCollector::RequestInfo& b) {
24 return a.source_id < b.source_id;
25 }
26 21
27 void AddEntryToRequestInfo(const PassiveLogCollector::Entry& entry, 22 void AddEntryToRequestInfo(const PassiveLogCollector::Entry& entry,
28 PassiveLogCollector::RequestInfo* out_info) { 23 PassiveLogCollector::RequestInfo* out_info) {
29 // Start dropping new entries when the log has gotten too big. 24 // Start dropping new entries when the log has gotten too big.
30 if (out_info->entries.size() + 1 <= kMaxNumEntriesPerLog) { 25 if (out_info->entries.size() + 1 <= kMaxNumEntriesPerLog) {
31 out_info->entries.push_back(entry); 26 out_info->entries.push_back(entry);
32 } else { 27 } else {
33 out_info->num_entries_truncated += 1; 28 out_info->num_entries_truncated += 1;
34 out_info->entries[kMaxNumEntriesPerLog - 1] = entry; 29 out_info->entries[kMaxNumEntriesPerLog - 1] = entry;
35 } 30 }
36 } 31 }
37 32
38 void AppendToRequestInfo(const PassiveLogCollector::RequestInfo& info,
39 PassiveLogCollector::RequestInfo* out_info) {
40 for (size_t i = 0; i < info.entries.size(); ++i)
41 AddEntryToRequestInfo(info.entries[i], out_info);
42 }
43
44 // Appends all of the logged events in |input| to |out|.
45 void AppendAllEntriesFromRequests(
46 const PassiveLogCollector::RequestInfoList& input,
47 PassiveLogCollector::EntryList* out) {
48 for (size_t i = 0; i < input.size(); ++i) {
49 const PassiveLogCollector::EntryList& entries = input[i].entries;
50 out->insert(out->end(), entries.begin(), entries.end());
51 }
52 }
53
54 // Comparator to sort entries by their |order| property, ascending. 33 // Comparator to sort entries by their |order| property, ascending.
55 bool SortByOrderComparator(const PassiveLogCollector::Entry& a, 34 bool SortByOrderComparator(const PassiveLogCollector::Entry& a,
56 const PassiveLogCollector::Entry& b) { 35 const PassiveLogCollector::Entry& b) {
57 return a.order < b.order; 36 return a.order < b.order;
58 } 37 }
59 38
60 void SetSubordinateSource(PassiveLogCollector::RequestInfo* info,
61 const PassiveLogCollector::Entry& entry) {
62 info->subordinate_source.id = static_cast<net::NetLogIntegerParameter*>(
63 entry.params.get())->value();
64 switch (entry.type) {
65 case net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID:
66 info->subordinate_source.type = net::NetLog::SOURCE_CONNECT_JOB;
67 break;
68 case net::NetLog::TYPE_SOCKET_POOL_SOCKET_ID:
69 info->subordinate_source.type = net::NetLog::SOURCE_SOCKET;
70 break;
71 default:
72 NOTREACHED();
73 break;
74 }
75 }
76
77 } // namespace 39 } // namespace
78 40
79 //---------------------------------------------------------------------------- 41 //----------------------------------------------------------------------------
80 // PassiveLogCollector 42 // PassiveLogCollector
81 //---------------------------------------------------------------------------- 43 //----------------------------------------------------------------------------
82 44
83 PassiveLogCollector::PassiveLogCollector() 45 PassiveLogCollector::PassiveLogCollector()
84 : url_request_tracker_(&connect_job_tracker_, &socket_tracker_), 46 : ALLOW_THIS_IN_INITIALIZER_LIST(connect_job_tracker_(this)),
85 socket_stream_tracker_(&connect_job_tracker_, &socket_tracker_), 47 ALLOW_THIS_IN_INITIALIZER_LIST(url_request_tracker_(this)),
48 ALLOW_THIS_IN_INITIALIZER_LIST(socket_stream_tracker_(this)),
86 num_events_seen_(0) { 49 num_events_seen_(0) {
50
51 // Define the mapping between source types and the tracker objects.
52 memset(&trackers_[0], 0, sizeof(trackers_));
53 trackers_[net::NetLog::SOURCE_URL_REQUEST] = &url_request_tracker_;
54 trackers_[net::NetLog::SOURCE_SOCKET_STREAM] = &socket_stream_tracker_;
55 trackers_[net::NetLog::SOURCE_CONNECT_JOB] = &connect_job_tracker_;
56 trackers_[net::NetLog::SOURCE_SOCKET] = &socket_tracker_;
57 trackers_[net::NetLog::SOURCE_INIT_PROXY_RESOLVER] =
58 &init_proxy_resolver_tracker_;
59 trackers_[net::NetLog::SOURCE_SPDY_SESSION] = &spdy_session_tracker_;
60
61 // Make sure our mapping is up-to-date.
62 for (size_t i = 0; i < arraysize(trackers_); ++i)
63 DCHECK(trackers_[i]) << "Unhandled SourceType: " << i;
87 } 64 }
88 65
89 PassiveLogCollector::~PassiveLogCollector() { 66 PassiveLogCollector::~PassiveLogCollector() {
90 } 67 }
91 68
92 void PassiveLogCollector::OnAddEntry( 69 void PassiveLogCollector::OnAddEntry(
93 net::NetLog::EventType type, 70 net::NetLog::EventType type,
94 const base::TimeTicks& time, 71 const base::TimeTicks& time,
95 const net::NetLog::Source& source, 72 const net::NetLog::Source& source,
96 net::NetLog::EventPhase phase, 73 net::NetLog::EventPhase phase,
97 net::NetLog::EventParameters* params) { 74 net::NetLog::EventParameters* params) {
98 // Package the parameters into a single struct for convenience. 75 // Package the parameters into a single struct for convenience.
99 Entry entry(num_events_seen_++, type, time, source, phase, params); 76 Entry entry(num_events_seen_++, type, time, source, phase, params);
100 77
101 switch (entry.source.type) { 78 RequestTrackerBase* tracker = GetTrackerForSourceType(entry.source.type);
102 case net::NetLog::SOURCE_URL_REQUEST: 79 if (tracker)
103 url_request_tracker_.OnAddEntry(entry); 80 tracker->OnAddEntry(entry);
104 break; 81 }
105 case net::NetLog::SOURCE_SOCKET_STREAM: 82
106 socket_stream_tracker_.OnAddEntry(entry); 83 PassiveLogCollector::RequestTrackerBase*
107 break; 84 PassiveLogCollector::GetTrackerForSourceType(
108 case net::NetLog::SOURCE_CONNECT_JOB: 85 net::NetLog::SourceType source_type) {
109 connect_job_tracker_.OnAddEntry(entry); 86 DCHECK_LE(source_type, static_cast<int>(arraysize(trackers_)));
110 break; 87 DCHECK_GE(source_type, 0);
111 case net::NetLog::SOURCE_SOCKET: 88 return trackers_[source_type];
112 socket_tracker_.OnAddEntry(entry);
113 break;
114 case net::NetLog::SOURCE_INIT_PROXY_RESOLVER:
115 init_proxy_resolver_tracker_.OnAddEntry(entry);
116 break;
117 default:
118 // Drop all other logged events.
119 break;
120 }
121 } 89 }
122 90
123 void PassiveLogCollector::Clear() { 91 void PassiveLogCollector::Clear() {
124 connect_job_tracker_.Clear(); 92 for (size_t i = 0; i < arraysize(trackers_); ++i)
125 url_request_tracker_.Clear(); 93 trackers_[i]->Clear();
126 socket_stream_tracker_.Clear();
127 } 94 }
128 95
129 void PassiveLogCollector::GetAllCapturedEvents(EntryList* out) const { 96 void PassiveLogCollector::GetAllCapturedEvents(EntryList* out) const {
130 out->clear(); 97 out->clear();
131 98
132 // Append all of the captured entries held by the various trackers to 99 // Append all of the captured entries held by the various trackers to
133 // |out|. 100 // |out|.
134 socket_stream_tracker_.AppendAllEntries(out); 101 for (size_t i = 0; i < arraysize(trackers_); ++i)
135 url_request_tracker_.AppendAllEntries(out); 102 trackers_[i]->AppendAllEntries(out);
136 spdy_session_tracker_.AppendAllEntries(out);
137
138 const EntryList& proxy_entries =
139 init_proxy_resolver_tracker_.entries();
140 out->insert(out->end(), proxy_entries.begin(), proxy_entries.end());
141 103
142 // Now sort the list of entries by their insertion time (ascending). 104 // Now sort the list of entries by their insertion time (ascending).
143 std::sort(out->begin(), out->end(), &SortByOrderComparator); 105 std::sort(out->begin(), out->end(), &SortByOrderComparator);
144 } 106 }
145 107
146 std::string PassiveLogCollector::RequestInfo::GetURL() const { 108 std::string PassiveLogCollector::RequestInfo::GetURL() const {
147 // Note: we look at the first *two* entries, since the outer REQUEST_ALIVE 109 // Note: we look at the first *two* entries, since the outer REQUEST_ALIVE
148 // doesn't actually contain any data. 110 // doesn't actually contain any data.
149 for (size_t i = 0; i < 2 && i < entries.size(); ++i) { 111 for (size_t i = 0; i < 2 && i < entries.size(); ++i) {
150 const PassiveLogCollector::Entry& entry = entries[i]; 112 const PassiveLogCollector::Entry& entry = entries[i];
(...skipping 11 matching lines...) Expand all
162 } 124 }
163 } 125 }
164 return std::string(); 126 return std::string();
165 } 127 }
166 128
167 //---------------------------------------------------------------------------- 129 //----------------------------------------------------------------------------
168 // RequestTrackerBase 130 // RequestTrackerBase
169 //---------------------------------------------------------------------------- 131 //----------------------------------------------------------------------------
170 132
171 PassiveLogCollector::RequestTrackerBase::RequestTrackerBase( 133 PassiveLogCollector::RequestTrackerBase::RequestTrackerBase(
172 size_t max_graveyard_size) 134 size_t max_graveyard_size, PassiveLogCollector* parent)
173 : max_graveyard_size_(max_graveyard_size), 135 : max_graveyard_size_(max_graveyard_size), parent_(parent) {
174 next_graveyard_index_(0) {
175 } 136 }
176 137
138 PassiveLogCollector::RequestTrackerBase::~RequestTrackerBase() {}
139
177 void PassiveLogCollector::RequestTrackerBase::OnAddEntry(const Entry& entry) { 140 void PassiveLogCollector::RequestTrackerBase::OnAddEntry(const Entry& entry) {
178 RequestInfo& info = live_requests_[entry.source.id]; 141 RequestInfo& info = requests_[entry.source.id];
179 info.source_id = entry.source.id; // In case this is a new entry. 142 info.source_id = entry.source.id; // In case this is a new entry.
180 Action result = DoAddEntry(entry, &info); 143 Action result = DoAddEntry(entry, &info);
181 144
182 switch (result) { 145 if (result != ACTION_NONE) {
183 case ACTION_MOVE_TO_GRAVEYARD: 146 // We are either queuing it for deletion, or deleting it immediately.
184 InsertIntoGraveyard(info); 147 // If someone else holds a reference to this source, defer the deletion
185 // (fall-through) 148 // until all the references are released.
186 case ACTION_DELETE: 149 info.is_alive = false;
187 RemoveFromLiveRequests(entry.source.id); 150 if (info.reference_count == 0) {
188 break; 151 switch (result) {
189 default: 152 case ACTION_MOVE_TO_GRAVEYARD:
190 break; 153 AddToDeletionQueue(info.source_id);
154 break;
155 case ACTION_DELETE:
156 DeleteRequestInfo(info.source_id);
157 break;
158 default:
159 NOTREACHED();
160 break;
161 }
162 }
191 } 163 }
192 164
193 if (live_requests_.size() > kMaxLiveRequests) { 165 if (requests_.size() > kMaxRequestsPerTracker) {
194 // This is a safety net in case something went wrong, to avoid continually 166 // This is a safety net in case something went wrong, to avoid continually
195 // growing memory. 167 // growing memory.
196 LOG(WARNING) << "The passive log data has grown larger " 168 LOG(WARNING) << "The passive log data has grown larger "
197 "than expected, resetting"; 169 "than expected, resetting";
198 live_requests_.clear(); 170 Clear();
199 } 171 }
200 } 172 }
201 173
202 PassiveLogCollector::RequestInfoList 174 void PassiveLogCollector::RequestTrackerBase::DeleteRequestInfo(
203 PassiveLogCollector::RequestTrackerBase::GetLiveRequests() const {
204 RequestInfoList list;
205
206 // Copy all of the live requests into the vector.
207 for (SourceIDToInfoMap::const_iterator it = live_requests_.begin();
208 it != live_requests_.end();
209 ++it) {
210 list.push_back(it->second);
211 // We pass the copy (made by the list insert), so changes made in
212 // OnLiveRequest are only seen by our caller.
213 OnLiveRequest(&list.back());
214 std::sort(list.back().entries.begin(), list.back().entries.end(),
215 SortByOrderComparator);
216 }
217
218 std::sort(list.begin(), list.end(), OrderBySourceID);
219 return list;
220 }
221
222 void PassiveLogCollector::RequestTrackerBase::ClearRecentlyDeceased() {
223 next_graveyard_index_ = 0;
224 graveyard_.clear();
225 }
226
227 // Returns a list of recently completed Requests.
228 PassiveLogCollector::RequestInfoList
229 PassiveLogCollector::RequestTrackerBase::GetRecentlyDeceased() const {
230 RequestInfoList list;
231
232 // Copy the items from |graveyard_| (our circular queue of recently
233 // deceased request infos) into a vector, ordered from oldest to newest.
234 for (size_t i = 0; i < graveyard_.size(); ++i) {
235 size_t index = (next_graveyard_index_ + i) % graveyard_.size();
236 list.push_back(graveyard_[index]);
237 }
238 return list;
239 }
240
241 PassiveLogCollector::RequestInfo*
242 PassiveLogCollector::RequestTrackerBase::GetRequestInfo(uint32 source_id) {
243 // Look for it in the live requests first.
244 SourceIDToInfoMap::iterator it = live_requests_.find(source_id);
245 if (it != live_requests_.end())
246 return &(it->second);
247
248 // Otherwise, scan through the graveyard to find an entry for |source_id|.
249 for (size_t i = 0; i < graveyard_.size(); ++i) {
250 if (graveyard_[i].source_id == source_id) {
251 return &graveyard_[i];
252 }
253 }
254 return NULL;
255 }
256
257 void PassiveLogCollector::RequestTrackerBase::RemoveFromLiveRequests(
258 uint32 source_id) { 175 uint32 source_id) {
259 // Remove from |live_requests_|. 176 SourceIDToInfoMap::iterator it = requests_.find(source_id);
260 SourceIDToInfoMap::iterator it = live_requests_.find(source_id); 177 DCHECK(it != requests_.end());
261 // TODO(eroman): Shouldn't have this 'if', is it actually really necessary? 178 // The request should not be in the deletion queue.
262 if (it != live_requests_.end()) 179 DCHECK(std::find(deletion_queue_.begin(), deletion_queue_.end(),
263 live_requests_.erase(it); 180 source_id) == deletion_queue_.end());
181 ReleaseAllReferencesToDependencies(&(it->second));
182 requests_.erase(it);
264 } 183 }
265 184
266 void PassiveLogCollector::RequestTrackerBase::Clear() { 185 void PassiveLogCollector::RequestTrackerBase::Clear() {
267 ClearRecentlyDeceased(); 186 deletion_queue_.clear();
268 live_requests_.clear(); 187
188 // Release all references held to dependent sources.
189 for (SourceIDToInfoMap::iterator it = requests_.begin();
190 it != requests_.end();
191 ++it) {
192 ReleaseAllReferencesToDependencies(&(it->second));
193 }
194 requests_.clear();
269 } 195 }
270 196
271 void PassiveLogCollector::RequestTrackerBase::AppendAllEntries( 197 void PassiveLogCollector::RequestTrackerBase::AppendAllEntries(
272 EntryList* out) const { 198 EntryList* out) const {
273 AppendAllEntriesFromRequests(GetLiveRequests(), out); 199 // Append all of the entries for each of the sources.
274 AppendAllEntriesFromRequests(GetRecentlyDeceased(), out); 200 for (SourceIDToInfoMap::const_iterator it = requests_.begin();
201 it != requests_.end();
202 ++it) {
203 const RequestInfo& info = it->second;
204 out->insert(out->end(), info.entries.begin(), info.entries.end());
205 }
275 } 206 }
276 207
277 void PassiveLogCollector::RequestTrackerBase::InsertIntoGraveyard( 208 void PassiveLogCollector::RequestTrackerBase::AddToDeletionQueue(
278 const RequestInfo& info) { 209 uint32 source_id) {
279 // Enforce a bound on the graveyard size, by treating it as a 210 DCHECK(requests_.find(source_id) != requests_.end());
280 // circular buffer. 211 DCHECK(!requests_.find(source_id)->second.is_alive);
281 if (graveyard_.size() < max_graveyard_size_) { 212 DCHECK_GE(requests_.find(source_id)->second.reference_count, 0);
282 // Still growing to maximum capacity. 213 DCHECK_LE(deletion_queue_.size(), max_graveyard_size_);
283 DCHECK_EQ(next_graveyard_index_, graveyard_.size()); 214
284 graveyard_.push_back(info); 215 deletion_queue_.push_back(source_id);
285 } else { 216
286 // At maximum capacity, overwite the oldest entry. 217 // After the deletion queue has reached its maximum size, start
287 graveyard_[next_graveyard_index_] = info; 218 // deleting requests in FIFO order.
219 if (deletion_queue_.size() > max_graveyard_size_) {
220 uint32 oldest = deletion_queue_.front();
221 deletion_queue_.pop_front();
222 DeleteRequestInfo(oldest);
288 } 223 }
289 next_graveyard_index_ = (next_graveyard_index_ + 1) % max_graveyard_size_; 224 }
225
226 void PassiveLogCollector::RequestTrackerBase::AdjustReferenceCountForSource(
227 int offset, uint32 source_id) {
228 DCHECK(offset == -1 || offset == 1) << "invalid offset: " << offset;
229
230 // In general it is invalid to call AdjustReferenceCountForSource() on
231 // source that doesn't exist. However, it is possible that if
232 // RequestTrackerBase::Clear() was previously called this can happen.
233 // TODO(eroman): Add a unit-test that exercises this case.
234 SourceIDToInfoMap::iterator it = requests_.find(source_id);
235 if (it == requests_.end())
236 return;
237
238 RequestInfo& info = it->second;
239 DCHECK_GE(info.reference_count, 0);
240 DCHECK_GE(info.reference_count + offset, 0);
241 info.reference_count += offset;
242
243 if (!info.is_alive) {
244 if (info.reference_count == 1 && offset == 1) {
245 // If we just added a reference to a dead source that had no references,
246 // it must have been in the deletion queue, so remove it from the queue.
247 DeletionQueue::iterator it =
248 std::remove(deletion_queue_.begin(), deletion_queue_.end(),
249 source_id);
250 DCHECK(it != deletion_queue_.end());
251 deletion_queue_.erase(it);
252 } else if (info.reference_count == 0) {
253 // If we just released the final reference to a dead request, go ahead
254 // and delete it right away.
255 DeleteRequestInfo(source_id);
256 }
257 }
258 }
259
260 void PassiveLogCollector::RequestTrackerBase::AddReferenceToSourceDependency(
261 const net::NetLog::Source& source, RequestInfo* info) {
262 // Find the tracker which should be holding |source|.
263 DCHECK(parent_);
264 RequestTrackerBase* tracker =
265 parent_->GetTrackerForSourceType(source.type);
266 DCHECK(tracker);
267
268 // Tell the owning tracker to increment the reference count of |source|.
269 tracker->AdjustReferenceCountForSource(1, source.id);
270
271 // Make a note to release this reference once |info| is destroyed.
272 info->dependencies.push_back(source);
273 }
274
275 void
276 PassiveLogCollector::RequestTrackerBase::ReleaseAllReferencesToDependencies(
277 RequestInfo* info) {
278 // Release all references |info| was holding to dependent sources.
279 for (SourceDependencyList::const_iterator it = info->dependencies.begin();
280 it != info->dependencies.end(); ++it) {
281 const net::NetLog::Source& source = *it;
282
283 // Find the tracker which should be holding |source|.
284 DCHECK(parent_);
285 RequestTrackerBase* tracker =
286 parent_->GetTrackerForSourceType(source.type);
287 DCHECK(tracker);
288
289 // Tell the owning tracker to decrement the reference count of |source|.
290 tracker->AdjustReferenceCountForSource(-1, source.id);
291 }
292
293 info->dependencies.clear();
290 } 294 }
291 295
292 //---------------------------------------------------------------------------- 296 //----------------------------------------------------------------------------
293 // ConnectJobTracker 297 // ConnectJobTracker
294 //---------------------------------------------------------------------------- 298 //----------------------------------------------------------------------------
295 299
296 const size_t PassiveLogCollector::ConnectJobTracker::kMaxGraveyardSize = 15; 300 const size_t PassiveLogCollector::ConnectJobTracker::kMaxGraveyardSize = 15;
297 301
298 PassiveLogCollector::ConnectJobTracker::ConnectJobTracker() 302 PassiveLogCollector::ConnectJobTracker::ConnectJobTracker(
299 : RequestTrackerBase(kMaxGraveyardSize) { 303 PassiveLogCollector* parent)
304 : RequestTrackerBase(kMaxGraveyardSize, parent) {
300 } 305 }
301 306
302 PassiveLogCollector::RequestTrackerBase::Action 307 PassiveLogCollector::RequestTrackerBase::Action
303 PassiveLogCollector::ConnectJobTracker::DoAddEntry(const Entry& entry, 308 PassiveLogCollector::ConnectJobTracker::DoAddEntry(const Entry& entry,
304 RequestInfo* out_info) { 309 RequestInfo* out_info) {
305 AddEntryToRequestInfo(entry, out_info); 310 AddEntryToRequestInfo(entry, out_info);
306 311
307 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID) { 312 if (entry.type == net::NetLog::TYPE_CONNECT_JOB_SET_SOCKET) {
308 SetSubordinateSource(out_info, entry); 313 const net::NetLog::Source& source_dependency =
314 static_cast<net::NetLogSourceParameter*>(entry.params.get())->value();
315 AddReferenceToSourceDependency(source_dependency, out_info);
309 } 316 }
310 317
311 // If this is the end of the connect job, move the request to the graveyard. 318 // If this is the end of the connect job, move the request to the graveyard.
312 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB && 319 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB &&
313 entry.phase == net::NetLog::PHASE_END) { 320 entry.phase == net::NetLog::PHASE_END) {
314 return ACTION_MOVE_TO_GRAVEYARD; 321 return ACTION_MOVE_TO_GRAVEYARD;
315 } 322 }
316 323
317 return ACTION_NONE; 324 return ACTION_NONE;
318 } 325 }
319 326
320 void PassiveLogCollector::ConnectJobTracker::AppendLogEntries(
321 RequestInfo* out_info, uint32 connect_id) {
322 RequestInfo* connect_info = GetRequestInfo(connect_id);
323 if (!connect_info) {
324 net::NetLogStringParameter* text = new net::NetLogStringParameter(
325 "todo", StringPrintf("Used ConnectJob id=%u", connect_id));
326 Entry new_entry(0, net::NetLog::TYPE_TODO_STRING, base::TimeTicks(),
327 net::NetLog::Source(net::NetLog::SOURCE_CONNECT_JOB,
328 connect_id),
329 net::NetLog::PHASE_NONE, text);
330 AddEntryToRequestInfo(new_entry, out_info);
331 return;
332 }
333
334 AppendToRequestInfo(*connect_info, out_info);
335 std::sort(out_info->entries.begin(), out_info->entries.end(),
336 &SortByOrderComparator);
337 out_info->num_entries_truncated += connect_info->num_entries_truncated;
338
339 if (connect_info->subordinate_source.is_valid())
340 AppendLogEntries(out_info, connect_info->subordinate_source.id);
341 }
342
343 //---------------------------------------------------------------------------- 327 //----------------------------------------------------------------------------
344 // SocketTracker 328 // SocketTracker
345 //---------------------------------------------------------------------------- 329 //----------------------------------------------------------------------------
346 330
347 const size_t PassiveLogCollector::SocketTracker::kMaxGraveyardSize = 15; 331 const size_t PassiveLogCollector::SocketTracker::kMaxGraveyardSize = 15;
348 332
349 PassiveLogCollector::SocketTracker::SocketTracker() 333 PassiveLogCollector::SocketTracker::SocketTracker()
350 : RequestTrackerBase(kMaxGraveyardSize) { 334 : RequestTrackerBase(kMaxGraveyardSize, NULL) {
351 } 335 }
352 336
353 PassiveLogCollector::RequestTrackerBase::Action 337 PassiveLogCollector::RequestTrackerBase::Action
354 PassiveLogCollector::SocketTracker::DoAddEntry(const Entry& entry, 338 PassiveLogCollector::SocketTracker::DoAddEntry(const Entry& entry,
355 RequestInfo* out_info) { 339 RequestInfo* out_info) {
356 int int_arg; 340 // TODO(eroman): aggregate the byte counts once truncation starts to happen,
357 switch (entry.type) { 341 // to summarize transaction read/writes for each SOCKET_IN_USE
358 case net::NetLog::TYPE_SOCKET_BYTES_SENT: 342 // section.
359 int_arg = static_cast<net::NetLogIntegerParameter*>( 343 if (entry.type == net::NetLog::TYPE_SOCKET_BYTES_SENT ||
360 entry.params.get())->value(); 344 entry.type == net::NetLog::TYPE_SOCKET_BYTES_RECEIVED) {
361 out_info->total_bytes_transmitted += int_arg; 345 return ACTION_NONE;
362 out_info->bytes_transmitted += int_arg;
363 out_info->last_tx_rx_time = entry.time;
364 out_info->last_tx_rx_position = entry.order;
365 break;
366 case net::NetLog::TYPE_SOCKET_BYTES_RECEIVED:
367 int_arg = static_cast<net::NetLogIntegerParameter*>(
368 entry.params.get())->value();
369 out_info->total_bytes_received += int_arg;
370 out_info->bytes_received += int_arg;
371 out_info->last_tx_rx_time = entry.time;
372 out_info->last_tx_rx_position = entry.order;
373 break;
374 case net::NetLog::TYPE_TCP_SOCKET_DONE:
375 return ACTION_MOVE_TO_GRAVEYARD;
376 default:
377 AddEntryToRequestInfo(entry, out_info);
378 break;
379 }
380 return ACTION_NONE;
381 }
382
383 void PassiveLogCollector::SocketTracker::AppendLogEntries(
384 RequestInfo* out_info, uint32 socket_id, bool clear) {
385 RequestInfo* socket_info = GetRequestInfo(socket_id);
386 if (!socket_info) {
387 net::NetLogStringParameter* text = new net::NetLogStringParameter(
388 "todo", StringPrintf("Used Socket id=%u.", socket_id));
389 Entry new_entry(0, net::NetLog::TYPE_TODO_STRING, base::TimeTicks(),
390 net::NetLog::Source(net::NetLog::SOURCE_SOCKET, socket_id),
391 net::NetLog::PHASE_NONE, text);
392 AddEntryToRequestInfo(new_entry, out_info);
393 return;
394 } 346 }
395 347
396 AppendToRequestInfo(*socket_info, out_info); 348 AddEntryToRequestInfo(entry, out_info);
397 out_info->num_entries_truncated += socket_info->num_entries_truncated;
398 349
399 // Synthesize a log entry for bytes sent and received. 350 if (entry.type == net::NetLog::TYPE_SOCKET_ALIVE &&
400 if (socket_info->bytes_transmitted > 0 || socket_info->bytes_received > 0) { 351 entry.phase == net::NetLog::PHASE_END) {
401 net::NetLogStringParameter* text = new net::NetLogStringParameter( 352 return ACTION_MOVE_TO_GRAVEYARD;
402 "stats",
403 StringPrintf("Tx/Rx: %"PRIu64"/%"PRIu64" [%"PRIu64"/%"PRIu64
404 " total on socket] (Bytes)",
405 socket_info->bytes_transmitted,
406 socket_info->bytes_received,
407 socket_info->total_bytes_transmitted,
408 socket_info->total_bytes_received));
409 Entry new_entry(socket_info->last_tx_rx_position,
410 net::NetLog::TYPE_TODO_STRING,
411 socket_info->last_tx_rx_time,
412 net::NetLog::Source(net::NetLog::SOURCE_SOCKET, socket_id),
413 net::NetLog::PHASE_NONE,
414 text);
415 AddEntryToRequestInfo(new_entry, out_info);
416 } 353 }
417 std::sort(out_info->entries.begin(), out_info->entries.end(),
418 &SortByOrderComparator);
419 354
420 if (clear) 355 return ACTION_NONE;
421 ClearInfo(socket_info);
422 }
423
424 void PassiveLogCollector::SocketTracker::ClearInfo(RequestInfo* info) {
425 info->entries.clear();
426 info->num_entries_truncated = 0;
427 info->bytes_transmitted = 0;
428 info->bytes_received = 0;
429 info->last_tx_rx_position = 0;
430 info->last_tx_rx_time = base::TimeTicks();
431 } 356 }
432 357
433 //---------------------------------------------------------------------------- 358 //----------------------------------------------------------------------------
434 // RequestTracker 359 // RequestTracker
435 //---------------------------------------------------------------------------- 360 //----------------------------------------------------------------------------
436 361
437 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardSize = 25; 362 const size_t PassiveLogCollector::RequestTracker::kMaxGraveyardSize = 25;
438 363
439 PassiveLogCollector::RequestTracker::RequestTracker( 364 PassiveLogCollector::RequestTracker::RequestTracker(PassiveLogCollector* parent)
440 ConnectJobTracker* connect_job_tracker, SocketTracker* socket_tracker) 365 : RequestTrackerBase(kMaxGraveyardSize, parent) {
441 : RequestTrackerBase(kMaxGraveyardSize),
442 connect_job_tracker_(connect_job_tracker),
443 socket_tracker_(socket_tracker) {
444 } 366 }
445 367
446 PassiveLogCollector::RequestTrackerBase::Action 368 PassiveLogCollector::RequestTrackerBase::Action
447 PassiveLogCollector::RequestTracker::DoAddEntry(const Entry& entry, 369 PassiveLogCollector::RequestTracker::DoAddEntry(const Entry& entry,
448 RequestInfo* out_info) { 370 RequestInfo* out_info) {
449 // We expect up to three events with IDs. 371 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_CONNECT_JOB ||
450 // - Begin SOCKET_POOL_CONNECT_JOB_ID: Means a ConnectJob was created for 372 entry.type == net::NetLog::TYPE_SOCKET_POOL_BOUND_TO_SOCKET) {
451 // this request. Including it for now, but the resulting socket may be 373 const net::NetLog::Source& source_dependency =
452 // used for a different request. 374 static_cast<net::NetLogSourceParameter*>(entry.params.get())->value();
453 // - End SOCKET_POOL_CONNECT_JOB_ID: The named ConnectJob completed and 375 AddReferenceToSourceDependency(source_dependency, out_info);
454 // this request will be getting the socket from that request.
455 // - SOCKET_POOL_SOCKET_ID: The given socket will be used for this request.
456 //
457 // The action to take when seeing these events depends on the current
458 // content of the |subordinate_source| field:
459 // |subordinate_source| is invalid (fresh state).
460 // - Begin SOCKET_POOL_CONNECT_JOB_ID: Set |subordinate_source|.
461 // - End SOCKET_POOL_CONNECT_JOB_ID: Integrate the named ConnectJob ID.
462 // - SOCKET_POOL_SOCKET_ID: Set |subordinate_source|.
463 // |subordinate_source| is a ConnectJob:
464 // - Begin SOCKET_POOL_CONNECT_JOB_ID: Set |subordinate_source|.
465 // - End SOCKET_POOL_CONNECT_JOB_ID: Integrate the named ConnectJob ID and
466 // clear the |subordinate_source|.
467 // - SOCKET_POOL_SOCKET_ID: Set |subordinate_source|. (The request was
468 // assigned a new idle socket, after starting a ConnectJob.)
469 // |subordinate_source| is a Socket:
470 // First, integrate the subordinate socket source, then:
471 // - Begin SOCKET_POOL_CONNECT_JOB_ID: Set |subordinate_source|.
472 // (Connection restarted with a new ConnectJob.)
473 // - End SOCKET_POOL_CONNECT_JOB_ID: Integrate the named ConnectJob ID and
474 // clear the |subordinate_source|. (Connection restarted with a late bound
475 // ConnectJob.)
476 // - SOCKET_POOL_SOCKET_ID: Set |subordinate_source|. (Connection
477 // restarted and got an idle socket.)
478 if (entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID ||
479 entry.type == net::NetLog::TYPE_SOCKET_POOL_SOCKET_ID) {
480
481 if (out_info->subordinate_source.is_valid() &&
482 out_info->subordinate_source.type == net::NetLog::SOURCE_SOCKET)
483 IntegrateSubordinateSource(out_info, true);
484
485 SetSubordinateSource(out_info, entry);
486
487 if (entry.phase == net::NetLog::PHASE_END &&
488 entry.type == net::NetLog::TYPE_SOCKET_POOL_CONNECT_JOB_ID) {
489 IntegrateSubordinateSource(out_info, true);
490 out_info->subordinate_source.id = net::NetLog::Source::kInvalidId;
491 }
492 } 376 }
493 377
494 AddEntryToRequestInfo(entry, out_info); 378 AddEntryToRequestInfo(entry, out_info);
495 379
496 // If the request has ended, move it to the graveyard. 380 // If the request has ended, move it to the graveyard.
497 if (entry.type == net::NetLog::TYPE_REQUEST_ALIVE && 381 if (entry.type == net::NetLog::TYPE_REQUEST_ALIVE &&
498 entry.phase == net::NetLog::PHASE_END) { 382 entry.phase == net::NetLog::PHASE_END) {
499 IntegrateSubordinateSource(out_info, true);
500 if (StartsWithASCII(out_info->GetURL(), "chrome://", false)) { 383 if (StartsWithASCII(out_info->GetURL(), "chrome://", false)) {
501 // Avoid sending "chrome://" requests to the graveyard, since it just 384 // Avoid sending "chrome://" requests to the graveyard, since it just
502 // adds to clutter. 385 // adds to clutter.
503 return ACTION_DELETE; 386 return ACTION_DELETE;
504 } 387 }
505 return ACTION_MOVE_TO_GRAVEYARD; 388 return ACTION_MOVE_TO_GRAVEYARD;
506 } 389 }
507 390
508 return ACTION_NONE; 391 return ACTION_NONE;
509 } 392 }
510 393
511 void PassiveLogCollector::RequestTracker::IntegrateSubordinateSource(
512 RequestInfo* info, bool clear_entries) const {
513 if (!info->subordinate_source.is_valid())
514 return;
515
516 uint32 subordinate_id = info->subordinate_source.id;
517 switch (info->subordinate_source.type) {
518 case net::NetLog::SOURCE_CONNECT_JOB:
519 connect_job_tracker_->AppendLogEntries(info, subordinate_id);
520 break;
521 case net::NetLog::SOURCE_SOCKET:
522 socket_tracker_->AppendLogEntries(info, subordinate_id, clear_entries);
523 break;
524 default:
525 NOTREACHED();
526 break;
527 }
528 }
529
530 //---------------------------------------------------------------------------- 394 //----------------------------------------------------------------------------
531 // InitProxyResolverTracker 395 // InitProxyResolverTracker
532 //---------------------------------------------------------------------------- 396 //----------------------------------------------------------------------------
533 397
534 PassiveLogCollector::InitProxyResolverTracker::InitProxyResolverTracker() {} 398 const size_t PassiveLogCollector::InitProxyResolverTracker::kMaxGraveyardSize =
399 3;
535 400
536 void PassiveLogCollector::InitProxyResolverTracker::OnAddEntry( 401 PassiveLogCollector::InitProxyResolverTracker::InitProxyResolverTracker()
537 const Entry& entry) { 402 : RequestTrackerBase(kMaxGraveyardSize, NULL) {
403 }
404
405 PassiveLogCollector::RequestTrackerBase::Action
406 PassiveLogCollector::InitProxyResolverTracker::DoAddEntry(
407 const Entry& entry, RequestInfo* out_info) {
408 AddEntryToRequestInfo(entry, out_info);
538 if (entry.type == net::NetLog::TYPE_INIT_PROXY_RESOLVER && 409 if (entry.type == net::NetLog::TYPE_INIT_PROXY_RESOLVER &&
539 entry.phase == net::NetLog::PHASE_BEGIN) { 410 entry.phase == net::NetLog::PHASE_END) {
540 // If this is the start of a new InitProxyResolver, overwrite the old data. 411 return ACTION_MOVE_TO_GRAVEYARD;
541 entries_.clear();
542 entries_.push_back(entry);
543 } else { 412 } else {
544 // Otherwise append it to the log for the latest InitProxyResolver. 413 return ACTION_NONE;
545 if (!entries_.empty() && entries_[0].source.id != entry.source.id) {
546 // If this entry doesn't match what we think was the latest
547 // InitProxyResolver, drop it. (This shouldn't happen, but we will guard
548 // against it).
549 return;
550 }
551 entries_.push_back(entry);
552 } 414 }
553
554 // Safety net: INIT_PROXY_RESOLVER shouldn't generate many messages, but in
555 // case something goes wrong, avoid exploding the memory usage.
556 if (entries_.size() > kMaxNumEntriesPerLog)
557 entries_.clear();
558 } 415 }
559 416
560 //---------------------------------------------------------------------------- 417 //----------------------------------------------------------------------------
561 // SpdySessionTracker 418 // SpdySessionTracker
562 //---------------------------------------------------------------------------- 419 //----------------------------------------------------------------------------
563 420
564 const size_t PassiveLogCollector::SpdySessionTracker::kMaxGraveyardSize = 10; 421 const size_t PassiveLogCollector::SpdySessionTracker::kMaxGraveyardSize = 10;
565 422
566 PassiveLogCollector::SpdySessionTracker::SpdySessionTracker() 423 PassiveLogCollector::SpdySessionTracker::SpdySessionTracker()
567 : RequestTrackerBase(kMaxGraveyardSize) { 424 : RequestTrackerBase(kMaxGraveyardSize, NULL) {
568 } 425 }
569 426
570 PassiveLogCollector::RequestTrackerBase::Action 427 PassiveLogCollector::RequestTrackerBase::Action
571 PassiveLogCollector::SpdySessionTracker::DoAddEntry(const Entry& entry, 428 PassiveLogCollector::SpdySessionTracker::DoAddEntry(const Entry& entry,
572 RequestInfo* out_info) { 429 RequestInfo* out_info) {
430 AddEntryToRequestInfo(entry, out_info);
573 if (entry.type == net::NetLog::TYPE_SPDY_SESSION && 431 if (entry.type == net::NetLog::TYPE_SPDY_SESSION &&
574 entry.phase == net::NetLog::PHASE_END) { 432 entry.phase == net::NetLog::PHASE_END) {
575 return ACTION_MOVE_TO_GRAVEYARD; 433 return ACTION_MOVE_TO_GRAVEYARD;
576 } else { 434 } else {
577 AddEntryToRequestInfo(entry, out_info);
578 return ACTION_NONE; 435 return ACTION_NONE;
579 } 436 }
580 } 437 }
OLDNEW
« no previous file with comments | « chrome/browser/net/passive_log_collector.h ('k') | chrome/browser/net/passive_log_collector_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698