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