summaryrefslogtreecommitdiffstats
path: root/chrome/browser/net/passive_log_collector.h
blob: 5d46fb37e5404cf7bc3bb3ac02e1ed547a5601a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_
#define CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_
#pragma once

#include <deque>
#include <string>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/hash_tables.h"
#include "base/ref_counted.h"
#include "base/time.h"
#include "chrome/browser/net/chrome_net_log.h"
#include "net/base/net_log.h"

// PassiveLogCollector watches the NetLog event stream, and saves the network
// events for recent requests, in a circular buffer.
//
// This is done so that when a network problem is encountered (performance
// problem, or error), about:net-internals can be opened shortly after the
// problem and it will contain a trace for the problem request.
//
// (This is in contrast to the "active logging" which captures every single
// network event, but requires capturing to have been enabled *prior* to
// encountering the problem. Active capturing is enabled as long as
// about:net-internals is open).
//
// The data captured by PassiveLogCollector is grouped by NetLog::Source, into
// a SourceInfo structure. These in turn are grouped by NetLog::SourceType, and
// owned by a SourceTracker instance for the specific source type.
class PassiveLogCollector : public ChromeNetLog::Observer {
 public:
  // This structure encapsulates all of the parameters of a captured event,
  // including an "order" field that identifies when it was captured relative
  // to other events.
  struct Entry {
    Entry(uint32 order,
          net::NetLog::EventType type,
          const base::TimeTicks& time,
          net::NetLog::Source source,
          net::NetLog::EventPhase phase,
          net::NetLog::EventParameters* params);
    ~Entry();

    uint32 order;
    net::NetLog::EventType type;
    base::TimeTicks time;
    net::NetLog::Source source;
    net::NetLog::EventPhase phase;
    scoped_refptr<net::NetLog::EventParameters> params;
  };

  typedef std::vector<Entry> EntryList;
  typedef std::vector<net::NetLog::Source> SourceDependencyList;

  struct SourceInfo {
    SourceInfo();
    ~SourceInfo();

    // Returns the URL that corresponds with this source. This is
    // only meaningful for certain source types (URL_REQUEST, SOCKET_STREAM).
    // For the rest, it will return an empty string.
    std::string GetURL() const;

    uint32 source_id;
    EntryList entries;
    size_t num_entries_truncated;

    // List of other sources which contain information relevant to this
    // source (for example, a url request might depend on the log items
    // for a connect job and for a socket that were bound to it.)
    SourceDependencyList dependencies;

    // Holds the count of how many other sources have added this as a
    // dependent source. When it is 0, it means noone has referenced it so it
    // can be deleted normally.
    int reference_count;

    // |is_alive| is set to false once the source has been added to the
    // tracker's graveyard (it may still be kept around due to a non-zero
    // reference_count, but it is still considered "dead").
    bool is_alive;
  };

  typedef std::vector<SourceInfo> SourceInfoList;

  // Interface for consuming a NetLog entry.
  class SourceTrackerInterface {
   public:
    virtual ~SourceTrackerInterface() {}

    virtual void OnAddEntry(const Entry& entry) = 0;

    // Clears all the passively logged data from this tracker.
    virtual void Clear() = 0;

    // Appends all the captured entries to |out|. The ordering is undefined.
    virtual void AppendAllEntries(EntryList* out) const = 0;
  };

  // This source tracker is intended for TYPE_NONE. All entries go into a
  // circular buffer, and there is no concept of live/dead requests.
  class GlobalSourceTracker : public SourceTrackerInterface {
   public:
    GlobalSourceTracker();
    ~GlobalSourceTracker();

    // SourceTrackerInterface implementation:
    virtual void OnAddEntry(const Entry& entry);
    virtual void Clear();
    virtual void AppendAllEntries(EntryList* out) const;

   private:
    typedef std::deque<Entry> CircularEntryList;
    CircularEntryList entries_;
    DISALLOW_COPY_AND_ASSIGN(GlobalSourceTracker);
  };

  // This class stores and manages the passively logged information for
  // URLRequests/SocketStreams/ConnectJobs.
  class SourceTracker : public SourceTrackerInterface {
   public:
    // Creates a SourceTracker that will track at most |max_num_sources|.
    // Up to |max_graveyard_size| unreferenced sources will be kept around
    // before deleting them for good. |parent| may be NULL, and points to
    // the owning PassiveLogCollector (it is used when adding references
    // to other sources).
    SourceTracker(size_t max_num_sources,
                  size_t max_graveyard_size,
                  PassiveLogCollector* parent);

    virtual ~SourceTracker();

    // SourceTrackerInterface implementation:
    virtual void OnAddEntry(const Entry& entry);
    virtual void Clear();
    virtual void AppendAllEntries(EntryList* out) const;

#ifdef UNIT_TEST
    // Helper used to inspect the current state by unit-tests.
    // Retuns a copy of the source infos held by the tracker.
    SourceInfoList GetAllDeadOrAliveSources(bool is_alive) const {
      SourceInfoList result;
      for (SourceIDToInfoMap::const_iterator it = sources_.begin();
           it != sources_.end(); ++it) {
        if (it->second.is_alive == is_alive)
          result.push_back(it->second);
      }
      return result;
    }
#endif

   protected:
    enum Action {
      ACTION_NONE,
      ACTION_DELETE,
      ACTION_MOVE_TO_GRAVEYARD,
    };

    // Makes |info| hold a reference to |source|. This way |source| will be
    // kept alive at least as long as |info|.
    void AddReferenceToSourceDependency(const net::NetLog::Source& source,
                                        SourceInfo* info);

   private:
    typedef base::hash_map<uint32, SourceInfo> SourceIDToInfoMap;
    typedef std::deque<uint32> DeletionQueue;

    // Updates |out_info| with the information from |entry|. Returns an action
    // to perform for this map entry on completion.
    virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info) = 0;

    // Removes |source_id| from |sources_|. This also releases any references
    // to dependencies held by this source.
    void DeleteSourceInfo(uint32 source_id);

    // Adds |source_id| to the FIFO queue (graveyard) for deletion.
    void AddToDeletionQueue(uint32 source_id);

    // Removes |source_id| from the |deletion_queue_| container.
    void EraseFromDeletionQueue(uint32 source_id);

    // Adds/Releases a reference from the source with ID |source_id|.
    // Use |offset=-1| to do a release, and |offset=1| for an addref.
    void AdjustReferenceCountForSource(int offset, uint32 source_id);

    // Releases all the references to sources held by |info|.
    void ReleaseAllReferencesToDependencies(SourceInfo* info);

    // This map contains all of the sources being tracked by this tracker.
    // (It includes both the "live" sources, and the "dead" ones.)
    SourceIDToInfoMap sources_;

    size_t max_num_sources_;
    size_t max_graveyard_size_;

    // FIFO queue for entries in |sources_| that are no longer alive, and
    // can be deleted. This buffer is also called "graveyard" elsewhere. We
    // queue sources for deletion so they can persist a bit longer.
    DeletionQueue deletion_queue_;

    PassiveLogCollector* parent_;

    DISALLOW_COPY_AND_ASSIGN(SourceTracker);
  };

  // Specialization of SourceTracker for handling ConnectJobs.
  class ConnectJobTracker : public SourceTracker {
   public:
    static const size_t kMaxNumSources;
    static const size_t kMaxGraveyardSize;

    explicit ConnectJobTracker(PassiveLogCollector* parent);

   protected:
    virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info);
   private:
    DISALLOW_COPY_AND_ASSIGN(ConnectJobTracker);
  };

  // Specialization of SourceTracker for handling Sockets.
  class SocketTracker : public SourceTracker {
   public:
    static const size_t kMaxNumSources;
    static const size_t kMaxGraveyardSize;

    SocketTracker();

   protected:
    virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info);

   private:
    DISALLOW_COPY_AND_ASSIGN(SocketTracker);
  };

  // Specialization of SourceTracker for handling URLRequest/SocketStream.
  class RequestTracker : public SourceTracker {
   public:
    static const size_t kMaxNumSources;
    static const size_t kMaxGraveyardSize;

    explicit RequestTracker(PassiveLogCollector* parent);

   protected:
    virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info);

   private:
    DISALLOW_COPY_AND_ASSIGN(RequestTracker);
  };

  // Specialization of SourceTracker for handling
  // SOURCE_INIT_PROXY_RESOLVER.
  class InitProxyResolverTracker : public SourceTracker {
   public:
    static const size_t kMaxNumSources;
    static const size_t kMaxGraveyardSize;

    InitProxyResolverTracker();

   protected:
    virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info);

   private:
    DISALLOW_COPY_AND_ASSIGN(InitProxyResolverTracker);
  };

  // Tracks the log entries for the last seen SOURCE_SPDY_SESSION.
  class SpdySessionTracker : public SourceTracker {
   public:
    static const size_t kMaxNumSources;
    static const size_t kMaxGraveyardSize;

    SpdySessionTracker();

   protected:
    virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info);

   private:
    DISALLOW_COPY_AND_ASSIGN(SpdySessionTracker);
  };

  // Tracks the log entries for the last seen SOURCE_HOST_RESOLVER_IMPL_REQUEST.
  class DNSRequestTracker : public SourceTracker {
   public:
    static const size_t kMaxNumSources;
    static const size_t kMaxGraveyardSize;

    DNSRequestTracker();

   protected:
    virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info);

   private:
    DISALLOW_COPY_AND_ASSIGN(DNSRequestTracker);
  };

  // Tracks the log entries for the last seen SOURCE_HOST_RESOLVER_IMPL_JOB.
  class DNSJobTracker : public SourceTracker {
   public:
    static const size_t kMaxNumSources;
    static const size_t kMaxGraveyardSize;

    DNSJobTracker();

   protected:
    virtual Action DoAddEntry(const Entry& entry, SourceInfo* out_info);

   private:
    DISALLOW_COPY_AND_ASSIGN(DNSJobTracker);
  };

  PassiveLogCollector();
  ~PassiveLogCollector();

  // Observer implementation:
  virtual void OnAddEntry(net::NetLog::EventType type,
                          const base::TimeTicks& time,
                          const net::NetLog::Source& source,
                          net::NetLog::EventPhase phase,
                          net::NetLog::EventParameters* params);

  // Returns the tracker to use for sources of type |source_type|, or NULL.
  SourceTrackerInterface* GetTrackerForSourceType(
      net::NetLog::SourceType source_type);

  // Clears all of the passively logged data.
  void Clear();

  // Fills |out| with the full list of events that have been passively
  // captured. The list is ordered by capture time.
  void GetAllCapturedEvents(EntryList* out) const;

 private:
  FRIEND_TEST_ALL_PREFIXES(PassiveLogCollectorTest,
                           HoldReferenceToDependentSource);
  FRIEND_TEST_ALL_PREFIXES(PassiveLogCollectorTest,
                           HoldReferenceToDeletedSource);

  GlobalSourceTracker global_source_tracker_;
  ConnectJobTracker connect_job_tracker_;
  SocketTracker socket_tracker_;
  RequestTracker url_request_tracker_;
  RequestTracker socket_stream_tracker_;
  InitProxyResolverTracker init_proxy_resolver_tracker_;
  SpdySessionTracker spdy_session_tracker_;
  DNSRequestTracker dns_request_tracker_;
  DNSJobTracker dns_job_tracker_;

  // This array maps each NetLog::SourceType to one of the tracker instances
  // defined above. Use of this array avoid duplicating the list of trackers
  // elsewhere.
  SourceTrackerInterface* trackers_[net::NetLog::SOURCE_COUNT];

  // The count of how many events have flowed through this log. Used to set the
  // "order" field on captured events.
  uint32 num_events_seen_;

  DISALLOW_COPY_AND_ASSIGN(PassiveLogCollector);
};

#endif  // CHROME_BROWSER_NET_PASSIVE_LOG_COLLECTOR_H_