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 = NULL; 105 base::DictionaryValue* source_dict = NULL; 106 int source_id = -1; 107 int source_type = NetLog::SOURCE_COUNT; 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_GE(source_id, 0); 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(data_->time)); 127 128 // Set the entry source. 129 base::DictionaryValue* source_dict = new base::DictionaryValue(); 130 source_dict->SetInteger("id", data_->source.id); 131 source_dict->SetInteger("type", static_cast<int>(data_->source.type)); 132 entry_dict->Set("source", source_dict); 133 134 // Set the event info. 135 entry_dict->SetInteger("type", static_cast<int>(data_->type)); 136 entry_dict->SetInteger("phase", static_cast<int>(data_->phase)); 137 138 // Set the event-specific parameters. 139 if (data_->parameters_callback) { 140 base::Value* value = data_->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 (data_->parameters_callback) 150 return data_->parameters_callback->Run(log_level_); 151 return NULL; 152 } 153 154 NetLog::EntryData::EntryData( 155 EventType type, 156 Source source, 157 EventPhase phase, 158 base::TimeTicks time, 159 const ParametersCallback* parameters_callback) 160 : type(type), 161 source(source), 162 phase(phase), 163 time(time), 164 parameters_callback(parameters_callback) { 165 } 166 167 NetLog::EntryData::~EntryData() { 168 } 169 170 NetLog::Entry::Entry(const EntryData* data, LogLevel log_level) 171 : data_(data), log_level_(log_level) { 172 } 173 174 NetLog::Entry::~Entry() { 175 } 176 177 NetLog::ThreadSafeObserver::ThreadSafeObserver() : log_level_(LOG_NONE), 178 net_log_(NULL) { 179 } 180 181 NetLog::ThreadSafeObserver::~ThreadSafeObserver() { 182 // Make sure we aren't watching a NetLog on destruction. Because the NetLog 183 // may pass events to each observer on multiple threads, we cannot safely 184 // stop watching a NetLog automatically from a parent class. 185 DCHECK(!net_log_); 186 } 187 188 NetLog::LogLevel NetLog::ThreadSafeObserver::log_level() const { 189 DCHECK(net_log_); 190 return log_level_; 191 } 192 193 NetLog* NetLog::ThreadSafeObserver::net_log() const { 194 return net_log_; 195 } 196 197 void NetLog::ThreadSafeObserver::OnAddEntryData(const EntryData& entry_data) { 198 OnAddEntry(Entry(&entry_data, log_level())); 199 } 200 201 NetLog::NetLog() 202 : last_id_(0), 203 base_log_level_(LOG_NONE), 204 effective_log_level_(LOG_NONE) { 205 } 206 207 NetLog::~NetLog() { 208 } 209 210 void NetLog::AddGlobalEntry(EventType type) { 211 AddEntry(type, 212 Source(net::NetLog::SOURCE_NONE, NextID()), 213 net::NetLog::PHASE_NONE, 214 NULL); 215 } 216 217 void NetLog::AddGlobalEntry( 218 EventType type, 219 const NetLog::ParametersCallback& parameters_callback) { 220 AddEntry(type, 221 Source(net::NetLog::SOURCE_NONE, NextID()), 222 net::NetLog::PHASE_NONE, 223 ¶meters_callback); 224 } 225 226 uint32 NetLog::NextID() { 227 return base::subtle::NoBarrier_AtomicIncrement(&last_id_, 1); 228 } 229 230 void NetLog::SetBaseLogLevel(LogLevel log_level) { 231 base::AutoLock lock(lock_); 232 base_log_level_ = log_level; 233 234 UpdateLogLevel(); 235 } 236 237 NetLog::LogLevel NetLog::GetLogLevel() const { 238 base::subtle::Atomic32 log_level = 239 base::subtle::NoBarrier_Load(&effective_log_level_); 240 return static_cast<net::NetLog::LogLevel>(log_level); 241 } 242 243 void NetLog::AddThreadSafeObserver( 244 net::NetLog::ThreadSafeObserver* observer, 245 LogLevel log_level) { 246 DCHECK_NE(LOG_NONE, log_level); 247 base::AutoLock lock(lock_); 248 249 DCHECK(!observer->net_log_); 250 DCHECK_EQ(LOG_NONE, observer->log_level_); 251 observers_.AddObserver(observer); 252 observer->net_log_ = this; 253 observer->log_level_ = log_level; 254 UpdateLogLevel(); 255 } 256 257 void NetLog::SetObserverLogLevel( 258 net::NetLog::ThreadSafeObserver* observer, 259 LogLevel log_level) { 260 DCHECK_NE(LOG_NONE, log_level); 261 base::AutoLock lock(lock_); 262 263 DCHECK(observers_.HasObserver(observer)); 264 DCHECK_EQ(this, observer->net_log_); 265 DCHECK_NE(LOG_NONE, observer->log_level_); 266 observer->log_level_ = log_level; 267 UpdateLogLevel(); 268 } 269 270 void NetLog::RemoveThreadSafeObserver( 271 net::NetLog::ThreadSafeObserver* observer) { 272 base::AutoLock lock(lock_); 273 274 DCHECK(observers_.HasObserver(observer)); 275 DCHECK_EQ(this, observer->net_log_); 276 DCHECK_NE(LOG_NONE, observer->log_level_); 277 observers_.RemoveObserver(observer); 278 observer->net_log_ = NULL; 279 observer->log_level_ = LOG_NONE; 280 UpdateLogLevel(); 281 } 282 283 void NetLog::UpdateLogLevel() { 284 lock_.AssertAcquired(); 285 286 // Look through all the observers and find the finest granularity 287 // log level (higher values of the enum imply *lower* log levels). 288 LogLevel new_effective_log_level = base_log_level_; 289 ObserverListBase<ThreadSafeObserver>::Iterator it(observers_); 290 ThreadSafeObserver* observer; 291 while ((observer = it.GetNext()) != NULL) { 292 new_effective_log_level = 293 std::min(new_effective_log_level, observer->log_level()); 294 } 295 base::subtle::NoBarrier_Store(&effective_log_level_, 296 new_effective_log_level); 297 } 298 299 // static 300 std::string NetLog::TickCountToString(const base::TimeTicks& time) { 301 int64 delta_time = (time - base::TimeTicks()).InMilliseconds(); 302 return base::Int64ToString(delta_time); 303 } 304 305 // static 306 const char* NetLog::EventTypeToString(EventType event) { 307 switch (event) { 308 #define EVENT_TYPE(label) case TYPE_ ## label: return #label; 309 #include "net/base/net_log_event_type_list.h" 310 #undef EVENT_TYPE 311 default: 312 NOTREACHED(); 313 return NULL; 314 } 315 } 316 317 // static 318 base::Value* NetLog::GetEventTypesAsValue() { 319 base::DictionaryValue* dict = new base::DictionaryValue(); 320 for (int i = 0; i < EVENT_COUNT; ++i) { 321 dict->SetInteger(EventTypeToString(static_cast<EventType>(i)), i); 322 } 323 return dict; 324 } 325 326 // static 327 const char* NetLog::SourceTypeToString(SourceType source) { 328 switch (source) { 329 #define SOURCE_TYPE(label) case SOURCE_ ## label: return #label; 330 #include "net/base/net_log_source_type_list.h" 331 #undef SOURCE_TYPE 332 default: 333 NOTREACHED(); 334 return NULL; 335 } 336 } 337 338 // static 339 base::Value* NetLog::GetSourceTypesAsValue() { 340 base::DictionaryValue* dict = new base::DictionaryValue(); 341 for (int i = 0; i < SOURCE_COUNT; ++i) { 342 dict->SetInteger(SourceTypeToString(static_cast<SourceType>(i)), i); 343 } 344 return dict; 345 } 346 347 // static 348 const char* NetLog::EventPhaseToString(EventPhase phase) { 349 switch (phase) { 350 case PHASE_BEGIN: 351 return "PHASE_BEGIN"; 352 case PHASE_END: 353 return "PHASE_END"; 354 case PHASE_NONE: 355 return "PHASE_NONE"; 356 } 357 NOTREACHED(); 358 return NULL; 359 } 360 361 // static 362 bool NetLog::IsLoggingBytes(LogLevel log_level) { 363 return log_level == NetLog::LOG_ALL; 364 } 365 366 // static 367 bool NetLog::IsLogging(LogLevel log_level) { 368 return log_level < NetLog::LOG_NONE; 369 } 370 371 // static 372 NetLog::ParametersCallback NetLog::IntegerCallback(const char* name, 373 int value) { 374 return base::Bind(&NetLogIntegerCallback, name, value); 375 } 376 377 // static 378 NetLog::ParametersCallback NetLog::Int64Callback(const char* name, 379 int64 value) { 380 return base::Bind(&NetLogInt64Callback, name, value); 381 } 382 383 // static 384 NetLog::ParametersCallback NetLog::StringCallback(const char* name, 385 const std::string* value) { 386 DCHECK(value); 387 return base::Bind(&NetLogStringCallback, name, value); 388 } 389 390 // static 391 NetLog::ParametersCallback NetLog::StringCallback(const char* name, 392 const base::string16* value) { 393 DCHECK(value); 394 return base::Bind(&NetLogString16Callback, name, value); 395 } 396 397 void NetLog::AddEntry(EventType type, 398 const Source& source, 399 EventPhase phase, 400 const NetLog::ParametersCallback* parameters_callback) { 401 if (GetLogLevel() == LOG_NONE) 402 return; 403 EntryData entry_data(type, source, phase, base::TimeTicks::Now(), 404 parameters_callback); 405 406 // Notify all of the log observers. 407 base::AutoLock lock(lock_); 408 FOR_EACH_OBSERVER(ThreadSafeObserver, observers_, OnAddEntryData(entry_data)); 409 } 410 411 void BoundNetLog::AddEntry(NetLog::EventType type, 412 NetLog::EventPhase phase) const { 413 if (!net_log_) 414 return; 415 net_log_->AddEntry(type, source_, phase, NULL); 416 } 417 418 void BoundNetLog::AddEntry( 419 NetLog::EventType type, 420 NetLog::EventPhase phase, 421 const NetLog::ParametersCallback& get_parameters) const { 422 if (!net_log_) 423 return; 424 net_log_->AddEntry(type, source_, phase, &get_parameters); 425 } 426 427 void BoundNetLog::AddEvent(NetLog::EventType type) const { 428 AddEntry(type, NetLog::PHASE_NONE); 429 } 430 431 void BoundNetLog::AddEvent( 432 NetLog::EventType type, 433 const NetLog::ParametersCallback& get_parameters) const { 434 AddEntry(type, NetLog::PHASE_NONE, get_parameters); 435 } 436 437 void BoundNetLog::BeginEvent(NetLog::EventType type) const { 438 AddEntry(type, NetLog::PHASE_BEGIN); 439 } 440 441 void BoundNetLog::BeginEvent( 442 NetLog::EventType type, 443 const NetLog::ParametersCallback& get_parameters) const { 444 AddEntry(type, NetLog::PHASE_BEGIN, get_parameters); 445 } 446 447 void BoundNetLog::EndEvent(NetLog::EventType type) const { 448 AddEntry(type, NetLog::PHASE_END); 449 } 450 451 void BoundNetLog::EndEvent( 452 NetLog::EventType type, 453 const NetLog::ParametersCallback& get_parameters) const { 454 AddEntry(type, NetLog::PHASE_END, get_parameters); 455 } 456 457 void BoundNetLog::AddEventWithNetErrorCode(NetLog::EventType event_type, 458 int net_error) const { 459 DCHECK_NE(ERR_IO_PENDING, net_error); 460 if (net_error >= 0) { 461 AddEvent(event_type); 462 } else { 463 AddEvent(event_type, NetLog::IntegerCallback("net_error", net_error)); 464 } 465 } 466 467 void BoundNetLog::EndEventWithNetErrorCode(NetLog::EventType event_type, 468 int net_error) const { 469 DCHECK_NE(ERR_IO_PENDING, net_error); 470 if (net_error >= 0) { 471 EndEvent(event_type); 472 } else { 473 EndEvent(event_type, NetLog::IntegerCallback("net_error", net_error)); 474 } 475 } 476 477 void BoundNetLog::AddByteTransferEvent(NetLog::EventType event_type, 478 int byte_count, 479 const char* bytes) const { 480 AddEvent(event_type, base::Bind(BytesTransferredCallback, byte_count, bytes)); 481 } 482 483 NetLog::LogLevel BoundNetLog::GetLogLevel() const { 484 if (net_log_) 485 return net_log_->GetLogLevel(); 486 return NetLog::LOG_NONE; 487 } 488 489 bool BoundNetLog::IsLoggingBytes() const { 490 return NetLog::IsLoggingBytes(GetLogLevel()); 491 } 492 493 bool BoundNetLog::IsLogging() const { 494 return NetLog::IsLogging(GetLogLevel()); 495 } 496 497 // static 498 BoundNetLog BoundNetLog::Make(NetLog* net_log, 499 NetLog::SourceType source_type) { 500 if (!net_log) 501 return BoundNetLog(); 502 503 NetLog::Source source(source_type, net_log->NextID()); 504 return BoundNetLog(source, net_log); 505 } 506 507 } // namespace net 508