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