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 ¶meters_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