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 #ifndef CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_ | 5 #ifndef CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_ |
6 #define CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_ | 6 #define CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_ |
7 | 7 |
| 8 #include <deque> |
8 #include <string> | 9 #include <string> |
9 #include <vector> | 10 #include <vector> |
10 | 11 |
11 #include "base/gtest_prod_util.h" | 12 #include "base/gtest_prod_util.h" |
12 #include "base/hash_tables.h" | 13 #include "base/hash_tables.h" |
13 #include "base/ref_counted.h" | 14 #include "base/ref_counted.h" |
14 #include "base/time.h" | 15 #include "base/time.h" |
15 #include "chrome/browser/net/chrome_net_log.h" | 16 #include "chrome/browser/net/chrome_net_log.h" |
16 #include "net/base/net_log.h" | 17 #include "net/base/net_log.h" |
17 | 18 |
| 19 // PassiveLogCollector watches the NetLog event stream, and saves the network |
| 20 // event for recent requests, in a circular buffer. |
| 21 // |
| 22 // This is done so that when a network problem is encountered (performance |
| 23 // problem, or error), about:net-internals can be opened shortly after the |
| 24 // problem and it will contain a trace for the problem request. |
| 25 // |
| 26 // (This is in contrast to the "active logging" which captures every single |
| 27 // network event, but requires capturing to have been enabled *prior* to |
| 28 // encountering the problem. Active capturing is enabled as long as |
| 29 // about:net-internals is open). |
| 30 // |
| 31 // The data captured by PassiveLogCollector is grouped by NetLog::Source, into |
| 32 // a RequestInfo structure. These in turn are grouped by NetLog::SourceType, and |
| 33 // owned by a RequestTrackerBase instance for the specific source type. |
18 class PassiveLogCollector : public ChromeNetLog::Observer { | 34 class PassiveLogCollector : public ChromeNetLog::Observer { |
19 public: | 35 public: |
20 // This structure encapsulates all of the parameters of a captured event, | 36 // This structure encapsulates all of the parameters of a captured event, |
21 // including an "order" field that identifies when it was captured relative | 37 // including an "order" field that identifies when it was captured relative |
22 // to other events. | 38 // to other events. |
23 struct Entry { | 39 struct Entry { |
24 Entry(uint32 order, | 40 Entry(uint32 order, |
25 net::NetLog::EventType type, | 41 net::NetLog::EventType type, |
26 const base::TimeTicks& time, | 42 const base::TimeTicks& time, |
27 net::NetLog::Source source, | 43 net::NetLog::Source source, |
28 net::NetLog::EventPhase phase, | 44 net::NetLog::EventPhase phase, |
29 net::NetLog::EventParameters* params) | 45 net::NetLog::EventParameters* params) |
30 : order(order), type(type), time(time), source(source), phase(phase), | 46 : order(order), type(type), time(time), source(source), phase(phase), |
31 params(params) { | 47 params(params) { |
32 } | 48 } |
33 | 49 |
34 uint32 order; | 50 uint32 order; |
35 net::NetLog::EventType type; | 51 net::NetLog::EventType type; |
36 base::TimeTicks time; | 52 base::TimeTicks time; |
37 net::NetLog::Source source; | 53 net::NetLog::Source source; |
38 net::NetLog::EventPhase phase; | 54 net::NetLog::EventPhase phase; |
39 scoped_refptr<net::NetLog::EventParameters> params; | 55 scoped_refptr<net::NetLog::EventParameters> params; |
40 }; | 56 }; |
41 | 57 |
42 typedef std::vector<Entry> EntryList; | 58 typedef std::vector<Entry> EntryList; |
| 59 typedef std::vector<net::NetLog::Source> SourceDependencyList; |
43 | 60 |
| 61 // TODO(eroman): Rename to SourceInfo. |
44 struct RequestInfo { | 62 struct RequestInfo { |
45 RequestInfo() | 63 RequestInfo() |
46 : source_id(net::NetLog::Source::kInvalidId), | 64 : source_id(net::NetLog::Source::kInvalidId), |
47 num_entries_truncated(0), | 65 num_entries_truncated(0), reference_count(0), is_alive(true) {} |
48 total_bytes_transmitted(0), | |
49 total_bytes_received(0), | |
50 bytes_transmitted(0), | |
51 bytes_received(0), | |
52 last_tx_rx_position(0) {} | |
53 | 66 |
54 // Returns the URL that corresponds with this source. This is | 67 // Returns the URL that corresponds with this source. This is |
55 // only meaningful for certain source types (URL_REQUEST, SOCKET_STREAM). | 68 // only meaningful for certain source types (URL_REQUEST, SOCKET_STREAM). |
56 // For the rest, it will return an empty string. | 69 // For the rest, it will return an empty string. |
57 std::string GetURL() const; | 70 std::string GetURL() const; |
58 | 71 |
59 uint32 source_id; | 72 uint32 source_id; |
60 EntryList entries; | 73 EntryList entries; |
61 size_t num_entries_truncated; | 74 size_t num_entries_truncated; |
62 net::NetLog::Source subordinate_source; | |
63 | 75 |
64 // Only used in SocketTracker. | 76 // List of other sources which contain information relevant to this |
65 uint64 total_bytes_transmitted; | 77 // request (for example, a url request might depend on the log items |
66 uint64 total_bytes_received; | 78 // for a connect job and for a socket that were bound to it.) |
67 uint64 bytes_transmitted; | 79 SourceDependencyList dependencies; |
68 uint64 bytes_received; | 80 |
69 uint32 last_tx_rx_position; // The |order| of the last Tx or Rx entry. | 81 // Holds the count of how many other sources have added this as a |
70 base::TimeTicks last_tx_rx_time; // The |time| of the last Tx or Rx entry. | 82 // dependent source. When it is 0, it means noone has referenced it so it |
| 83 // can be deleted normally. |
| 84 int reference_count; |
| 85 |
| 86 // |is_alive| is set to false once the request has been added to the |
| 87 // tracker's graveyard (it may still be kept around due to a non-zero |
| 88 // reference_count, but it is still considered "dead"). |
| 89 bool is_alive; |
71 }; | 90 }; |
72 | 91 |
73 typedef std::vector<RequestInfo> RequestInfoList; | 92 typedef std::vector<RequestInfo> RequestInfoList; |
74 | 93 |
75 // This class stores and manages the passively logged information for | 94 // This class stores and manages the passively logged information for |
76 // URLRequests/SocketStreams/ConnectJobs. | 95 // URLRequests/SocketStreams/ConnectJobs. |
77 class RequestTrackerBase { | 96 class RequestTrackerBase { |
78 public: | 97 public: |
79 explicit RequestTrackerBase(size_t max_graveyard_size); | 98 RequestTrackerBase(size_t max_graveyard_size, PassiveLogCollector* parent); |
| 99 |
| 100 virtual ~RequestTrackerBase(); |
80 | 101 |
81 void OnAddEntry(const Entry& entry); | 102 void OnAddEntry(const Entry& entry); |
82 | 103 |
83 RequestInfoList GetLiveRequests() const; | 104 // Clears all the passively logged data from this tracker. |
84 void ClearRecentlyDeceased(); | |
85 RequestInfoList GetRecentlyDeceased() const; | |
86 | |
87 void Clear(); | 105 void Clear(); |
88 | 106 |
89 // Appends all the captured entries to |out|. The ordering is undefined. | 107 // Appends all the captured entries to |out|. The ordering is undefined. |
90 void AppendAllEntries(EntryList* out) const; | 108 void AppendAllEntries(EntryList* out) const; |
91 | 109 |
| 110 #ifdef UNIT_TEST |
| 111 // Helper used to inspect the current state by unit-tests. |
| 112 // Retuns a copy of the requests held by the tracker. |
| 113 RequestInfoList GetAllDeadOrAliveRequests(bool is_alive) const { |
| 114 RequestInfoList result; |
| 115 for (SourceIDToInfoMap::const_iterator it = requests_.begin(); |
| 116 it != requests_.end(); ++it) { |
| 117 if (it->second.is_alive == is_alive) |
| 118 result.push_back(it->second); |
| 119 } |
| 120 return result; |
| 121 } |
| 122 #endif |
| 123 |
92 protected: | 124 protected: |
93 enum Action { | 125 enum Action { |
94 ACTION_NONE, | 126 ACTION_NONE, |
95 ACTION_DELETE, | 127 ACTION_DELETE, |
96 ACTION_MOVE_TO_GRAVEYARD, | 128 ACTION_MOVE_TO_GRAVEYARD, |
97 }; | 129 }; |
98 | 130 |
99 // Finds a request, either in the live entries or the graveyard and returns | 131 // Makes |info| hold a reference to |source|. This way |source| will be |
100 // it. | 132 // kept alive at least as long as |info|. |
101 RequestInfo* GetRequestInfo(uint32 id); | 133 void AddReferenceToSourceDependency(const net::NetLog::Source& source, |
102 | 134 RequestInfo* info); |
103 // When GetLiveRequests() is called, RequestTrackerBase calls this method | |
104 // for each entry after adding it to the list which will be returned | |
105 // to the caller. | |
106 virtual void OnLiveRequest(RequestInfo* info) const {} | |
107 | 135 |
108 private: | 136 private: |
109 typedef base::hash_map<uint32, RequestInfo> SourceIDToInfoMap; | 137 typedef base::hash_map<uint32, RequestInfo> SourceIDToInfoMap; |
| 138 typedef std::deque<uint32> DeletionQueue; |
110 | 139 |
111 // Updates |out_info| with the information from |entry|. Returns an action | 140 // Updates |out_info| with the information from |entry|. Returns an action |
112 // to perform for this map entry on completion. | 141 // to perform for this map entry on completion. |
113 virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info) = 0; | 142 virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info) = 0; |
114 | 143 |
115 void RemoveFromLiveRequests(uint32 source_id); | 144 // Removes |source_id| from |requests_|. This also releases any references |
116 void InsertIntoGraveyard(const RequestInfo& info); | 145 // to dependencies held by this source. |
| 146 void DeleteRequestInfo(uint32 source_id); |
117 | 147 |
118 SourceIDToInfoMap live_requests_; | 148 // Adds |source_id| to the FIFO queue (graveyard) for deletion. |
| 149 void AddToDeletionQueue(uint32 source_id); |
| 150 |
| 151 // Adds/Releases a reference from the source with ID |source_id|. |
| 152 // Use |offset=-1| to do a release, and |offset=1| for an addref. |
| 153 void AdjustReferenceCountForSource(int offset, uint32 source_id); |
| 154 |
| 155 // Releases all the references to sources held by |info|. |
| 156 void ReleaseAllReferencesToDependencies(RequestInfo* info); |
| 157 |
| 158 // This map contains all of the requests being tracked by this tracker. |
| 159 // (It includes both the "live" requests, and the "dead" ones.) |
| 160 SourceIDToInfoMap requests_; |
| 161 |
119 size_t max_graveyard_size_; | 162 size_t max_graveyard_size_; |
120 size_t next_graveyard_index_; | 163 |
121 RequestInfoList graveyard_; | 164 // FIFO queue for entries in |requests_| that are no longer alive, and |
| 165 // can be deleted. This buffer is also called "graveyard" elsewhere. We |
| 166 // queue requests for deletion so they can persist a bit longer. |
| 167 DeletionQueue deletion_queue_; |
| 168 |
| 169 PassiveLogCollector* parent_; |
122 | 170 |
123 DISALLOW_COPY_AND_ASSIGN(RequestTrackerBase); | 171 DISALLOW_COPY_AND_ASSIGN(RequestTrackerBase); |
124 }; | 172 }; |
125 | 173 |
126 // Specialization of RequestTrackerBase for handling ConnectJobs. | 174 // Specialization of RequestTrackerBase for handling ConnectJobs. |
127 class ConnectJobTracker : public RequestTrackerBase { | 175 class ConnectJobTracker : public RequestTrackerBase { |
128 public: | 176 public: |
129 static const size_t kMaxGraveyardSize; | 177 static const size_t kMaxGraveyardSize; |
130 | 178 |
131 ConnectJobTracker(); | 179 explicit ConnectJobTracker(PassiveLogCollector* parent); |
132 | |
133 void AppendLogEntries(RequestInfo* out_info, uint32 connect_id); | |
134 | 180 |
135 protected: | 181 protected: |
136 virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info); | 182 virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info); |
137 private: | 183 private: |
138 DISALLOW_COPY_AND_ASSIGN(ConnectJobTracker); | 184 DISALLOW_COPY_AND_ASSIGN(ConnectJobTracker); |
139 }; | 185 }; |
140 | 186 |
141 // Specialization of RequestTrackerBase for handling Sockets. | 187 // Specialization of RequestTrackerBase for handling Sockets. |
142 class SocketTracker : public RequestTrackerBase { | 188 class SocketTracker : public RequestTrackerBase { |
143 public: | 189 public: |
144 static const size_t kMaxGraveyardSize; | 190 static const size_t kMaxGraveyardSize; |
145 | 191 |
146 SocketTracker(); | 192 SocketTracker(); |
147 | 193 |
148 void AppendLogEntries(RequestInfo* out_info, uint32 socket_id, bool clear); | |
149 | |
150 protected: | 194 protected: |
151 virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info); | 195 virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info); |
152 | 196 |
153 private: | 197 private: |
154 void ClearInfo(RequestInfo* info); | |
155 | |
156 DISALLOW_COPY_AND_ASSIGN(SocketTracker); | 198 DISALLOW_COPY_AND_ASSIGN(SocketTracker); |
157 }; | 199 }; |
158 | 200 |
159 // Specialization of RequestTrackerBase for handling URLRequest/SocketStream. | 201 // Specialization of RequestTrackerBase for handling URLRequest/SocketStream. |
160 class RequestTracker : public RequestTrackerBase { | 202 class RequestTracker : public RequestTrackerBase { |
161 public: | 203 public: |
162 static const size_t kMaxGraveyardSize; | 204 static const size_t kMaxGraveyardSize; |
163 | 205 |
164 RequestTracker(ConnectJobTracker* connect_job_tracker, | 206 explicit RequestTracker(PassiveLogCollector* parent); |
165 SocketTracker* socket_tracker); | |
166 | |
167 void IntegrateSubordinateSource(RequestInfo* info, | |
168 bool clear_entries) const; | |
169 | 207 |
170 protected: | 208 protected: |
171 virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info); | 209 virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info); |
172 | 210 |
173 virtual void OnLiveRequest(RequestInfo* info) const { | |
174 IntegrateSubordinateSource(info, false); | |
175 } | |
176 | |
177 private: | 211 private: |
178 ConnectJobTracker* connect_job_tracker_; | |
179 SocketTracker* socket_tracker_; | |
180 | |
181 DISALLOW_COPY_AND_ASSIGN(RequestTracker); | 212 DISALLOW_COPY_AND_ASSIGN(RequestTracker); |
182 }; | 213 }; |
183 | 214 |
184 // Tracks the log entries for the last seen SOURCE_INIT_PROXY_RESOLVER. | 215 // Specialization of RequestTrackerBase for handling |
185 class InitProxyResolverTracker { | 216 // SOURCE_INIT_PROXY_RESOLVER. |
| 217 class InitProxyResolverTracker : public RequestTrackerBase { |
186 public: | 218 public: |
| 219 static const size_t kMaxGraveyardSize; |
| 220 |
187 InitProxyResolverTracker(); | 221 InitProxyResolverTracker(); |
188 | 222 |
189 void OnAddEntry(const Entry& entry); | 223 protected: |
190 | 224 virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info); |
191 const EntryList& entries() const { | |
192 return entries_; | |
193 } | |
194 | 225 |
195 private: | 226 private: |
196 EntryList entries_; | |
197 DISALLOW_COPY_AND_ASSIGN(InitProxyResolverTracker); | 227 DISALLOW_COPY_AND_ASSIGN(InitProxyResolverTracker); |
198 }; | 228 }; |
199 | 229 |
200 // Tracks the log entries for the last seen SOURCE_SPDY_SESSION. | 230 // Tracks the log entries for the last seen SOURCE_SPDY_SESSION. |
201 class SpdySessionTracker : public RequestTrackerBase { | 231 class SpdySessionTracker : public RequestTrackerBase { |
202 public: | 232 public: |
203 static const size_t kMaxGraveyardSize; | 233 static const size_t kMaxGraveyardSize; |
204 | 234 |
205 SpdySessionTracker(); | 235 SpdySessionTracker(); |
206 | 236 |
207 protected: | 237 protected: |
208 virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info); | 238 virtual Action DoAddEntry(const Entry& entry, RequestInfo* out_info); |
209 | 239 |
210 private: | 240 private: |
211 DISALLOW_COPY_AND_ASSIGN(SpdySessionTracker); | 241 DISALLOW_COPY_AND_ASSIGN(SpdySessionTracker); |
212 }; | 242 }; |
213 | 243 |
214 PassiveLogCollector(); | 244 PassiveLogCollector(); |
215 ~PassiveLogCollector(); | 245 ~PassiveLogCollector(); |
216 | 246 |
217 // Observer implementation: | 247 // Observer implementation: |
218 virtual void OnAddEntry(net::NetLog::EventType type, | 248 virtual void OnAddEntry(net::NetLog::EventType type, |
219 const base::TimeTicks& time, | 249 const base::TimeTicks& time, |
220 const net::NetLog::Source& source, | 250 const net::NetLog::Source& source, |
221 net::NetLog::EventPhase phase, | 251 net::NetLog::EventPhase phase, |
222 net::NetLog::EventParameters* params); | 252 net::NetLog::EventParameters* params); |
223 | 253 |
| 254 // Returns the tracker to use for sources of type |source_type|, or NULL. |
| 255 RequestTrackerBase* GetTrackerForSourceType( |
| 256 net::NetLog::SourceType source_type); |
| 257 |
224 // Clears all of the passively logged data. | 258 // Clears all of the passively logged data. |
225 void Clear(); | 259 void Clear(); |
226 | 260 |
227 RequestTracker* url_request_tracker() { | |
228 return &url_request_tracker_; | |
229 } | |
230 | |
231 RequestTracker* socket_stream_tracker() { | |
232 return &socket_stream_tracker_; | |
233 } | |
234 | |
235 InitProxyResolverTracker* init_proxy_resolver_tracker() { | |
236 return &init_proxy_resolver_tracker_; | |
237 } | |
238 | |
239 SpdySessionTracker* spdy_session_tracker() { | |
240 return &spdy_session_tracker_; | |
241 } | |
242 | |
243 // Fills |out| with the full list of events that have been passively | 261 // Fills |out| with the full list of events that have been passively |
244 // captured. The list is ordered by capture time. | 262 // captured. The list is ordered by capture time. |
245 void GetAllCapturedEvents(EntryList* out) const; | 263 void GetAllCapturedEvents(EntryList* out) const; |
246 | 264 |
247 private: | 265 private: |
248 FRIEND_TEST_ALL_PREFIXES(PassiveLogCollectorTest, LostConnectJob); | 266 FRIEND_TEST_ALL_PREFIXES(PassiveLogCollectorTest, |
249 FRIEND_TEST_ALL_PREFIXES(PassiveLogCollectorTest, LostSocket); | 267 HoldReferenceToDependentSource); |
250 | 268 |
251 ConnectJobTracker connect_job_tracker_; | 269 ConnectJobTracker connect_job_tracker_; |
252 SocketTracker socket_tracker_; | 270 SocketTracker socket_tracker_; |
253 RequestTracker url_request_tracker_; | 271 RequestTracker url_request_tracker_; |
254 RequestTracker socket_stream_tracker_; | 272 RequestTracker socket_stream_tracker_; |
255 InitProxyResolverTracker init_proxy_resolver_tracker_; | 273 InitProxyResolverTracker init_proxy_resolver_tracker_; |
256 SpdySessionTracker spdy_session_tracker_; | 274 SpdySessionTracker spdy_session_tracker_; |
257 | 275 |
| 276 // This array maps each NetLog::SourceType to one of the tracker instances |
| 277 // defined above. Use of this array avoid duplicating the list of trackers |
| 278 // elsewhere. |
| 279 RequestTrackerBase* trackers_[net::NetLog::SOURCE_COUNT]; |
| 280 |
258 // The count of how many events have flowed through this log. Used to set the | 281 // The count of how many events have flowed through this log. Used to set the |
259 // "order" field on captured events. | 282 // "order" field on captured events. |
260 uint32 num_events_seen_; | 283 uint32 num_events_seen_; |
261 | 284 |
262 DISALLOW_COPY_AND_ASSIGN(PassiveLogCollector); | 285 DISALLOW_COPY_AND_ASSIGN(PassiveLogCollector); |
263 }; | 286 }; |
264 | 287 |
265 #endif // CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_ | 288 #endif // CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_ |
OLD | NEW |