// Copyright (c) 2012 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 <string>

#include "base/atomicops.h"
#include "base/basictypes.h"
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/observer_list.h"
#include "base/strings/string16.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "net/base/net_export.h"

namespace base {
class DictionaryValue;
class Value;
}

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.
//
// All methods are thread safe, with the exception that no NetLog or
// NetLog::ThreadSafeObserver functions may be called by an observer's
// OnAddEntry() method.  Doing so will result in a deadlock.
//
// For a broader introduction see the design document:
// https://sites.google.com/a/chromium.org/dev/developers/design-documents/network-stack/netlog
class NET_EXPORT NetLog {
 public:
  enum EventType {
#define EVENT_TYPE(label) TYPE_ ## label,
#include "net/base/net_log_event_type_list.h"
#undef EVENT_TYPE
    EVENT_COUNT
  };

  // The 'phase' of an event trace (whether it marks the beginning or end
  // of an event.).
  enum EventPhase {
    PHASE_NONE,
    PHASE_BEGIN,
    PHASE_END,
  };

  // The "source" identifies the entity that generated the log message.
  enum SourceType {
#define SOURCE_TYPE(label) SOURCE_ ## label,
#include "net/base/net_log_source_type_list.h"
#undef SOURCE_TYPE
    SOURCE_COUNT
  };

  // Specifies the granularity of events that should be emitted to the log.
  //
  // Since the LogLevel may be read and set on any thread without locking, it
  // may be possible for an Observer to receive an event or parameters that
  // normally wouldn't be logged at the currently active log level.
  enum LogLevel {
    // Log everything possible, even if it is slow and memory expensive.
    // Includes logging of transferred bytes.
    LOG_ALL,

    // Log all events, but do not include the actual transferred bytes as
    // parameters for bytes sent/received events.
    LOG_ALL_BUT_BYTES,

    // Only log events which are cheap, and don't consume much memory.  This is
    // the default value for observers.
    LOG_BASIC,

    // Don't log any events.
    LOG_NONE,
  };

  // A callback function that return a Value representation of the parameters
  // associated with an event.  If called, it will be called synchonously,
  // so it need not have owning references.  May be called more than once, or
  // not at all.  May return NULL.
  typedef base::Callback<base::Value*(LogLevel)> ParametersCallback;

  // 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 NET_EXPORT Source {
    static const uint32 kInvalidId;

    Source();
    Source(SourceType type, uint32 id);
    bool IsValid() const;

    // Adds the source to a DictionaryValue containing event parameters,
    // using the name "source_dependency".
    void AddToEventParameters(base::DictionaryValue* event_params) const;

    // Returns a callback that returns a dictionary with a single entry
    // named "source_dependecy" that describes |this|.
    ParametersCallback ToEventParametersCallback() const;

    // Attempts to extract a Source from a set of event parameters.  Returns
    // true and writes the result to |source| on success.  Returns false and
    // makes |source| an invalid source on failure.
    // TODO(mmenke):  Long term, we want to remove this.
    static bool FromEventParameters(base::Value* event_params, Source* source);

    SourceType type;
    uint32 id;
  };

  class NET_EXPORT Entry {
   public:
    Entry(EventType type,
          Source source,
          EventPhase phase,
          base::TimeTicks time,
          const ParametersCallback* parameters_callback,
          LogLevel log_level);
    ~Entry();

    EventType type() const { return type_; }
    Source source() const { return source_; }
    EventPhase phase() const { return phase_; }

    // Serializes the specified event to a Value.  The Value also includes the
    // current time.  Caller takes ownership of returned Value.  Takes in a time
    // to allow back-dating entries.
    base::Value* ToValue() const;

    // Returns the parameters as a Value.  Returns NULL if there are no
    // parameters.  Caller takes ownership of returned Value.
    base::Value* ParametersToValue() const;

   private:
    const EventType type_;
    const Source source_;
    const EventPhase phase_;
    const base::TimeTicks time_;
    const ParametersCallback* parameters_callback_;

    // Log level when the event occurred.
    const LogLevel log_level_;

    // It is not safe to copy this class, since |parameters_callback_| may
    // include pointers that become stale immediately after the event is added,
    // even if the code were modified to keep its own copy of the callback.
    DISALLOW_COPY_AND_ASSIGN(Entry);
  };

  // An observer, that must ensure its own thread safety, for events
  // being added to a NetLog.
  class NET_EXPORT ThreadSafeObserver {
   public:
    // Constructs an observer that wants to see network events, with
    // the specified minimum event granularity.  A ThreadSafeObserver can only
    // observe a single NetLog at a time.
    //
    // Observers will be called on the same thread an entry is added on,
    // and are responsible for ensuring their own thread safety.
    //
    // Observers must stop watching a NetLog before either the Observer or the
    // NetLog is destroyed.
    ThreadSafeObserver();

    // Returns the minimum log level for events this observer wants to
    // receive.  Must not be called when not watching a NetLog.
    LogLevel log_level() const;

    // Returns the NetLog we are currently watching, if any.  Returns NULL
    // otherwise.
    NetLog* net_log() const;

    // This method will be called on the thread that the event occurs on.  It
    // is the responsibility of the observer to handle it in a thread safe
    // manner.
    //
    // It is illegal for an Observer to call any NetLog or
    // NetLog::Observer functions in response to a call to OnAddEntry.
    virtual void OnAddEntry(const Entry& entry) = 0;

   protected:
    virtual ~ThreadSafeObserver();

   private:
    friend class NetLog;

    // Both of these values are only modified by the NetLog.
    LogLevel log_level_;
    NetLog* net_log_;

    DISALLOW_COPY_AND_ASSIGN(ThreadSafeObserver);
  };

  NetLog();
  virtual ~NetLog();

  // Emits a global event to the log stream, with its own unique source ID.
  void AddGlobalEntry(EventType type);
  void AddGlobalEntry(EventType type,
                      const NetLog::ParametersCallback& parameters_callback);

  // Returns a unique ID which can be used as a source ID.  All returned IDs
  // will be unique and greater than 0.
  uint32 NextID();

  // Returns the logging level for this NetLog. This is used to avoid computing
  // and saving expensive log entries.
  LogLevel GetLogLevel() const;

  // Adds an observer and sets its log level.  The observer must not be
  // watching any NetLog, including this one, when this is called.
  //
  // Typical observers should specify LOG_BASIC.
  //
  // Observers that need to see the full granularity of events can specify
  // LOG_ALL_BUT_BYTES. However, doing so will have performance consequences.
  //
  // NetLog implementations must call NetLog::OnAddObserver to update the
  // observer's internal state.
  void AddThreadSafeObserver(ThreadSafeObserver* observer, LogLevel log_level);

  // Sets the log level of |observer| to |log_level|.  |observer| must be
  // watching |this|.  NetLog implementations must call
  // NetLog::OnSetObserverLogLevel to update the observer's internal state.
  void SetObserverLogLevel(ThreadSafeObserver* observer, LogLevel log_level);

  // Removes an observer.  NetLog implementations must call
  // NetLog::OnAddObserver to update the observer's internal state.
  //
  // For thread safety reasons, it is recommended that this not be called in
  // an object's destructor.
  void RemoveThreadSafeObserver(ThreadSafeObserver* observer);

  // Converts a time to the string format that the NetLog uses to represent
  // times.  Strings are used since integers may overflow.
  static std::string TickCountToString(const base::TimeTicks& time);

  // Returns a C-String symbolic name for |event_type|.
  static const char* EventTypeToString(EventType event_type);

  // Returns a dictionary that maps event type symbolic names to their enum
  // values.  Caller takes ownership of the returned Value.
  static base::Value* GetEventTypesAsValue();

  // Returns a C-String symbolic name for |source_type|.
  static const char* SourceTypeToString(SourceType source_type);

  // Returns a dictionary that maps source type symbolic names to their enum
  // values.  Caller takes ownership of the returned Value.
  static base::Value* GetSourceTypesAsValue();

  // Returns a C-String symbolic name for |event_phase|.
  static const char* EventPhaseToString(EventPhase event_phase);

  // Returns true if |log_level| indicates the actual bytes transferred should
  // be logged.  This is only the case when |log_level| is LOG_ALL.
  static bool IsLoggingBytes(LogLevel log_level);

  // Returns true if |log_level| indicates that all events should be logged,
  // including frequently occuring ones that may impact performances.
  // This is the case when |log_level| is LOG_ALL or LOG_ALL_BUT_BYTES.
  static bool IsLoggingAllEvents(LogLevel log_level);

  // Creates a ParametersCallback that encapsulates a single integer.
  // Warning: |name| must remain valid for the life of the callback.
  // TODO(mmenke):  Rename this to be consistent with Int64Callback.
  static ParametersCallback IntegerCallback(const char* name, int value);

  // Creates a ParametersCallback that encapsulates a single int64.  The
  // callback will return the value as a StringValue, since IntegerValues
  // only support 32-bit values.
  // Warning: |name| must remain valid for the life of the callback.
  static ParametersCallback Int64Callback(const char* name, int64 value);

  // Creates a ParametersCallback that encapsulates a single UTF8 string.  Takes
  // |value| as a pointer to avoid copying, and emphasize it must be valid for
  // the life of the callback.  |value| may not be NULL.
  // Warning: |name| and |value| must remain valid for the life of the callback.
  static ParametersCallback StringCallback(const char* name,
                                           const std::string* value);

  // Same as above, but takes in a UTF16 string.
  static ParametersCallback StringCallback(const char* name,
                                           const base::string16* value);

 protected:
  // Set the lowest allowed log level, regardless of any Observers.
  void SetBaseLogLevel(LogLevel log_level);

 private:
  friend class BoundNetLog;

  void AddEntry(EventType type,
                const Source& source,
                EventPhase phase,
                const NetLog::ParametersCallback* parameters_callback);

  // Called whenever an observer is added or removed, or has its log level
  // changed.  Must have acquired |lock_| prior to calling.
  void UpdateLogLevel();

  // |lock_| protects access to |observers_|.
  base::Lock lock_;

  // Last assigned source ID.  Incremented to get the next one.
  base::subtle::Atomic32 last_id_;

  // The lowest allowed log level, regardless of any Observers.
  // Normally defaults to LOG_NONE, but can be changed with SetBaseLogLevel
  LogLevel base_log_level_;

  // The current log level.
  base::subtle::Atomic32 effective_log_level_;

  // |lock_| must be acquired whenever reading or writing to this.
  ObserverList<ThreadSafeObserver, true> observers_;

  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 NET_EXPORT BoundNetLog {
 public:
  BoundNetLog() : net_log_(NULL) {}

  // Add a log entry to the NetLog for the bound source.
  void AddEntry(NetLog::EventType type, NetLog::EventPhase phase) const;
  void AddEntry(NetLog::EventType type,
                NetLog::EventPhase phase,
                const NetLog::ParametersCallback& get_parameters) const;

  // Convenience methods that call AddEntry with a fixed "capture phase"
  // (begin, end, or none).
  void BeginEvent(NetLog::EventType type) const;
  void BeginEvent(NetLog::EventType type,
                  const NetLog::ParametersCallback& get_parameters) const;

  void EndEvent(NetLog::EventType type) const;
  void EndEvent(NetLog::EventType type,
                const NetLog::ParametersCallback& get_parameters) const;

  void AddEvent(NetLog::EventType type) const;
  void AddEvent(NetLog::EventType type,
                const NetLog::ParametersCallback& get_parameters) const;

  // Just like AddEvent, except |net_error| is a net error code.  A parameter
  // called "net_error" with the indicated value will be recorded for the event.
  // |net_error| must be negative, and not ERR_IO_PENDING, as it's not a true
  // error.
  void AddEventWithNetErrorCode(NetLog::EventType event_type,
                                int net_error) const;

  // Just like EndEvent, except |net_error| is a net error code.  If it's
  // negative, a parameter called "net_error" with a value of |net_error| is
  // associated with the event.  Otherwise, the end event has no parameters.
  // |net_error| must not be ERR_IO_PENDING, as it's not a true error.
  void EndEventWithNetErrorCode(NetLog::EventType event_type,
                                int net_error) const;

  // Logs a byte transfer event to the NetLog.  Determines whether to log the
  // received bytes or not based on the current logging level.
  void AddByteTransferEvent(NetLog::EventType event_type,
                            int byte_count, const char* bytes) const;

  NetLog::LogLevel GetLogLevel() const;

  // Shortcut for NetLog::IsLoggingBytes(this->GetLogLevel()).
  bool IsLoggingBytes() const;

  // Shortcut for NetLog::IsLoggingAllEvents(this->GetLogLevel()).
  bool IsLoggingAllEvents() 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:
  BoundNetLog(const NetLog::Source& source, NetLog* net_log)
      : source_(source), net_log_(net_log) {
  }

  NetLog::Source source_;
  NetLog* net_log_;
};

}  // namespace net

#endif  // NET_BASE_NET_LOG_H_
