net_log.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/string_number_conversions.h" 10#include "base/time.h" 11#include "base/utf_string_conversions.h" 12#include "base/values.h" 13#include "net/base/net_errors.h" 14 15namespace net { 16 17namespace { 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. 23Value* BytesTransferredCallback(int byte_count, 24 const char* bytes, 25 NetLog::LogLevel log_level) { 26 DictionaryValue* dict = new 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 33Value* SourceEventParametersCallback(const NetLog::Source source, 34 NetLog::LogLevel /* log_level */) { 35 if (!source.IsValid()) 36 return NULL; 37 DictionaryValue* event_params = new DictionaryValue(); 38 source.AddToEventParameters(event_params); 39 return event_params; 40} 41 42Value* NetLogIntegerCallback(const char* name, 43 int value, 44 NetLog::LogLevel /* log_level */) { 45 DictionaryValue* event_params = new DictionaryValue(); 46 event_params->SetInteger(name, value); 47 return event_params; 48} 49 50Value* NetLogInt64Callback(const char* name, 51 int64 value, 52 NetLog::LogLevel /* log_level */) { 53 DictionaryValue* event_params = new DictionaryValue(); 54 event_params->SetString(name, base::Int64ToString(value)); 55 return event_params; 56} 57 58Value* NetLogStringCallback(const char* name, 59 const std::string* value, 60 NetLog::LogLevel /* log_level */) { 61 DictionaryValue* event_params = new DictionaryValue(); 62 event_params->SetString(name, *value); 63 return event_params; 64} 65 66Value* NetLogString16Callback(const char* name, 67 const string16* value, 68 NetLog::LogLevel /* log_level */) { 69 DictionaryValue* event_params = new DictionaryValue(); 70 event_params->SetString(name, *value); 71 return event_params; 72} 73 74} // namespace 75 76// LoadTimingInfo requires this be 0. 77const uint32 NetLog::Source::kInvalidId = 0; 78 79NetLog::Source::Source() : type(SOURCE_NONE), id(kInvalidId) { 80} 81 82NetLog::Source::Source(SourceType type, uint32 id) : type(type), id(id) { 83} 84 85bool NetLog::Source::IsValid() const { 86 return id != kInvalidId; 87} 88 89void NetLog::Source::AddToEventParameters(DictionaryValue* event_params) const { 90 DictionaryValue* dict = new DictionaryValue(); 91 dict->SetInteger("type", static_cast<int>(type)); 92 dict->SetInteger("id", static_cast<int>(id)); 93 event_params->Set("source_dependency", dict); 94} 95 96NetLog::ParametersCallback NetLog::Source::ToEventParametersCallback() const { 97 return base::Bind(&SourceEventParametersCallback, *this); 98} 99 100// static 101bool NetLog::Source::FromEventParameters(Value* event_params, Source* source) { 102 DictionaryValue* dict; 103 DictionaryValue* source_dict; 104 int source_id; 105 int source_type; 106 if (!event_params || 107 !event_params->GetAsDictionary(&dict) || 108 !dict->GetDictionary("source_dependency", &source_dict) || 109 !source_dict->GetInteger("id", &source_id) || 110 !source_dict->GetInteger("type", &source_type)) { 111 *source = Source(); 112 return false; 113 } 114 115 DCHECK_LE(0, source_id); 116 DCHECK_LT(source_type, NetLog::SOURCE_COUNT); 117 *source = Source(static_cast<SourceType>(source_type), source_id); 118 return true; 119} 120 121Value* NetLog::Entry::ToValue() const { 122 DictionaryValue* entry_dict(new DictionaryValue()); 123 124 entry_dict->SetString("time", TickCountToString(time_)); 125 126 // Set the entry source. 127 DictionaryValue* source_dict = new DictionaryValue(); 128 source_dict->SetInteger("id", source_.id); 129 source_dict->SetInteger("type", static_cast<int>(source_.type)); 130 entry_dict->Set("source", source_dict); 131 132 // Set the event info. 133 entry_dict->SetInteger("type", static_cast<int>(type_)); 134 entry_dict->SetInteger("phase", static_cast<int>(phase_)); 135 136 // Set the event-specific parameters. 137 if (parameters_callback_) { 138 Value* value = parameters_callback_->Run(log_level_); 139 if (value) 140 entry_dict->Set("params", value); 141 } 142 143 return entry_dict; 144} 145 146Value* NetLog::Entry::ParametersToValue() const { 147 if (parameters_callback_) 148 return parameters_callback_->Run(log_level_); 149 return NULL; 150} 151 152NetLog::Entry::Entry( 153 EventType type, 154 Source source, 155 EventPhase phase, 156 base::TimeTicks time, 157 const ParametersCallback* parameters_callback, 158 LogLevel log_level) 159 : type_(type), 160 source_(source), 161 phase_(phase), 162 time_(time), 163 parameters_callback_(parameters_callback), 164 log_level_(log_level) { 165}; 166 167NetLog::Entry::~Entry() { 168} 169 170NetLog::ThreadSafeObserver::ThreadSafeObserver() : log_level_(LOG_BASIC), 171 net_log_(NULL) { 172} 173 174NetLog::ThreadSafeObserver::~ThreadSafeObserver() { 175 // Make sure we aren't watching a NetLog on destruction. Because the NetLog 176 // may pass events to each observer on multiple threads, we cannot safely 177 // stop watching a NetLog automatically from a parent class. 178 DCHECK(!net_log_); 179} 180 181NetLog::LogLevel NetLog::ThreadSafeObserver::log_level() const { 182 DCHECK(net_log_); 183 return log_level_; 184} 185 186NetLog* NetLog::ThreadSafeObserver::net_log() const { 187 return net_log_; 188} 189 190void NetLog::AddGlobalEntry(EventType type) { 191 AddEntry(type, 192 Source(net::NetLog::SOURCE_NONE, NextID()), 193 net::NetLog::PHASE_NONE, 194 NULL); 195} 196 197void NetLog::AddGlobalEntry( 198 EventType type, 199 const NetLog::ParametersCallback& parameters_callback) { 200 AddEntry(type, 201 Source(net::NetLog::SOURCE_NONE, NextID()), 202 net::NetLog::PHASE_NONE, 203 ¶meters_callback); 204} 205 206// static 207std::string NetLog::TickCountToString(const base::TimeTicks& time) { 208 int64 delta_time = (time - base::TimeTicks()).InMilliseconds(); 209 return base::Int64ToString(delta_time); 210} 211 212// static 213const char* NetLog::EventTypeToString(EventType event) { 214 switch (event) { 215#define EVENT_TYPE(label) case TYPE_ ## label: return #label; 216#include "net/base/net_log_event_type_list.h" 217#undef EVENT_TYPE 218 default: 219 NOTREACHED(); 220 return NULL; 221 } 222} 223 224// static 225base::Value* NetLog::GetEventTypesAsValue() { 226 DictionaryValue* dict = new DictionaryValue(); 227 for (int i = 0; i < EVENT_COUNT; ++i) { 228 dict->SetInteger(EventTypeToString(static_cast<EventType>(i)), i); 229 } 230 return dict; 231} 232 233// static 234const char* NetLog::SourceTypeToString(SourceType source) { 235 switch (source) { 236#define SOURCE_TYPE(label) case SOURCE_ ## label: return #label; 237#include "net/base/net_log_source_type_list.h" 238#undef SOURCE_TYPE 239 default: 240 NOTREACHED(); 241 return NULL; 242 } 243} 244 245// static 246base::Value* NetLog::GetSourceTypesAsValue() { 247 DictionaryValue* dict = new DictionaryValue(); 248 for (int i = 0; i < SOURCE_COUNT; ++i) { 249 dict->SetInteger(SourceTypeToString(static_cast<SourceType>(i)), i); 250 } 251 return dict; 252} 253 254// static 255const char* NetLog::EventPhaseToString(EventPhase phase) { 256 switch (phase) { 257 case PHASE_BEGIN: 258 return "PHASE_BEGIN"; 259 case PHASE_END: 260 return "PHASE_END"; 261 case PHASE_NONE: 262 return "PHASE_NONE"; 263 } 264 NOTREACHED(); 265 return NULL; 266} 267 268// static 269bool NetLog::IsLoggingBytes(LogLevel log_level) { 270 return log_level == NetLog::LOG_ALL; 271} 272 273// static 274bool NetLog::IsLoggingAllEvents(LogLevel log_level) { 275 return log_level <= NetLog::LOG_ALL_BUT_BYTES; 276} 277 278// static 279NetLog::ParametersCallback NetLog::IntegerCallback(const char* name, 280 int value) { 281 return base::Bind(&NetLogIntegerCallback, name, value); 282} 283 284// static 285NetLog::ParametersCallback NetLog::Int64Callback(const char* name, 286 int64 value) { 287 return base::Bind(&NetLogInt64Callback, name, value); 288} 289 290// static 291NetLog::ParametersCallback NetLog::StringCallback(const char* name, 292 const std::string* value) { 293 DCHECK(value); 294 return base::Bind(&NetLogStringCallback, name, value); 295} 296 297// static 298NetLog::ParametersCallback NetLog::StringCallback(const char* name, 299 const string16* value) { 300 DCHECK(value); 301 return base::Bind(&NetLogString16Callback, name, value); 302} 303 304void NetLog::OnAddObserver(ThreadSafeObserver* observer, LogLevel log_level) { 305 DCHECK(!observer->net_log_); 306 observer->net_log_ = this; 307 observer->log_level_ = log_level; 308} 309 310void NetLog::OnSetObserverLogLevel(ThreadSafeObserver* observer, 311 LogLevel log_level) { 312 DCHECK_EQ(this, observer->net_log_); 313 observer->log_level_ = log_level; 314} 315 316void NetLog::OnRemoveObserver(ThreadSafeObserver* observer) { 317 DCHECK_EQ(this, observer->net_log_); 318 observer->net_log_ = NULL; 319} 320 321void NetLog::AddEntry(EventType type, 322 const Source& source, 323 EventPhase phase, 324 const NetLog::ParametersCallback* parameters_callback) { 325 Entry entry(type, source, phase, base::TimeTicks::Now(), 326 parameters_callback, GetLogLevel()); 327 OnAddEntry(entry); 328} 329 330void BoundNetLog::AddEntry(NetLog::EventType type, 331 NetLog::EventPhase phase) const { 332 if (!net_log_) 333 return; 334 net_log_->AddEntry(type, source_, phase, NULL); 335} 336 337void BoundNetLog::AddEntry( 338 NetLog::EventType type, 339 NetLog::EventPhase phase, 340 const NetLog::ParametersCallback& get_parameters) const { 341 if (!net_log_) 342 return; 343 net_log_->AddEntry(type, source_, phase, &get_parameters); 344} 345 346void BoundNetLog::AddEvent(NetLog::EventType type) const { 347 AddEntry(type, NetLog::PHASE_NONE); 348} 349 350void BoundNetLog::AddEvent( 351 NetLog::EventType type, 352 const NetLog::ParametersCallback& get_parameters) const { 353 AddEntry(type, NetLog::PHASE_NONE, get_parameters); 354} 355 356void BoundNetLog::BeginEvent(NetLog::EventType type) const { 357 AddEntry(type, NetLog::PHASE_BEGIN); 358} 359 360void BoundNetLog::BeginEvent( 361 NetLog::EventType type, 362 const NetLog::ParametersCallback& get_parameters) const { 363 AddEntry(type, NetLog::PHASE_BEGIN, get_parameters); 364} 365 366void BoundNetLog::EndEvent(NetLog::EventType type) const { 367 AddEntry(type, NetLog::PHASE_END); 368} 369 370void BoundNetLog::EndEvent( 371 NetLog::EventType type, 372 const NetLog::ParametersCallback& get_parameters) const { 373 AddEntry(type, NetLog::PHASE_END, get_parameters); 374} 375 376void BoundNetLog::AddEventWithNetErrorCode(NetLog::EventType event_type, 377 int net_error) const { 378 DCHECK_NE(ERR_IO_PENDING, net_error); 379 if (net_error >= 0) { 380 AddEvent(event_type); 381 } else { 382 AddEvent(event_type, NetLog::IntegerCallback("net_error", net_error)); 383 } 384} 385 386void BoundNetLog::EndEventWithNetErrorCode(NetLog::EventType event_type, 387 int net_error) const { 388 DCHECK_NE(ERR_IO_PENDING, net_error); 389 if (net_error >= 0) { 390 EndEvent(event_type); 391 } else { 392 EndEvent(event_type, NetLog::IntegerCallback("net_error", net_error)); 393 } 394} 395 396void BoundNetLog::AddByteTransferEvent(NetLog::EventType event_type, 397 int byte_count, 398 const char* bytes) const { 399 AddEvent(event_type, base::Bind(BytesTransferredCallback, byte_count, bytes)); 400} 401 402NetLog::LogLevel BoundNetLog::GetLogLevel() const { 403 if (net_log_) 404 return net_log_->GetLogLevel(); 405 return NetLog::LOG_BASIC; 406} 407 408bool BoundNetLog::IsLoggingBytes() const { 409 return NetLog::IsLoggingBytes(GetLogLevel()); 410} 411 412bool BoundNetLog::IsLoggingAllEvents() const { 413 return NetLog::IsLoggingAllEvents(GetLogLevel()); 414} 415 416// static 417BoundNetLog BoundNetLog::Make(NetLog* net_log, 418 NetLog::SourceType source_type) { 419 if (!net_log) 420 return BoundNetLog(); 421 422 NetLog::Source source(source_type, net_log->NextID()); 423 return BoundNetLog(source, net_log); 424} 425 426} // namespace net 427