Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chromeos/network/network_event_log.h" | 5 #include "chromeos/network/network_event_log.h" |
| 6 | 6 |
| 7 #include "base/files/file_path.h" | |
| 7 #include "base/i18n/time_formatting.h" | 8 #include "base/i18n/time_formatting.h" |
| 8 #include "base/logging.h" | 9 #include "base/logging.h" |
| 9 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/stringprintf.h" | 11 #include "base/stringprintf.h" |
| 12 #include "base/strings/string_tokenizer.h" | |
| 11 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
| 14 #include "base/values.h" | |
| 15 #include "net/base/escape.h" | |
| 12 | 16 |
| 13 namespace chromeos { | 17 namespace chromeos { |
| 14 | 18 |
| 15 namespace network_event_log { | 19 namespace network_event_log { |
| 16 | 20 |
| 17 namespace { | 21 namespace { |
| 18 | 22 |
| 19 struct LogEntry { | 23 struct LogEntry { |
| 20 LogEntry(const std::string& module, | 24 LogEntry(const std::string& file, |
| 25 int file_line, | |
| 26 LogLevel log_level, | |
| 21 const std::string& event, | 27 const std::string& event, |
| 22 const std::string& description); | 28 const std::string& description); |
| 23 | 29 |
| 24 std::string ToString() const; | 30 std::string ToString(bool show_time, |
| 31 bool show_file, | |
| 32 bool show_desc, | |
| 33 bool format_html) const; | |
| 34 void SendToVLogOrErrorLog() const; | |
| 25 | 35 |
| 26 bool ContentEquals(const LogEntry& other) const; | 36 bool ContentEquals(const LogEntry& other) const; |
| 27 | 37 |
| 28 std::string module; | 38 std::string file; |
| 39 int file_line; | |
| 40 LogLevel log_level; | |
| 29 std::string event; | 41 std::string event; |
| 30 std::string description; | 42 std::string description; |
| 31 base::Time time; | 43 base::Time time; |
| 32 int count; | 44 int count; |
| 33 }; | 45 }; |
| 34 | 46 |
| 35 LogEntry::LogEntry(const std::string& module, | 47 LogEntry::LogEntry(const std::string& file, |
| 48 int file_line, | |
| 49 LogLevel log_level, | |
| 36 const std::string& event, | 50 const std::string& event, |
| 37 const std::string& description) | 51 const std::string& description) |
| 38 : module(module), | 52 : file(file), |
| 53 file_line(file_line), | |
| 54 log_level(log_level), | |
| 39 event(event), | 55 event(event), |
| 40 description(description), | 56 description(description), |
| 41 time(base::Time::Now()), | 57 time(base::Time::Now()), |
| 42 count(1) { | 58 count(1) { |
| 43 } | 59 } |
| 44 | 60 |
| 45 std::string LogEntry::ToString() const { | 61 std::string LogEntry::ToString(bool show_time, |
| 62 bool show_file, | |
| 63 bool show_desc, | |
| 64 bool format_html) const { | |
| 46 std::string line; | 65 std::string line; |
| 47 line += "[" + UTF16ToUTF8(base::TimeFormatShortDateAndTime(time)) + "]"; | 66 if (show_time) |
| 48 line += " " + module + ":" + event; | 67 line += "[" + UTF16ToUTF8(base::TimeFormatShortDateAndTime(time)) + "] "; |
| 49 if (!description.empty()) | 68 if (show_file) { |
| 50 line += ": " + description; | 69 line += net::EscapeForHTML( |
| 70 base::StringPrintf("%s:%d ", file.c_str(), file_line)); | |
| 71 } | |
| 72 bool italic = (log_level == LOG_LEVEL_DEBUG && format_html); | |
| 73 bool bold = (log_level == LOG_LEVEL_ERROR && format_html); | |
| 74 if (italic) | |
| 75 line += "<i>"; | |
| 76 if (bold) | |
| 77 line += "<b>"; | |
| 78 line += event; | |
| 79 if (show_desc && !description.empty()) | |
| 80 line += ": " + net::EscapeForHTML(description); | |
| 81 if (bold) | |
| 82 line += "</b>"; | |
| 83 if (italic) | |
| 84 line += "</i>"; | |
| 85 | |
| 51 if (count > 1) | 86 if (count > 1) |
| 52 line += base::StringPrintf(" (%d)", count); | 87 line += base::StringPrintf(" (%d)", count); |
| 53 line += "\n"; | 88 line += "\n"; |
| 54 return line; | 89 return line; |
| 55 } | 90 } |
| 56 | 91 |
| 92 void LogEntry::SendToVLogOrErrorLog() const { | |
| 93 const bool show_time = true; | |
| 94 const bool show_file = true; | |
| 95 const bool show_desc = true; | |
| 96 const bool format_html = false; | |
| 97 std::string output = ToString(show_time, show_file, show_desc, format_html); | |
| 98 if (log_level == LOG_LEVEL_ERROR) | |
| 99 LOG(ERROR) << output; | |
| 100 else | |
| 101 VLOG(1) << output; | |
| 102 } | |
| 103 | |
| 57 bool LogEntry::ContentEquals(const LogEntry& other) const { | 104 bool LogEntry::ContentEquals(const LogEntry& other) const { |
| 58 return module == other.module && | 105 return file == other.file && |
| 106 file_line == other.file_line && | |
| 59 event == other.event && | 107 event == other.event && |
| 60 description == other.description; | 108 description == other.description; |
| 61 } | 109 } |
| 62 | 110 |
| 111 void GetFormat(const std::string& format_string, | |
| 112 bool* show_time, | |
| 113 bool* show_file, | |
| 114 bool* show_desc, | |
| 115 bool* format_html) { | |
| 116 base::StringTokenizer tokens(format_string, ","); | |
| 117 *show_time = false; | |
| 118 *show_file = false; | |
| 119 *show_desc = false; | |
| 120 *format_html = false; | |
| 121 while (tokens.GetNext()) { | |
| 122 std::string tok(tokens.token()); | |
| 123 if (tok == "time") | |
| 124 *show_time = true; | |
| 125 if (tok == "file") | |
| 126 *show_file = true; | |
| 127 if (tok == "desc") | |
| 128 *show_desc = true; | |
| 129 if (tok == "html") | |
| 130 *format_html = true; | |
| 131 } | |
| 132 } | |
| 133 | |
| 63 typedef std::deque<LogEntry> LogEntryList; | 134 typedef std::deque<LogEntry> LogEntryList; |
| 64 | 135 |
| 65 class NetworkEventLog { | 136 class NetworkEventLog { |
| 66 public: | 137 public: |
| 67 NetworkEventLog() {} | 138 NetworkEventLog() {} |
| 68 ~NetworkEventLog() {} | 139 ~NetworkEventLog() {} |
| 69 | 140 |
| 70 void AddEntry(const LogEntry& entry); | 141 void AddLogEntry(const LogEntry& entry); |
| 71 | 142 |
| 72 std::string GetAsString(StringOrder order, | 143 std::string GetAsString(StringOrder order, |
| 144 const std::string& format, | |
| 145 LogLevel max_level, | |
| 73 size_t max_events); | 146 size_t max_events); |
| 74 | 147 |
| 75 private: | 148 private: |
| 76 LogEntryList entries_; | 149 LogEntryList entries_; |
| 77 | 150 |
| 78 DISALLOW_COPY_AND_ASSIGN(NetworkEventLog); | 151 DISALLOW_COPY_AND_ASSIGN(NetworkEventLog); |
| 79 }; | 152 }; |
| 80 | 153 |
| 81 void NetworkEventLog::AddEntry(const LogEntry& entry) { | 154 void NetworkEventLog::AddLogEntry(const LogEntry& entry) { |
| 82 if (!entries_.empty()) { | 155 if (!entries_.empty()) { |
| 83 LogEntry& last = entries_.back(); | 156 LogEntry& last = entries_.back(); |
| 84 if (last.ContentEquals(entry)) { | 157 if (last.ContentEquals(entry)) { |
| 85 // Update count and time for identical events to avoid log spam. | 158 // Update count and time for identical events to avoid log spam. |
| 86 ++last.count; | 159 ++last.count; |
| 160 last.log_level = std::min(last.log_level, entry.log_level); | |
| 87 last.time = base::Time::Now(); | 161 last.time = base::Time::Now(); |
| 88 return; | 162 return; |
| 89 } | 163 } |
| 90 } | 164 } |
| 91 if (entries_.size() >= kMaxNetworkEventLogEntries) | 165 if (entries_.size() >= kMaxNetworkEventLogEntries) |
| 92 entries_.pop_front(); | 166 entries_.pop_front(); |
| 93 entries_.push_back(entry); | 167 entries_.push_back(entry); |
| 94 VLOG(1) << entry.ToString(); | 168 entry.SendToVLogOrErrorLog(); |
| 95 } | 169 } |
| 96 | 170 |
| 97 std::string NetworkEventLog::GetAsString(StringOrder order, | 171 std::string NetworkEventLog::GetAsString(StringOrder order, |
| 172 const std::string& format, | |
| 173 LogLevel max_level, | |
| 98 size_t max_events) { | 174 size_t max_events) { |
| 99 if (entries_.empty()) | 175 if (entries_.empty()) |
| 100 return "No Log Entries."; | 176 return "No Log Entries."; |
| 101 | 177 |
| 178 bool show_time, show_file, show_desc, format_html; | |
| 179 GetFormat(format, &show_time, &show_file, &show_desc, &format_html); | |
| 180 | |
| 102 std::string result; | 181 std::string result; |
| 103 if (order == OLDEST_FIRST) { | 182 if (order == OLDEST_FIRST) { |
| 104 size_t offset = 0; | 183 size_t offset = 0; |
| 105 if (max_events > 0 && max_events < entries_.size()) | 184 if (max_events > 0 && max_events < entries_.size()) { |
| 106 offset = entries_.size() - max_events; | 185 // Iterate backwards through the list, decrementing the offset for entries |
|
gauravsh
2013/05/14 23:01:20
update the comment
stevenjb
2013/05/15 16:20:43
Done.
| |
| 186 // that will be skipped. | |
| 187 size_t shown_events = 0; | |
| 188 LogEntryList::const_reverse_iterator riter; | |
| 189 for (riter = entries_.rbegin(); riter != entries_.rend(); ++riter) { | |
| 190 if (riter->log_level > max_level) | |
| 191 continue; | |
| 192 if (++shown_events >= max_events) | |
| 193 break; | |
| 194 } | |
| 195 if (riter != entries_.rend()) | |
| 196 offset = entries_.rend() - riter - 1; | |
| 197 } | |
| 107 for (LogEntryList::const_iterator iter = entries_.begin() + offset; | 198 for (LogEntryList::const_iterator iter = entries_.begin() + offset; |
| 108 iter != entries_.end(); ++iter) { | 199 iter != entries_.end(); ++iter) { |
| 109 result += (*iter).ToString(); | 200 if (iter->log_level > max_level) |
| 201 continue; | |
| 202 result += (*iter).ToString(show_time, show_file, show_desc, format_html); | |
| 110 } | 203 } |
| 111 } else { | 204 } else { |
| 112 size_t nlines = 0; | 205 size_t nlines = 0; |
| 113 // Iterate backwards through the list to show the most recent entries first. | 206 // Iterate backwards through the list to show the most recent entries first. |
| 114 for (LogEntryList::const_reverse_iterator riter = entries_.rbegin(); | 207 for (LogEntryList::const_reverse_iterator riter = entries_.rbegin(); |
| 115 riter != entries_.rend(); ++riter) { | 208 riter != entries_.rend(); ++riter) { |
| 116 result += (*riter).ToString(); | 209 if (riter->log_level > max_level) |
| 210 continue; | |
| 211 result += (*riter).ToString(show_time, show_file, show_desc, format_html); | |
| 117 if (max_events > 0 && ++nlines >= max_events) | 212 if (max_events > 0 && ++nlines >= max_events) |
| 118 break; | 213 break; |
| 119 } | 214 } |
| 120 } | 215 } |
| 121 return result; | 216 return result; |
| 122 } | 217 } |
| 123 | 218 |
| 124 } // namespace | 219 } // namespace |
| 125 | 220 |
| 126 NetworkEventLog* g_network_event_log = NULL; | 221 NetworkEventLog* g_network_event_log = NULL; |
| 222 const LogLevel kDefaultLogLevel = LOG_LEVEL_EVENT; | |
| 127 const size_t kMaxNetworkEventLogEntries = 1000; | 223 const size_t kMaxNetworkEventLogEntries = 1000; |
| 128 | 224 |
| 129 void Initialize() { | 225 void Initialize() { |
| 130 if (g_network_event_log) | 226 if (g_network_event_log) |
| 131 delete g_network_event_log; // reset log | 227 delete g_network_event_log; // reset log |
| 132 g_network_event_log = new NetworkEventLog(); | 228 g_network_event_log = new NetworkEventLog(); |
| 133 } | 229 } |
| 134 | 230 |
| 135 void Shutdown() { | 231 void Shutdown() { |
| 136 delete g_network_event_log; | 232 delete g_network_event_log; |
| 137 g_network_event_log = NULL; | 233 g_network_event_log = NULL; |
| 138 } | 234 } |
| 139 | 235 |
| 140 bool IsInitialized() { | 236 bool IsInitialized() { |
| 141 return g_network_event_log != NULL; | 237 return g_network_event_log != NULL; |
| 142 } | 238 } |
| 143 | 239 |
| 144 void AddEntry(const std::string& module, | 240 namespace internal { |
| 241 | |
| 242 void AddEntry(const char* file, | |
| 243 int file_line, | |
| 244 LogLevel log_level, | |
| 145 const std::string& event, | 245 const std::string& event, |
| 146 const std::string& description) { | 246 const std::string& description) { |
| 147 LogEntry entry(module, event, description); | 247 std::string filestr; |
| 248 if (file) | |
| 249 filestr = base::FilePath(std::string(file)).BaseName().value(); | |
| 250 LogEntry entry(filestr, file_line, log_level, event, description); | |
| 148 if (!g_network_event_log) { | 251 if (!g_network_event_log) { |
| 149 VLOG(1) << entry.ToString(); | 252 entry.SendToVLogOrErrorLog(); |
| 150 return; | 253 return; |
| 151 } | 254 } |
| 152 g_network_event_log->AddEntry(entry); | 255 g_network_event_log->AddLogEntry(entry); |
| 153 } | 256 } |
| 154 | 257 |
| 155 std::string GetAsString(StringOrder order, size_t max_events) { | 258 } // namespace internal |
| 259 | |
| 260 std::string GetAsString(StringOrder order, | |
| 261 const std::string& format, | |
| 262 LogLevel max_level, | |
| 263 size_t max_events) { | |
| 156 if (!g_network_event_log) | 264 if (!g_network_event_log) |
| 157 return "NetworkEventLog not intitialized."; | 265 return "NetworkEventLog not initialized."; |
| 158 return g_network_event_log->GetAsString(order, max_events); | 266 return g_network_event_log->GetAsString(order, format, max_level, max_events); |
| 159 } | 267 } |
| 160 | 268 |
| 161 } // namespace network_event_log | 269 } // namespace network_event_log |
| 162 | 270 |
| 163 } // namespace chromeos | 271 } // namespace chromeos |
| OLD | NEW |