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           &parameters_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