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