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.
5 #include "net/base/net_log.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"
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
,
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
));
33 base::Value
* SourceEventParametersCallback(const NetLog::Source source
,
34 NetLog::LogLevel
/* log_level */) {
35 if (!source
.IsValid())
37 base::DictionaryValue
* event_params
= new base::DictionaryValue();
38 source
.AddToEventParameters(event_params
);
42 base::Value
* NetLogIntegerCallback(const char* name
,
44 NetLog::LogLevel
/* log_level */) {
45 base::DictionaryValue
* event_params
= new base::DictionaryValue();
46 event_params
->SetInteger(name
, value
);
50 base::Value
* NetLogInt64Callback(const char* name
,
52 NetLog::LogLevel
/* log_level */) {
53 base::DictionaryValue
* event_params
= new base::DictionaryValue();
54 event_params
->SetString(name
, base::Int64ToString(value
));
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
);
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
);
76 // LoadTimingInfo requires this be 0.
77 const uint32
NetLog::Source::kInvalidId
= 0;
79 NetLog::Source::Source() : type(SOURCE_NONE
), id(kInvalidId
) {
82 NetLog::Source::Source(SourceType type
, uint32 id
) : type(type
), id(id
) {
85 bool NetLog::Source::IsValid() const {
86 return id
!= kInvalidId
;
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
);
97 NetLog::ParametersCallback
NetLog::Source::ToEventParametersCallback() const {
98 return base::Bind(&SourceEventParametersCallback
, *this);
102 bool NetLog::Source::FromEventParameters(base::Value
* event_params
,
104 base::DictionaryValue
* dict
;
105 base::DictionaryValue
* source_dict
;
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
)) {
117 DCHECK_LE(0, source_id
);
118 DCHECK_LT(source_type
, NetLog::SOURCE_COUNT
);
119 *source
= Source(static_cast<SourceType
>(source_type
), source_id
);
123 base::Value
* NetLog::Entry::ToValue() const {
124 base::DictionaryValue
* entry_dict(new base::DictionaryValue());
126 entry_dict
->SetString("time", TickCountToString(time_
));
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
);
134 // Set the event info.
135 entry_dict
->SetInteger("type", static_cast<int>(type_
));
136 entry_dict
->SetInteger("phase", static_cast<int>(phase_
));
138 // Set the event-specific parameters.
139 if (parameters_callback_
) {
140 base::Value
* value
= parameters_callback_
->Run(log_level_
);
142 entry_dict
->Set("params", value
);
148 base::Value
* NetLog::Entry::ParametersToValue() const {
149 if (parameters_callback_
)
150 return parameters_callback_
->Run(log_level_
);
154 NetLog::Entry::Entry(
158 base::TimeTicks time
,
159 const ParametersCallback
* parameters_callback
,
165 parameters_callback_(parameters_callback
),
166 log_level_(log_level
) {
169 NetLog::Entry::~Entry() {
172 NetLog::ThreadSafeObserver::ThreadSafeObserver() : log_level_(LOG_BASIC
),
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.
183 NetLog::LogLevel
NetLog::ThreadSafeObserver::log_level() const {
188 NetLog
* NetLog::ThreadSafeObserver::net_log() const {
194 base_log_level_(LOG_NONE
),
195 effective_log_level_(LOG_NONE
) {
201 void NetLog::AddGlobalEntry(EventType type
) {
203 Source(net::NetLog::SOURCE_NONE
, NextID()),
204 net::NetLog::PHASE_NONE
,
208 void NetLog::AddGlobalEntry(
210 const NetLog::ParametersCallback
& parameters_callback
) {
212 Source(net::NetLog::SOURCE_NONE
, NextID()),
213 net::NetLog::PHASE_NONE
,
214 ¶meters_callback
);
217 uint32
NetLog::NextID() {
218 return base::subtle::NoBarrier_AtomicIncrement(&last_id_
, 1);
221 void NetLog::SetBaseLogLevel(LogLevel log_level
) {
222 base::AutoLock
lock(lock_
);
223 base_log_level_
= log_level
;
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
);
234 void NetLog::AddThreadSafeObserver(
235 net::NetLog::ThreadSafeObserver
* observer
,
236 LogLevel log_level
) {
237 base::AutoLock
lock(lock_
);
239 DCHECK(!observer
->net_log_
);
240 observers_
.AddObserver(observer
);
241 observer
->net_log_
= this;
242 observer
->log_level_
= log_level
;
246 void NetLog::SetObserverLogLevel(
247 net::NetLog::ThreadSafeObserver
* observer
,
248 LogLevel log_level
) {
249 base::AutoLock
lock(lock_
);
251 DCHECK(observers_
.HasObserver(observer
));
252 DCHECK_EQ(this, observer
->net_log_
);
253 observer
->log_level_
= log_level
;
257 void NetLog::RemoveThreadSafeObserver(
258 net::NetLog::ThreadSafeObserver
* observer
) {
259 base::AutoLock
lock(lock_
);
261 DCHECK(observers_
.HasObserver(observer
));
262 DCHECK_EQ(this, observer
->net_log_
);
263 observers_
.RemoveObserver(observer
);
264 observer
->net_log_
= NULL
;
268 void NetLog::UpdateLogLevel() {
269 lock_
.AssertAcquired();
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());
280 base::subtle::NoBarrier_Store(&effective_log_level_
,
281 new_effective_log_level
);
285 std::string
NetLog::TickCountToString(const base::TimeTicks
& time
) {
286 int64 delta_time
= (time
- base::TimeTicks()).InMilliseconds();
287 return base::Int64ToString(delta_time
);
291 const char* NetLog::EventTypeToString(EventType event
) {
293 #define EVENT_TYPE(label) case TYPE_ ## label: return #label;
294 #include "net/base/net_log_event_type_list.h"
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
);
312 const char* NetLog::SourceTypeToString(SourceType source
) {
314 #define SOURCE_TYPE(label) case SOURCE_ ## label: return #label;
315 #include "net/base/net_log_source_type_list.h"
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
);
333 const char* NetLog::EventPhaseToString(EventPhase phase
) {
336 return "PHASE_BEGIN";
347 bool NetLog::IsLoggingBytes(LogLevel log_level
) {
348 return log_level
== NetLog::LOG_ALL
;
352 bool NetLog::IsLoggingAllEvents(LogLevel log_level
) {
353 return log_level
<= NetLog::LOG_ALL_BUT_BYTES
;
357 NetLog::ParametersCallback
NetLog::IntegerCallback(const char* name
,
359 return base::Bind(&NetLogIntegerCallback
, name
, value
);
363 NetLog::ParametersCallback
NetLog::Int64Callback(const char* name
,
365 return base::Bind(&NetLogInt64Callback
, name
, value
);
369 NetLog::ParametersCallback
NetLog::StringCallback(const char* name
,
370 const std::string
* value
) {
372 return base::Bind(&NetLogStringCallback
, name
, value
);
376 NetLog::ParametersCallback
NetLog::StringCallback(const char* name
,
377 const base::string16
* value
) {
379 return base::Bind(&NetLogString16Callback
, name
, value
);
382 void NetLog::AddEntry(EventType type
,
383 const Source
& source
,
385 const NetLog::ParametersCallback
* parameters_callback
) {
386 LogLevel log_level
= GetLogLevel();
387 if (log_level
== LOG_NONE
)
389 Entry
entry(type
, source
, phase
, base::TimeTicks::Now(),
390 parameters_callback
, log_level
);
392 // Notify all of the log observers.
393 base::AutoLock
lock(lock_
);
394 FOR_EACH_OBSERVER(ThreadSafeObserver
, observers_
, OnAddEntry(entry
));
397 void BoundNetLog::AddEntry(NetLog::EventType type
,
398 NetLog::EventPhase phase
) const {
401 net_log_
->AddEntry(type
, source_
, phase
, NULL
);
404 void BoundNetLog::AddEntry(
405 NetLog::EventType type
,
406 NetLog::EventPhase phase
,
407 const NetLog::ParametersCallback
& get_parameters
) const {
410 net_log_
->AddEntry(type
, source_
, phase
, &get_parameters
);
413 void BoundNetLog::AddEvent(NetLog::EventType type
) const {
414 AddEntry(type
, NetLog::PHASE_NONE
);
417 void BoundNetLog::AddEvent(
418 NetLog::EventType type
,
419 const NetLog::ParametersCallback
& get_parameters
) const {
420 AddEntry(type
, NetLog::PHASE_NONE
, get_parameters
);
423 void BoundNetLog::BeginEvent(NetLog::EventType type
) const {
424 AddEntry(type
, NetLog::PHASE_BEGIN
);
427 void BoundNetLog::BeginEvent(
428 NetLog::EventType type
,
429 const NetLog::ParametersCallback
& get_parameters
) const {
430 AddEntry(type
, NetLog::PHASE_BEGIN
, get_parameters
);
433 void BoundNetLog::EndEvent(NetLog::EventType type
) const {
434 AddEntry(type
, NetLog::PHASE_END
);
437 void BoundNetLog::EndEvent(
438 NetLog::EventType type
,
439 const NetLog::ParametersCallback
& get_parameters
) const {
440 AddEntry(type
, NetLog::PHASE_END
, get_parameters
);
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
);
449 AddEvent(event_type
, NetLog::IntegerCallback("net_error", net_error
));
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
);
459 EndEvent(event_type
, NetLog::IntegerCallback("net_error", net_error
));
463 void BoundNetLog::AddByteTransferEvent(NetLog::EventType event_type
,
465 const char* bytes
) const {
466 AddEvent(event_type
, base::Bind(BytesTransferredCallback
, byte_count
, bytes
));
469 NetLog::LogLevel
BoundNetLog::GetLogLevel() const {
471 return net_log_
->GetLogLevel();
472 return NetLog::LOG_BASIC
;
475 bool BoundNetLog::IsLoggingBytes() const {
476 return NetLog::IsLoggingBytes(GetLogLevel());
479 bool BoundNetLog::IsLoggingAllEvents() const {
480 return NetLog::IsLoggingAllEvents(GetLogLevel());
484 BoundNetLog
BoundNetLog::Make(NetLog
* net_log
,
485 NetLog::SourceType source_type
) {
487 return BoundNetLog();
489 NetLog::Source
source(source_type
, net_log
->NextID());
490 return BoundNetLog(source
, net_log
);