| 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 |