passive_log_collector.h revision 731df977c0511bca2206b5f333555b1205ff1f43
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 3// found in the LICENSE file. 4 5#ifndef CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_ 6#define CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_ 7#pragma once 8 9#include <deque> 10#include <string> 11#include <vector> 12 13#include "base/gtest_prod_util.h" 14#include "base/hash_tables.h" 15#include "base/ref_counted.h" 16#include "base/time.h" 17#include "chrome/browser/net/chrome_net_log.h" 18#include "net/base/net_log.h" 19 20// PassiveLogCollector watches the NetLog event stream, and saves the network 21// events for recent requests, in a circular buffer. 22// 23// This is done so that when a network problem is encountered (performance 24// problem, or error), about:net-internals can be opened shortly after the 25// problem and it will contain a trace for the problem request. 26// 27// (This is in contrast to the "active logging" which captures every single 28// network event, but requires capturing to have been enabled *prior* to 29// encountering the problem. Active capturing is enabled as long as 30// about:net-internals is open). 31// 32// The data captured by PassiveLogCollector is grouped by NetLog::Source, into 33// a SourceInfo structure. These in turn are grouped by NetLog::SourceType, and 34// owned by a SourceTracker instance for the specific source type. 35class PassiveLogCollector : public ChromeNetLog::Observer { 36 public: 37 // This structure encapsulates all of the parameters of a captured event, 38 // including an "order" field that identifies when it was captured relative 39 // to other events. 40 struct Entry { 41 Entry(uint32 order, 42 net::NetLog::EventType type, 43 const base::TimeTicks& time, 44 net::NetLog::Source source, 45 net::NetLog::EventPhase phase, 46 net::NetLog::EventParameters* params); 47 ~Entry(); 48 49 uint32 order; 50 net::NetLog::EventType type; 51 base::TimeTicks time; 52 net::NetLog::Source source; 53 net::NetLog::EventPhase phase; 54 scoped_refptr<net::NetLog::EventParameters> params; 55 }; 56 57 typedef std::vector<Entry> EntryList; 58 typedef std::vector<net::NetLog::Source> SourceDependencyList; 59 60 struct SourceInfo { 61 SourceInfo(); 62 ~SourceInfo(); 63 64 // Returns the URL that corresponds with this source. This is 65 // only meaningful for certain source types (URL_REQUEST, SOCKET_STREAM). 66 // For the rest, it will return an empty string. 67 std::string GetURL() const; 68 69 uint32 source_id; 70 EntryList entries; 71 size_t num_entries_truncated; 72 73 // List of other sources which contain information relevant to this 74 // source (for example, a url request might depend on the log items 75 // for a connect job and for a socket that were bound to it.) 76 SourceDependencyList dependencies; 77 78 // Holds the count of how many other sources have added this as a 79 // dependent source. When it is 0, it means noone has referenced it so it 80 // can be deleted normally. 81 int reference_count; 82 83 // |is_alive| is set to false once the source has been added to the 84 // tracker's graveyard (it may still be kept around due to a non-zero 85 // reference_count, but it is still considered "dead"). 86 bool is_alive; 87 }; 88 89 typedef std::vector<SourceInfo> SourceInfoList; 90 91 // Interface for consuming a NetLog entry. 92 class SourceTrackerInterface { 93 public: 94 virtual ~SourceTrackerInterface() {} 95 96 virtual void OnAddEntry(const Entry& entry) = 0; 97 98 // Clears all the passively logged data from this tracker. 99 virtual void Clear() = 0; 100 101 // Appends all the captured entries to |out|. The ordering is undefined. 102 virtual void AppendAllEntries(EntryList* out) const = 0; 103 }; 104 105 // This source tracker is intended for TYPE_NONE. All entries go into a 106 // circular buffer, and there is no concept of live/dead requests. 107 class GlobalSourceTracker : public SourceTrackerInterface { 108 public: 109 GlobalSourceTracker(); 110 ~GlobalSourceTracker(); 111 112 // SourceTrackerInterface implementation: 113 virtual void OnAddEntry(const Entry& entry); 114 virtual void Clear(); 115 virtual void AppendAllEntries(EntryList* out) const; 116 117 private: 118 typedef std::deque<Entry> CircularEntryList; 119 CircularEntryList entries_; 120 DISALLOW_COPY_AND_ASSIGN(GlobalSourceTracker); 121 }; 122 123 // This class stores and manages the passively logged information for 124 // URLRequests/SocketStreams/ConnectJobs. 125 class SourceTracker : public SourceTrackerInterface { 126 public: 127 // Creates a SourceTracker that will track at most |max_num_sources|. 128 // Up to |max_graveyard_size| unreferenced sources will be kept around 129 // before deleting them for good. |parent| may be NULL, and points to 130 // the owning PassiveLogCollector (it is used when adding references 131 // to other sources). 132 SourceTracker(size_t max_num_sources, 133 size_t max_graveyard_size, 134 PassiveLogCollector* parent); 135 136 virtual ~SourceTracker(); 137 138 // SourceTrackerInterface implementation: 139 virtual void OnAddEntry(const Entry& entry); 140 virtual void Clear(); 141 virtual void AppendAllEntries(EntryList* out) const; 142 143#ifdef UNIT_TEST 144 // Helper used to inspect the current state by unit-tests. 145 // Retuns a copy of the source infos held by the tracker. 146 SourceInfoList GetAllDeadOrAliveSources(bool is_alive) const { 147 SourceInfoList result; 148 for (SourceIDToInfoMap::const_iterator it = sources_.begin(); 149 it != sources_.end(); ++it) { 150 if (it->second.is_alive == is_alive) 151 result.push_back(it->second); 152 } 153 return result; 154 } 155#endif 156 157 protected: 158 enum Action { 159 ACTION_NONE, 160 ACTION_DELETE, 161 ACTION_MOVE_TO_GRAVEYARD, 162 }; 163 164 // Makes |info| hold a reference to |source|. This way |source| will be 165 // kept alive at least as long as |info|. 166 void AddReferenceToSourceDependency(const net::NetLog::Source& source, 167 SourceInfo* info); 168 169 private: 170 typedef base::hash_map<uint32, SourceInfo> SourceIDToInfoMap; 171 typedef std::deque<uint32> DeletionQueue; 172 173 // Updates |out_info| with the information from |entry|. Returns an action 174 // to perform for this map entry on completion. 175 virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info) = 0; 176 177 // Removes |source_id| from |sources_|. This also releases any references 178 // to dependencies held by this source. 179 void DeleteSourceInfo(uint32 source_id); 180 181 // Adds |source_id| to the FIFO queue (graveyard) for deletion. 182 void AddToDeletionQueue(uint32 source_id); 183 184 // Adds/Releases a reference from the source with ID |source_id|. 185 // Use |offset=-1| to do a release, and |offset=1| for an addref. 186 void AdjustReferenceCountForSource(int offset, uint32 source_id); 187 188 // Releases all the references to sources held by |info|. 189 void ReleaseAllReferencesToDependencies(SourceInfo* info); 190 191 // This map contains all of the sources being tracked by this tracker. 192 // (It includes both the "live" sources, and the "dead" ones.) 193 SourceIDToInfoMap sources_; 194 195 size_t max_num_sources_; 196 size_t max_graveyard_size_; 197 198 // FIFO queue for entries in |sources_| that are no longer alive, and 199 // can be deleted. This buffer is also called "graveyard" elsewhere. We 200 // queue sources for deletion so they can persist a bit longer. 201 DeletionQueue deletion_queue_; 202 203 PassiveLogCollector* parent_; 204 205 DISALLOW_COPY_AND_ASSIGN(SourceTracker); 206 }; 207 208 // Specialization of SourceTracker for handling ConnectJobs. 209 class ConnectJobTracker : public SourceTracker { 210 public: 211 static const size_t kMaxNumSources; 212 static const size_t kMaxGraveyardSize; 213 214 explicit ConnectJobTracker(PassiveLogCollector* parent); 215 216 protected: 217 virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info); 218 private: 219 DISALLOW_COPY_AND_ASSIGN(ConnectJobTracker); 220 }; 221 222 // Specialization of SourceTracker for handling Sockets. 223 class SocketTracker : public SourceTracker { 224 public: 225 static const size_t kMaxNumSources; 226 static const size_t kMaxGraveyardSize; 227 228 SocketTracker(); 229 230 protected: 231 virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info); 232 233 private: 234 DISALLOW_COPY_AND_ASSIGN(SocketTracker); 235 }; 236 237 // Specialization of SourceTracker for handling URLRequest/SocketStream. 238 class RequestTracker : public SourceTracker { 239 public: 240 static const size_t kMaxNumSources; 241 static const size_t kMaxGraveyardSize; 242 243 explicit RequestTracker(PassiveLogCollector* parent); 244 245 protected: 246 virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info); 247 248 private: 249 DISALLOW_COPY_AND_ASSIGN(RequestTracker); 250 }; 251 252 // Specialization of SourceTracker for handling 253 // SOURCE_INIT_PROXY_RESOLVER. 254 class InitProxyResolverTracker : public SourceTracker { 255 public: 256 static const size_t kMaxNumSources; 257 static const size_t kMaxGraveyardSize; 258 259 InitProxyResolverTracker(); 260 261 protected: 262 virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info); 263 264 private: 265 DISALLOW_COPY_AND_ASSIGN(InitProxyResolverTracker); 266 }; 267 268 // Tracks the log entries for the last seen SOURCE_SPDY_SESSION. 269 class SpdySessionTracker : public SourceTracker { 270 public: 271 static const size_t kMaxNumSources; 272 static const size_t kMaxGraveyardSize; 273 274 SpdySessionTracker(); 275 276 protected: 277 virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info); 278 279 private: 280 DISALLOW_COPY_AND_ASSIGN(SpdySessionTracker); 281 }; 282 283 // Tracks the log entries for the last seen SOURCE_HOST_RESOLVER_IMPL_REQUEST. 284 class DNSRequestTracker : public SourceTracker { 285 public: 286 static const size_t kMaxNumSources; 287 static const size_t kMaxGraveyardSize; 288 289 DNSRequestTracker(); 290 291 protected: 292 virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info); 293 294 private: 295 DISALLOW_COPY_AND_ASSIGN(DNSRequestTracker); 296 }; 297 298 // Tracks the log entries for the last seen SOURCE_HOST_RESOLVER_IMPL_JOB. 299 class DNSJobTracker : public SourceTracker { 300 public: 301 static const size_t kMaxNumSources; 302 static const size_t kMaxGraveyardSize; 303 304 DNSJobTracker(); 305 306 protected: 307 virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info); 308 309 private: 310 DISALLOW_COPY_AND_ASSIGN(DNSJobTracker); 311 }; 312 313 PassiveLogCollector(); 314 ~PassiveLogCollector(); 315 316 // Observer implementation: 317 virtual void OnAddEntry(net::NetLog::EventType type, 318 const base::TimeTicks& time, 319 const net::NetLog::Source& source, 320 net::NetLog::EventPhase phase, 321 net::NetLog::EventParameters* params); 322 323 // Returns the tracker to use for sources of type |source_type|, or NULL. 324 SourceTrackerInterface* GetTrackerForSourceType( 325 net::NetLog::SourceType source_type); 326 327 // Clears all of the passively logged data. 328 void Clear(); 329 330 // Fills |out| with the full list of events that have been passively 331 // captured. The list is ordered by capture time. 332 void GetAllCapturedEvents(EntryList* out) const; 333 334 private: 335 FRIEND_TEST_ALL_PREFIXES(PassiveLogCollectorTest, 336 HoldReferenceToDependentSource); 337 FRIEND_TEST_ALL_PREFIXES(PassiveLogCollectorTest, 338 HoldReferenceToDeletedSource); 339 340 GlobalSourceTracker global_source_tracker_; 341 ConnectJobTracker connect_job_tracker_; 342 SocketTracker socket_tracker_; 343 RequestTracker url_request_tracker_; 344 RequestTracker socket_stream_tracker_; 345 InitProxyResolverTracker init_proxy_resolver_tracker_; 346 SpdySessionTracker spdy_session_tracker_; 347 DNSRequestTracker dns_request_tracker_; 348 DNSJobTracker dns_job_tracker_; 349 350 // This array maps each NetLog::SourceType to one of the tracker instances 351 // defined above. Use of this array avoid duplicating the list of trackers 352 // elsewhere. 353 SourceTrackerInterface* trackers_[net::NetLog::SOURCE_COUNT]; 354 355 // The count of how many events have flowed through this log. Used to set the 356 // "order" field on captured events. 357 uint32 num_events_seen_; 358 359 DISALLOW_COPY_AND_ASSIGN(PassiveLogCollector); 360}; 361 362#endif // CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_ 363