Home | History | Annotate | Download | only in base
      1 // Copyright 2013 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_logger.h"
      6 
      7 #include <stdio.h>
      8 
      9 #include "base/json/json_writer.h"
     10 #include "base/logging.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/strings/string_number_conversions.h"
     13 #include "base/values.h"
     14 #include "net/base/address_family.h"
     15 #include "net/base/load_states.h"
     16 #include "net/base/net_errors.h"
     17 #include "net/quic/quic_protocol.h"
     18 #include "net/quic/quic_utils.h"
     19 
     20 namespace {
     21 
     22 struct StringToConstant {
     23   const char* name;
     24   const int constant;
     25 };
     26 
     27 const StringToConstant kCertStatusFlags[] = {
     28 #define CERT_STATUS_FLAG(label, value) { #label, value },
     29 #include "net/cert/cert_status_flags_list.h"
     30 #undef CERT_STATUS_FLAG
     31 };
     32 
     33 const StringToConstant kLoadFlags[] = {
     34 #define LOAD_FLAG(label, value) { #label, value },
     35 #include "net/base/load_flags_list.h"
     36 #undef LOAD_FLAG
     37 };
     38 
     39 const StringToConstant kLoadStateTable[] = {
     40 #define LOAD_STATE(label) { # label, net::LOAD_STATE_ ## label },
     41 #include "net/base/load_states_list.h"
     42 #undef LOAD_STATE
     43 };
     44 
     45 const short kNetErrors[] = {
     46 #define NET_ERROR(label, value) value,
     47 #include "net/base/net_error_list.h"
     48 #undef NET_ERROR
     49 };
     50 
     51 }  // namespace
     52 
     53 namespace net {
     54 
     55 // This should be incremented when significant changes are made that will
     56 // invalidate the old loading code.
     57 static const int kLogFormatVersion = 1;
     58 
     59 NetLogLogger::NetLogLogger(FILE* file, const base::Value& constants)
     60     : file_(file), log_level_(NetLog::LOG_ALL_BUT_BYTES), added_events_(false) {
     61   DCHECK(file);
     62 
     63   // Write constants to the output file.  This allows loading files that have
     64   // different source and event types, as they may be added and removed
     65   // between Chrome versions.
     66   std::string json;
     67   base::JSONWriter::Write(&constants, &json);
     68   fprintf(file_.get(), "{\"constants\": %s,\n", json.c_str());
     69   fprintf(file_.get(), "\"events\": [\n");
     70 }
     71 
     72 NetLogLogger::~NetLogLogger() {
     73   if (file_.get())
     74     fprintf(file_.get(), "]}");
     75 }
     76 
     77 void NetLogLogger::set_log_level(net::NetLog::LogLevel log_level) {
     78   DCHECK(!net_log());
     79   log_level_ = log_level;
     80 }
     81 
     82 void NetLogLogger::StartObserving(net::NetLog* net_log) {
     83   net_log->AddThreadSafeObserver(this, log_level_);
     84 }
     85 
     86 void NetLogLogger::StopObserving() {
     87   net_log()->RemoveThreadSafeObserver(this);
     88 }
     89 
     90 void NetLogLogger::OnAddEntry(const net::NetLog::Entry& entry) {
     91   // Add a comma and newline for every event but the first.  Newlines are needed
     92   // so can load partial log files by just ignoring the last line.  For this to
     93   // work, lines cannot be pretty printed.
     94   scoped_ptr<base::Value> value(entry.ToValue());
     95   std::string json;
     96   base::JSONWriter::Write(value.get(), &json);
     97   fprintf(file_.get(), "%s%s",
     98           (added_events_ ? ",\n" : ""),
     99           json.c_str());
    100   added_events_ = true;
    101 }
    102 
    103 base::DictionaryValue* NetLogLogger::GetConstants() {
    104   base::DictionaryValue* constants_dict = new base::DictionaryValue();
    105 
    106   // Version of the file format.
    107   constants_dict->SetInteger("logFormatVersion", kLogFormatVersion);
    108 
    109   // Add a dictionary with information on the relationship between event type
    110   // enums and their symbolic names.
    111   constants_dict->Set("logEventTypes", net::NetLog::GetEventTypesAsValue());
    112 
    113   // Add a dictionary with information about the relationship between CertStatus
    114   // flags and their symbolic names.
    115   {
    116     base::DictionaryValue* dict = new base::DictionaryValue();
    117 
    118     for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kCertStatusFlags); i++)
    119       dict->SetInteger(kCertStatusFlags[i].name, kCertStatusFlags[i].constant);
    120 
    121     constants_dict->Set("certStatusFlag", dict);
    122   }
    123 
    124   // Add a dictionary with information about the relationship between load flag
    125   // enums and their symbolic names.
    126   {
    127     base::DictionaryValue* dict = new base::DictionaryValue();
    128 
    129     for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kLoadFlags); i++)
    130       dict->SetInteger(kLoadFlags[i].name, kLoadFlags[i].constant);
    131 
    132     constants_dict->Set("loadFlag", dict);
    133   }
    134 
    135   // Add a dictionary with information about the relationship between load state
    136   // enums and their symbolic names.
    137   {
    138     base::DictionaryValue* dict = new base::DictionaryValue();
    139 
    140     for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kLoadStateTable); i++)
    141       dict->SetInteger(kLoadStateTable[i].name, kLoadStateTable[i].constant);
    142 
    143     constants_dict->Set("loadState", dict);
    144   }
    145 
    146   // Add information on the relationship between net error codes and their
    147   // symbolic names.
    148   {
    149     base::DictionaryValue* dict = new base::DictionaryValue();
    150 
    151     for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNetErrors); i++)
    152       dict->SetInteger(ErrorToShortString(kNetErrors[i]), kNetErrors[i]);
    153 
    154     constants_dict->Set("netError", dict);
    155   }
    156 
    157   // Add information on the relationship between QUIC error codes and their
    158   // symbolic names.
    159   {
    160     base::DictionaryValue* dict = new base::DictionaryValue();
    161 
    162     for (net::QuicErrorCode error = net::QUIC_NO_ERROR;
    163          error < net::QUIC_LAST_ERROR;
    164          error = static_cast<net::QuicErrorCode>(error + 1)) {
    165       dict->SetInteger(net::QuicUtils::ErrorToString(error),
    166                        static_cast<int>(error));
    167     }
    168 
    169     constants_dict->Set("quicError", dict);
    170   }
    171 
    172   // Add information on the relationship between QUIC RST_STREAM error codes
    173   // and their symbolic names.
    174   {
    175     base::DictionaryValue* dict = new base::DictionaryValue();
    176 
    177     for (net::QuicRstStreamErrorCode error = net::QUIC_STREAM_NO_ERROR;
    178          error < net::QUIC_STREAM_LAST_ERROR;
    179          error = static_cast<net::QuicRstStreamErrorCode>(error + 1)) {
    180       dict->SetInteger(net::QuicUtils::StreamErrorToString(error),
    181                        static_cast<int>(error));
    182     }
    183 
    184     constants_dict->Set("quicRstStreamError", dict);
    185   }
    186 
    187   // Information about the relationship between event phase enums and their
    188   // symbolic names.
    189   {
    190     base::DictionaryValue* dict = new base::DictionaryValue();
    191 
    192     dict->SetInteger("PHASE_BEGIN", net::NetLog::PHASE_BEGIN);
    193     dict->SetInteger("PHASE_END", net::NetLog::PHASE_END);
    194     dict->SetInteger("PHASE_NONE", net::NetLog::PHASE_NONE);
    195 
    196     constants_dict->Set("logEventPhase", dict);
    197   }
    198 
    199   // Information about the relationship between source type enums and
    200   // their symbolic names.
    201   constants_dict->Set("logSourceType", net::NetLog::GetSourceTypesAsValue());
    202 
    203   // Information about the relationship between LogLevel enums and their
    204   // symbolic names.
    205   {
    206     base::DictionaryValue* dict = new base::DictionaryValue();
    207 
    208     dict->SetInteger("LOG_ALL", net::NetLog::LOG_ALL);
    209     dict->SetInteger("LOG_ALL_BUT_BYTES", net::NetLog::LOG_ALL_BUT_BYTES);
    210     dict->SetInteger("LOG_STRIP_PRIVATE_DATA",
    211                      net::NetLog::LOG_STRIP_PRIVATE_DATA);
    212 
    213     constants_dict->Set("logLevelType", dict);
    214   }
    215 
    216   // Information about the relationship between address family enums and
    217   // their symbolic names.
    218   {
    219     base::DictionaryValue* dict = new base::DictionaryValue();
    220 
    221     dict->SetInteger("ADDRESS_FAMILY_UNSPECIFIED",
    222                      net::ADDRESS_FAMILY_UNSPECIFIED);
    223     dict->SetInteger("ADDRESS_FAMILY_IPV4",
    224                      net::ADDRESS_FAMILY_IPV4);
    225     dict->SetInteger("ADDRESS_FAMILY_IPV6",
    226                      net::ADDRESS_FAMILY_IPV6);
    227 
    228     constants_dict->Set("addressFamily", dict);
    229   }
    230 
    231   // Information about how the "time ticks" values we have given it relate to
    232   // actual system times. (We used time ticks throughout since they are stable
    233   // across system clock changes).
    234   {
    235     int64 cur_time_ms = (base::Time::Now() - base::Time()).InMilliseconds();
    236 
    237     int64 cur_time_ticks_ms =
    238         (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds();
    239 
    240     // If we add this number to a time tick value, it gives the timestamp.
    241     int64 tick_to_time_ms = cur_time_ms - cur_time_ticks_ms;
    242 
    243     // Chrome on all platforms stores times using the Windows epoch
    244     // (Jan 1 1601), but the javascript wants a unix epoch.
    245     // TODO(eroman): Getting the timestamp relative to the unix epoch should
    246     //               be part of the time library.
    247     const int64 kUnixEpochMs = 11644473600000LL;
    248     int64 tick_to_unix_time_ms = tick_to_time_ms - kUnixEpochMs;
    249 
    250     // Pass it as a string, since it may be too large to fit in an integer.
    251     constants_dict->SetString("timeTickOffset",
    252                               base::Int64ToString(tick_to_unix_time_ms));
    253   }
    254 
    255   // "clientInfo" key is required for some NetLogLogger log readers.
    256   // Provide a default empty value for compatibility.
    257   constants_dict->Set("clientInfo", new base::DictionaryValue());
    258 
    259   return constants_dict;
    260 }
    261 
    262 }  // namespace net
    263