blob: aeb845a9a6c19c485af082be015bf2acc208ab16 [file] [log] [blame]
// 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_LOG_NET_LOG_H_
#define NET_LOG_NET_LOG_H_
#include <stdint.h>
#include <memory>
#include <string>
#include "base/atomicops.h"
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/strings/string16.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "net/base/net_export.h"
#include "net/log/net_log_capture_mode.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
// SpdySession).
//
// 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/log/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/log/net_log_source_type_list.h"
#undef SOURCE_TYPE
SOURCE_COUNT
};
// A callback that returns a Value representation of the parameters
// associated with an event. If called, it will be called synchronously,
// so it need not have owning references. May be called more than once, or
// not at all. May return NULL.
typedef base::Callback<std::unique_ptr<base::Value>(NetLogCaptureMode)>
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_t kInvalidId;
Source();
Source(SourceType type, uint32_t 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_dependency" 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_t id;
};
struct NET_EXPORT EntryData {
EntryData(EventType type,
Source source,
EventPhase phase,
base::TimeTicks time,
const ParametersCallback* parameters_callback);
~EntryData();
const EventType type;
const Source source;
const EventPhase phase;
const base::TimeTicks time;
const ParametersCallback* const parameters_callback;
};
// An Entry pre-binds EntryData to a capture mode, so observers will observe
// the output of ToValue() and ParametersToValue() at their log capture mode
// rather than the current maximum.
class NET_EXPORT Entry {
public:
Entry(const EntryData* data, NetLogCaptureMode capture_mode);
~Entry();
EventType type() const { return data_->type; }
Source source() const { return data_->source; }
EventPhase phase() const { return data_->phase; }
// Serializes the specified event to a Value. The Value also includes the
// current time. Takes in a time to allow back-dating entries.
std::unique_ptr<base::Value> ToValue() const;
// Returns the parameters as a Value. Returns NULL if there are no
// parameters.
std::unique_ptr<base::Value> ParametersToValue() const;
private:
const EntryData* const data_;
// Log capture mode when the event occurred.
const NetLogCaptureMode capture_mode_;
// 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 is notified of entries added to the NetLog. The
// "ThreadSafe" prefix of the name emphasizes that this observer may be
// called from different threads then the one which added it as an observer.
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 capture mode for events this observer wants to
// receive. It is only valid to call this while observing a NetLog.
NetLogCaptureMode capture_mode() const;
// Returns the NetLog being watched, or nullptr if there is none.
NetLog* net_log() const;
// This method is called whenever an entry (event) was added to the NetLog
// being watched.
//
// OnAddEntry() is invoked on the thread which generated the NetLog entry,
// which may be different from the thread that added this observer.
//
// Whenever OnAddEntry() is invoked, the NetLog's mutex is held. The
// consequences of this are:
//
// * OnAddEntry() will never be called concurrently -- implementations
// can rely on this to avoid needing their own synchronization.
//
// * It is illegal for an observer to call back into the NetLog, or the
// observer itself, as this can result in deadlock or violating
// expectations of non re-entrancy into ThreadSafeObserver.
virtual void OnAddEntry(const Entry& entry) = 0;
protected:
virtual ~ThreadSafeObserver();
private:
friend class NetLog;
void OnAddEntryData(const EntryData& entry_data);
// Both of these values are only modified by the NetLog.
NetLogCaptureMode capture_mode_;
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_t NextID();
// Returns true if there are any observers attached to the NetLog. This can be
// used as an optimization to avoid emitting log entries when there is no
// chance that the data will be consumed.
bool IsCapturing() const;
// Adds an observer and sets its log capture mode. The observer must not be
// watching any NetLog, including this one, when this is called.
//
// DEPRECATED: The ability to watch the netlog stream is being phased out
// (crbug.com/472693) as it can be misused in production code. Please consult
// with a net/log OWNER before introducing a new dependency on this.
void DeprecatedAddObserver(ThreadSafeObserver* observer,
NetLogCaptureMode capture_mode);
// Sets the log capture mode of |observer| to |capture_mode|. |observer| must
// be watching |this|. NetLog implementations must call
// NetLog::OnSetObserverCaptureMode to update the observer's internal state.
void SetObserverCaptureMode(ThreadSafeObserver* observer,
NetLogCaptureMode capture_mode);
// Removes an observer.
//
// For thread safety reasons, it is recommended that this not be called in
// an object's destructor.
//
// DEPRECATED: The ability to watch the netlog stream is being phased out
// (crbug.com/472693) as it can be misused in production code. Please consult
// with a net/log OWNER before introducing a new dependency on this.
void DeprecatedRemoveObserver(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);
// Creates a ParametersCallback that encapsulates a single bool.
// Warning: |name| must remain valid for the life of the callback.
static ParametersCallback BoolCallback(const char* name, bool value);
// Warning: |name| must remain valid for the life of the callback.
static ParametersCallback IntCallback(const char* name, int value);
// Creates a ParametersCallback that encapsulates a single int64_t. 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_t 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);
static ParametersCallback StringCallback(const char* name, const char* value);
// Same as above, but takes in a UTF16 string.
static ParametersCallback StringCallback(const char* name,
const base::string16* value);
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, to update
// |has_observers_|. Must have acquired |lock_| prior to calling.
void UpdateIsCapturing();
// |lock_| protects access to |observers_|.
base::Lock lock_;
// Last assigned source ID. Incremented to get the next one.
base::subtle::Atomic32 last_id_;
// |is_capturing_| will be 0 when there are no observers watching the NetLog,
// 1 otherwise. Note that this is stored as an Atomic32 rather than a boolean
// so it can be accessed without needing a lock.
base::subtle::Atomic32 is_capturing_;
// |lock_| must be acquired whenever reading or writing to this.
base::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) {}
~BoundNetLog();
// 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;
bool IsCapturing() 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:
// TODO(eroman): Temporary until crbug.com/467797 is solved.
enum Liveness {
ALIVE = 0xCA11AB13,
DEAD = 0xDEADBEEF,
};
BoundNetLog(const NetLog::Source& source, NetLog* net_log)
: source_(source), net_log_(net_log) {}
// TODO(eroman): Temporary until crbug.com/467797 is solved.
void CrashIfInvalid() const;
NetLog::Source source_;
NetLog* net_log_;
// TODO(eroman): Temporary until crbug.com/467797 is solved.
Liveness liveness_ = ALIVE;
};
} // namespace net
#endif // NET_LOG_NET_LOG_H_