Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2012 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 #include "net/base/net_log.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/logging.h"
      9 #include "base/strings/string_number_conversions.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "base/time/time.h"
     12 #include "base/values.h"
     13 #include "net/base/net_errors.h"
     14 
     15 namespace net {
     16 
     17 namespace {
     18 
     19 // Returns parameters for logging data transferred events. Includes number of
     20 // bytes transferred and, if the log level indicates bytes should be logged and
     21 // |byte_count| > 0, the bytes themselves.  The bytes are hex-encoded, since
     22 // base::StringValue only supports UTF-8.
     23 base::Value* BytesTransferredCallback(int byte_count,
     24                                       const char* bytes,
     25                                       NetLog::LogLevel log_level) {
     26   base::DictionaryValue* dict = new base::DictionaryValue();
     27   dict->SetInteger("byte_count", byte_count);
     28   if (NetLog::IsLoggingBytes(log_level) && byte_count > 0)
     29     dict->SetString("hex_encoded_bytes", base::HexEncode(bytes, byte_count));
     30   return dict;
     31 }
     32 
     33 base::Value* SourceEventParametersCallback(const NetLog::Source source,
     34                                            NetLog::LogLevel /* log_level */) {
     35   if (!source.IsValid())
     36     return NULL;
     37   base::DictionaryValue* event_params = new base::DictionaryValue();
     38   source.AddToEventParameters(event_params);
     39   return event_params;
     40 }
     41 
     42 base::Value* NetLogIntegerCallback(const char* name,
     43                                    int value,
     44                                    NetLog::LogLevel /* log_level */) {
     45   base::DictionaryValue* event_params = new base::DictionaryValue();
     46   event_params->SetInteger(name, value);
     47   return event_params;
     48 }
     49 
     50 base::Value* NetLogInt64Callback(const char* name,
     51                                  int64 value,
     52                                  NetLog::LogLevel /* log_level */) {
     53   base::DictionaryValue* event_params = new base::DictionaryValue();
     54   event_params->SetString(name, base::Int64ToString(value));
     55   return event_params;
     56 }
     57 
     58 base::Value* NetLogStringCallback(const char* name,
     59                                   const std::string* value,
     60                                   NetLog::LogLevel /* log_level */) {
     61   base::DictionaryValue* event_params = new base::DictionaryValue();
     62   event_params->SetString(name, *value);
     63   return event_params;
     64 }
     65 
     66 base::Value* NetLogString16Callback(const char* name,
     67                                     const base::string16* value,
     68                                     NetLog::LogLevel /* log_level */) {
     69   base::DictionaryValue* event_params = new base::DictionaryValue();
     70   event_params->SetString(name, *value);
     71   return event_params;
     72 }
     73 
     74 }  // namespace
     75 
     76 // LoadTimingInfo requires this be 0.
     77 const uint32 NetLog::Source::kInvalidId = 0;
     78 
     79 NetLog::Source::Source() : type(SOURCE_NONE), id(kInvalidId) {
     80 }
     81 
     82 NetLog::Source::Source(SourceType type, uint32 id) : type(type), id(id) {
     83 }
     84 
     85 bool NetLog::Source::IsValid() const {
     86   return id != kInvalidId;
     87 }
     88 
     89 void NetLog::Source::AddToEventParameters(
     90     base::DictionaryValue* event_params) const {
     91   base::DictionaryValue* dict = new base::DictionaryValue();
     92   dict->SetInteger("type", static_cast<int>(type));
     93   dict->SetInteger("id", static_cast<int>(id));
     94   event_params->Set("source_dependency", dict);
     95 }
     96 
     97 NetLog::ParametersCallback NetLog::Source::ToEventParametersCallback() const {
     98   return base::Bind(&SourceEventParametersCallback, *this);
     99 }
    100 
    101 // static
    102 bool NetLog::Source::FromEventParameters(base::Value* event_params,
    103                                          Source* source) {
    104   base::DictionaryValue* dict;
    105   base::DictionaryValue* source_dict;
    106   int source_id;
    107   int source_type;
    108   if (!event_params ||
    109       !event_params->GetAsDictionary(&dict) ||
    110       !dict->GetDictionary("source_dependency", &source_dict) ||
    111       !source_dict->GetInteger("id", &source_id) ||
    112       !source_dict->GetInteger("type", &source_type)) {
    113     *source = Source();
    114     return false;
    115   }
    116 
    117   DCHECK_LE(0, source_id);
    118   DCHECK_LT(source_type, NetLog::SOURCE_COUNT);
    119   *source = Source(static_cast<SourceType>(source_type), source_id);
    120   return true;
    121 }
    122 
    123 base::Value* NetLog::Entry::ToValue() const {
    124   base::DictionaryValue* entry_dict(new base::DictionaryValue());
    125 
    126   entry_dict->SetString("time", TickCountToString(time_));
    127 
    128   // Set the entry source.
    129   base::DictionaryValue* source_dict = new base::DictionaryValue();
    130   source_dict->SetInteger("id", source_.id);
    131   source_dict->SetInteger("type", static_cast<int>(source_.type));
    132   entry_dict->Set("source", source_dict);
    133 
    134   // Set the event info.
    135   entry_dict->SetInteger("type", static_cast<int>(type_));
    136   entry_dict->SetInteger("phase", static_cast<int>(phase_));
    137 
    138   // Set the event-specific parameters.
    139   if (parameters_callback_) {
    140     base::Value* value = parameters_callback_->Run(log_level_);
    141     if (value)
    142       entry_dict->Set("params", value);
    143   }
    144 
    145   return entry_dict;
    146 }
    147 
    148 base::Value* NetLog::Entry::ParametersToValue() const {
    149   if (parameters_callback_)
    150     return parameters_callback_->Run(log_level_);
    151   return NULL;
    152 }
    153 
    154 NetLog::Entry::Entry(
    155     EventType type,
    156     Source source,
    157     EventPhase phase,
    158     base::TimeTicks time,
    159     const ParametersCallback* parameters_callback,
    160     LogLevel log_level)
    161     : type_(type),
    162       source_(source),
    163       phase_(phase),
    164       time_(time),
    165       parameters_callback_(parameters_callback),
    166       log_level_(log_level) {
    167 };
    168 
    169 NetLog::Entry::~Entry() {
    170 }
    171 
    172 NetLog::ThreadSafeObserver::ThreadSafeObserver() : log_level_(LOG_BASIC),
    173                                                    net_log_(NULL) {
    174 }
    175 
    176 NetLog::ThreadSafeObserver::~ThreadSafeObserver() {
    177   // Make sure we aren't watching a NetLog on destruction.  Because the NetLog
    178   // may pass events to each observer on multiple threads, we cannot safely
    179   // stop watching a NetLog automatically from a parent class.
    180   DCHECK(!net_log_);
    181 }
    182 
    183 NetLog::LogLevel NetLog::ThreadSafeObserver::log_level() const {
    184   DCHECK(net_log_);
    185   return log_level_;
    186 }
    187 
    188 NetLog* NetLog::ThreadSafeObserver::net_log() const {
    189   return net_log_;
    190 }
    191 
    192 NetLog::NetLog()
    193     : last_id_(0),
    194       base_log_level_(LOG_NONE),
    195       effective_log_level_(LOG_NONE) {
    196 }
    197 
    198 NetLog::~NetLog() {
    199 }
    200 
    201 void NetLog::AddGlobalEntry(EventType type) {
    202   AddEntry(type,
    203            Source(net::NetLog::SOURCE_NONE, NextID()),
    204            net::NetLog::PHASE_NONE,
    205            NULL);
    206 }
    207 
    208 void NetLog::AddGlobalEntry(
    209     EventType type,
    210     const NetLog::ParametersCallback& parameters_callback) {
    211   AddEntry(type,
    212            Source(net::NetLog::SOURCE_NONE, NextID()),
    213            net::NetLog::PHASE_NONE,
    214            &parameters_callback);
    215 }
    216 
    217 uint32 NetLog::NextID() {
    218   return base::subtle::NoBarrier_AtomicIncrement(&last_id_, 1);
    219 }
    220 
    221 void NetLog::SetBaseLogLevel(LogLevel log_level) {
    222   base::AutoLock lock(lock_);
    223   base_log_level_ = log_level;
    224 
    225   UpdateLogLevel();
    226 }
    227 
    228 NetLog::LogLevel NetLog::GetLogLevel() const {
    229   base::subtle::Atomic32 log_level =
    230       base::subtle::NoBarrier_Load(&effective_log_level_);
    231   return static_cast<net::NetLog::LogLevel>(log_level);
    232 }
    233 
    234 void NetLog::AddThreadSafeObserver(
    235     net::NetLog::ThreadSafeObserver* observer,
    236     LogLevel log_level) {
    237   base::AutoLock lock(lock_);
    238 
    239   DCHECK(!observer->net_log_);
    240   observers_.AddObserver(observer);
    241   observer->net_log_ = this;
    242   observer->log_level_ = log_level;
    243   UpdateLogLevel();
    244 }
    245 
    246 void NetLog::SetObserverLogLevel(
    247     net::NetLog::ThreadSafeObserver* observer,
    248     LogLevel log_level) {
    249   base::AutoLock lock(lock_);
    250 
    251   DCHECK(observers_.HasObserver(observer));
    252   DCHECK_EQ(this, observer->net_log_);
    253   observer->log_level_ = log_level;
    254   UpdateLogLevel();
    255 }
    256 
    257 void NetLog::RemoveThreadSafeObserver(
    258     net::NetLog::ThreadSafeObserver* observer) {
    259   base::AutoLock lock(lock_);
    260 
    261   DCHECK(observers_.HasObserver(observer));
    262   DCHECK_EQ(this, observer->net_log_);
    263   observers_.RemoveObserver(observer);
    264   observer->net_log_ = NULL;
    265   UpdateLogLevel();
    266 }
    267 
    268 void NetLog::UpdateLogLevel() {
    269   lock_.AssertAcquired();
    270 
    271   // Look through all the observers and find the finest granularity
    272   // log level (higher values of the enum imply *lower* log levels).
    273   LogLevel new_effective_log_level = base_log_level_;
    274   ObserverListBase<ThreadSafeObserver>::Iterator it(observers_);
    275   ThreadSafeObserver* observer;
    276   while ((observer = it.GetNext()) != NULL) {
    277     new_effective_log_level =
    278         std::min(new_effective_log_level, observer->log_level());
    279   }
    280   base::subtle::NoBarrier_Store(&effective_log_level_,
    281                                 new_effective_log_level);
    282 }
    283 
    284 // static
    285 std::string NetLog::TickCountToString(const base::TimeTicks& time) {
    286   int64 delta_time = (time - base::TimeTicks()).InMilliseconds();
    287   return base::Int64ToString(delta_time);
    288 }
    289 
    290 // static
    291 const char* NetLog::EventTypeToString(EventType event) {
    292   switch (event) {
    293 #define EVENT_TYPE(label) case TYPE_ ## label: return #label;
    294 #include "net/base/net_log_event_type_list.h"
    295 #undef EVENT_TYPE
    296     default:
    297       NOTREACHED();
    298       return NULL;
    299   }
    300 }
    301 
    302 // static
    303 base::Value* NetLog::GetEventTypesAsValue() {
    304   base::DictionaryValue* dict = new base::DictionaryValue();
    305   for (int i = 0; i < EVENT_COUNT; ++i) {
    306     dict->SetInteger(EventTypeToString(static_cast<EventType>(i)), i);
    307   }
    308   return dict;
    309 }
    310 
    311 // static
    312 const char* NetLog::SourceTypeToString(SourceType source) {
    313   switch (source) {
    314 #define SOURCE_TYPE(label) case SOURCE_ ## label: return #label;
    315 #include "net/base/net_log_source_type_list.h"
    316 #undef SOURCE_TYPE
    317     default:
    318       NOTREACHED();
    319       return NULL;
    320   }
    321 }
    322 
    323 // static
    324 base::Value* NetLog::GetSourceTypesAsValue() {
    325   base::DictionaryValue* dict = new base::DictionaryValue();
    326   for (int i = 0; i < SOURCE_COUNT; ++i) {
    327     dict->SetInteger(SourceTypeToString(static_cast<SourceType>(i)), i);
    328   }
    329   return dict;
    330 }
    331 
    332 // static
    333 const char* NetLog::EventPhaseToString(EventPhase phase) {
    334   switch (phase) {
    335     case PHASE_BEGIN:
    336       return "PHASE_BEGIN";
    337     case PHASE_END:
    338       return "PHASE_END";
    339     case PHASE_NONE:
    340       return "PHASE_NONE";
    341   }
    342   NOTREACHED();
    343   return NULL;
    344 }
    345 
    346 // static
    347 bool NetLog::IsLoggingBytes(LogLevel log_level) {
    348   return log_level == NetLog::LOG_ALL;
    349 }
    350 
    351 // static
    352 bool NetLog::IsLoggingAllEvents(LogLevel log_level) {
    353   return log_level <= NetLog::LOG_ALL_BUT_BYTES;
    354 }
    355 
    356 // static
    357 NetLog::ParametersCallback NetLog::IntegerCallback(const char* name,
    358                                                    int value) {
    359   return base::Bind(&NetLogIntegerCallback, name, value);
    360 }
    361 
    362 // static
    363 NetLog::ParametersCallback NetLog::Int64Callback(const char* name,
    364                                                  int64 value) {
    365   return base::Bind(&NetLogInt64Callback, name, value);
    366 }
    367 
    368 // static
    369 NetLog::ParametersCallback NetLog::StringCallback(const char* name,
    370                                                   const std::string* value) {
    371   DCHECK(value);
    372   return base::Bind(&NetLogStringCallback, name, value);
    373 }
    374 
    375 // static
    376 NetLog::ParametersCallback NetLog::StringCallback(const char* name,
    377                                                   const base::string16* value) {
    378   DCHECK(value);
    379   return base::Bind(&NetLogString16Callback, name, value);
    380 }
    381 
    382 void NetLog::AddEntry(EventType type,
    383                       const Source& source,
    384                       EventPhase phase,
    385                       const NetLog::ParametersCallback* parameters_callback) {
    386   LogLevel log_level = GetLogLevel();
    387   if (log_level == LOG_NONE)
    388     return;
    389   Entry entry(type, source, phase, base::TimeTicks::Now(),
    390               parameters_callback, log_level);
    391 
    392   // Notify all of the log observers.
    393   base::AutoLock lock(lock_);
    394   FOR_EACH_OBSERVER(ThreadSafeObserver, observers_, OnAddEntry(entry));
    395 }
    396 
    397 void BoundNetLog::AddEntry(NetLog::EventType type,
    398                            NetLog::EventPhase phase) const {
    399   if (!net_log_)
    400     return;
    401   net_log_->AddEntry(type, source_, phase, NULL);
    402 }
    403 
    404 void BoundNetLog::AddEntry(
    405     NetLog::EventType type,
    406     NetLog::EventPhase phase,
    407     const NetLog::ParametersCallback& get_parameters) const {
    408   if (!net_log_)
    409     return;
    410   net_log_->AddEntry(type, source_, phase, &get_parameters);
    411 }
    412 
    413 void BoundNetLog::AddEvent(NetLog::EventType type) const {
    414   AddEntry(type, NetLog::PHASE_NONE);
    415 }
    416 
    417 void BoundNetLog::AddEvent(
    418     NetLog::EventType type,
    419     const NetLog::ParametersCallback& get_parameters) const {
    420   AddEntry(type, NetLog::PHASE_NONE, get_parameters);
    421 }
    422 
    423 void BoundNetLog::BeginEvent(NetLog::EventType type) const {
    424   AddEntry(type, NetLog::PHASE_BEGIN);
    425 }
    426 
    427 void BoundNetLog::BeginEvent(
    428     NetLog::EventType type,
    429     const NetLog::ParametersCallback& get_parameters) const {
    430   AddEntry(type, NetLog::PHASE_BEGIN, get_parameters);
    431 }
    432 
    433 void BoundNetLog::EndEvent(NetLog::EventType type) const {
    434   AddEntry(type, NetLog::PHASE_END);
    435 }
    436 
    437 void BoundNetLog::EndEvent(
    438     NetLog::EventType type,
    439     const NetLog::ParametersCallback& get_parameters) const {
    440   AddEntry(type, NetLog::PHASE_END, get_parameters);
    441 }
    442 
    443 void BoundNetLog::AddEventWithNetErrorCode(NetLog::EventType event_type,
    444                                            int net_error) const {
    445   DCHECK_NE(ERR_IO_PENDING, net_error);
    446   if (net_error >= 0) {
    447     AddEvent(event_type);
    448   } else {
    449     AddEvent(event_type, NetLog::IntegerCallback("net_error", net_error));
    450   }
    451 }
    452 
    453 void BoundNetLog::EndEventWithNetErrorCode(NetLog::EventType event_type,
    454                                            int net_error) const {
    455   DCHECK_NE(ERR_IO_PENDING, net_error);
    456   if (net_error >= 0) {
    457     EndEvent(event_type);
    458   } else {
    459     EndEvent(event_type, NetLog::IntegerCallback("net_error", net_error));
    460   }
    461 }
    462 
    463 void BoundNetLog::AddByteTransferEvent(NetLog::EventType event_type,
    464                                        int byte_count,
    465                                        const char* bytes) const {
    466   AddEvent(event_type, base::Bind(BytesTransferredCallback, byte_count, bytes));
    467 }
    468 
    469 NetLog::LogLevel BoundNetLog::GetLogLevel() const {
    470   if (net_log_)
    471     return net_log_->GetLogLevel();
    472   return NetLog::LOG_BASIC;
    473 }
    474 
    475 bool BoundNetLog::IsLoggingBytes() const {
    476   return NetLog::IsLoggingBytes(GetLogLevel());
    477 }
    478 
    479 bool BoundNetLog::IsLoggingAllEvents() const {
    480   return NetLog::IsLoggingAllEvents(GetLogLevel());
    481 }
    482 
    483 // static
    484 BoundNetLog BoundNetLog::Make(NetLog* net_log,
    485                               NetLog::SourceType source_type) {
    486   if (!net_log)
    487     return BoundNetLog();
    488 
    489   NetLog::Source source(source_type, net_log->NextID());
    490   return BoundNetLog(source, net_log);
    491 }
    492 
    493 }  // namespace net
    494