// 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 NET_BASE_NET_LOG_H_ #define NET_BASE_NET_LOG_H_ #include #include #include "base/scoped_ptr.h" #include "base/time.h" #include "net/base/net_log.h" namespace net { // NetLog is the destination for log messages generated by the network stack. // Each log message has a "source" field which identifies the specific entity // that generated the message (for example, which URLRequest or which // SocketStream). // // To avoid needing to pass in the "source id" to the logging functions, NetLog // is usually accessed through a BoundNetLog, which will always pass in a // specific source ID. // // Note that NetLog is NOT THREADSAFE. class NetLog { public: // TODO(eroman): Really, EventType and EventPhase should be // Event::Type and Event::Phase, to be consisent with Entry. // But there lots of consumers to change! enum EventType { #define EVENT_TYPE(label) TYPE_ ## label, #include "net/base/net_log_event_type_list.h" #undef EVENT_TYPE }; // The 'phase' of an event trace (whether it marks the beginning or end // of an event.). enum EventPhase { PHASE_NONE, PHASE_BEGIN, PHASE_END, }; struct Event { Event(EventType type, EventPhase phase) : type(type), phase(phase) {} Event() {} EventType type; EventPhase phase; }; // The "source" identifies the entity that generated the log message. enum SourceType { SOURCE_NONE, SOURCE_URL_REQUEST, SOURCE_SOCKET_STREAM, SOURCE_INIT_PROXY_RESOLVER, SOURCE_CONNECT_JOB, }; // Identifies the entity that generated this log. The |id| field should // uniquely identify the source, and is used by log observers to infer // message groupings. Can use NetLog::NextID() to create unique IDs. struct Source { Source() : type(SOURCE_NONE), id(-1) {} Source(SourceType type, int id) : type(type), id(id) {} SourceType type; int id; }; // TODO(eroman): generalize the entries so events can specify multiple // parameters, and TYPE_STRING is rarely needed. struct Entry { enum Type { // This entry describes an event trace. TYPE_EVENT, // This entry describes a network error code that was returned. TYPE_ERROR_CODE, // This entry is a free-form std::string. TYPE_STRING, // This entry is a C-string literal. TYPE_STRING_LITERAL, }; Source source; Type type; base::TimeTicks time; // The following is basically a union, only one of them should be // used depending on what |type| is. Event event; // valid when (type == TYPE_EVENT). int error_code; // valid when (type == TYPE_ERROR_CODE). std::string string; // valid when (type == TYPE_STRING). const char* literal; // valid when (type == TYPE_STRING_LITERAL). }; NetLog() {} virtual ~NetLog() {} // Adds a message to the log. virtual void AddEntry(const Entry& entry) = 0; // Returns a unique ID which can be used as a source ID. virtual int NextID() = 0; // Returns true if more complicated messages should be sent to the log. // TODO(eroman): This is a carry-over from refactoring; figure out // something better. virtual bool HasListener() const = 0; // Returns a C-String symbolic name for |event_type|. static const char* EventTypeToString(EventType event_type); // Returns a list of all the available EventTypes. static std::vector GetAllEventTypes(); private: DISALLOW_COPY_AND_ASSIGN(NetLog); }; // Helper that binds a Source to a NetLog, and exposes convenience methods to // output log messages without needing to pass in the source. class BoundNetLog { public: BoundNetLog() : net_log_(NULL) {} // TODO(eroman): This is a complete hack to allow passing in NULL in // place of a BoundNetLog. I added this while refactoring to simplify the // task of updating all the callers. BoundNetLog(int) : net_log_(NULL) {} BoundNetLog(const NetLog::Source& source, NetLog* net_log) : source_(source), net_log_(net_log) { } void AddEntry(const NetLog::Entry& entry) const; // Convenience methods that call through to the NetLog, passing in the // currently bound source. void AddEvent(NetLog::EventType event_type) const; bool HasListener() const; void BeginEvent(NetLog::EventType event_type) const; void BeginEventWithString(NetLog::EventType event_type, const std::string& string) const; void AddEventWithInteger(NetLog::EventType event_type, int integer) const; void EndEvent(NetLog::EventType event_type) const; void AddStringLiteral(const char* literal) const; void AddString(const std::string& string) const; void AddErrorCode(int error) const; // Helper to create a BoundNetLog given a NetLog and a SourceType. Takes care // of creating a unique source ID, and handles the case of NULL net_log. static BoundNetLog Make(NetLog* net_log, NetLog::SourceType source_type); const NetLog::Source& source() const { return source_; } NetLog* net_log() const { return net_log_; } private: NetLog::Source source_; NetLog* net_log_; }; // CapturingNetLog is an implementation of NetLog that saves messages to a // bounded buffer. class CapturingNetLog : public NetLog { public: // Ordered set of entries that were logged. typedef std::vector EntryList; enum { kUnbounded = -1 }; // Creates a CapturingNetLog that logs a maximum of |max_num_entries| // messages. explicit CapturingNetLog(size_t max_num_entries) : next_id_(0), max_num_entries_(max_num_entries) {} // NetLog implementation: virtual void AddEntry(const Entry& entry); virtual int NextID(); virtual bool HasListener() const { return true; } // Returns the list of all entries in the log. const EntryList& entries() const { return entries_; } void Clear(); private: int next_id_; size_t max_num_entries_; EntryList entries_; DISALLOW_COPY_AND_ASSIGN(CapturingNetLog); }; // Helper class that exposes a similar API as BoundNetLog, but uses a // CapturingNetLog rather than the more generic NetLog. // // CapturingBoundNetLog can easily be converted to a BoundNetLog using the // bound() method. class CapturingBoundNetLog { public: CapturingBoundNetLog(const NetLog::Source& source, CapturingNetLog* net_log) : source_(source), capturing_net_log_(net_log) { } explicit CapturingBoundNetLog(size_t max_num_entries) : capturing_net_log_(new CapturingNetLog(max_num_entries)) {} // The returned BoundNetLog is only valid while |this| is alive. BoundNetLog bound() const { return BoundNetLog(source_, capturing_net_log_.get()); } // Returns the list of all entries in the log. const CapturingNetLog::EntryList& entries() const { return capturing_net_log_->entries(); } void Clear(); // Sends all of captured messages to |net_log|, using the same source ID // as |net_log|. void AppendTo(const BoundNetLog& net_log) const; private: NetLog::Source source_; scoped_ptr capturing_net_log_; DISALLOW_COPY_AND_ASSIGN(CapturingBoundNetLog); }; } // namespace net #endif // NET_BASE_NET_LOG_H_