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