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/i18n/time_formatting.h" | 7 #include "base/i18n/time_formatting.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
| 11 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
| 12 #include "base/values.h" | |
| 12 | 13 |
| 13 namespace chromeos { | 14 namespace chromeos { |
| 14 | 15 |
| 15 namespace network_event_log { | 16 namespace network_event_log { |
| 16 | 17 |
| 17 namespace { | 18 namespace { |
| 18 | 19 |
| 19 struct LogEntry { | 20 struct LogEntry { |
| 20 LogEntry(const std::string& module, | 21 LogEntry(const std::string& file, |
| 22 int file_line, | |
| 23 int log_level, | |
|
gauravsh
2013/05/13 00:34:51
Why is this an int instead of a log-level? std::mi
stevenjb
2013/05/13 19:36:39
Done.
| |
| 21 const std::string& event, | 24 const std::string& event, |
| 22 const std::string& description); | 25 const std::string& description); |
| 23 | 26 |
| 24 std::string ToString() const; | 27 std::string ToString(const std::string& format) const; |
|
gauravsh
2013/05/13 00:34:51
Comment for the format of |format|?
stevenjb
2013/05/13 19:36:39
Changed to use bools
| |
| 25 | 28 |
| 26 bool ContentEquals(const LogEntry& other) const; | 29 bool ContentEquals(const LogEntry& other) const; |
| 27 | 30 |
| 28 std::string module; | 31 std::string file; |
|
pneubeck (no reviews)
2013/05/13 13:16:25
base::Location
stevenjb
2013/05/13 19:36:39
Again, more complexity than I think we want, see S
pneubeck (no reviews)
2013/05/16 08:21:07
With base::Location, the filename would not have t
| |
| 32 int file_line; | |
| 33 int log_level; | |
| 29 std::string event; | 34 std::string event; |
| 30 std::string description; | 35 std::string description; |
| 31 base::Time time; | 36 base::Time time; |
| 32 int count; | 37 int count; |
| 33 }; | 38 }; |
| 34 | 39 |
| 35 LogEntry::LogEntry(const std::string& module, | 40 LogEntry::LogEntry(const std::string& file, |
| 41 int file_line, | |
| 42 int log_level, | |
| 36 const std::string& event, | 43 const std::string& event, |
| 37 const std::string& description) | 44 const std::string& description) |
| 38 : module(module), | 45 : file(file), |
| 46 file_line(file_line), | |
| 47 log_level(log_level), | |
| 39 event(event), | 48 event(event), |
| 40 description(description), | 49 description(description), |
| 41 time(base::Time::Now()), | 50 time(base::Time::Now()), |
| 42 count(1) { | 51 count(1) { |
| 43 } | 52 } |
| 44 | 53 |
| 45 std::string LogEntry::ToString() const { | 54 std::string LogEntry::ToString(const std::string& format) const { |
| 46 std::string line; | 55 std::string line; |
| 47 line += "[" + UTF16ToUTF8(base::TimeFormatShortDateAndTime(time)) + "]"; | 56 if (format.find("time") != std::string::npos) |
| 48 line += " " + module + ":" + event; | 57 line += "[" + UTF16ToUTF8(base::TimeFormatShortDateAndTime(time)) + "] "; |
| 49 if (!description.empty()) | 58 if (format.find("file") != std::string::npos) |
| 59 line += base::StringPrintf("%s:%d ", file.c_str(), file_line); | |
| 60 bool italic = (log_level == LOG_LEVEL_DEBUG && | |
| 61 format.find("html") != std::string::npos); | |
| 62 bool bold = (log_level == LOG_LEVEL_ERROR && | |
| 63 format.find("html") != std::string::npos); | |
| 64 if (italic) | |
| 65 line += "<i>"; | |
| 66 if (bold) | |
| 67 line += "<b>"; | |
| 68 line += event; | |
| 69 if ((format.find("desc") != std::string::npos) && !description.empty()) | |
| 50 line += ": " + description; | 70 line += ": " + description; |
| 71 if (bold) | |
| 72 line += "</b>"; | |
| 73 if (italic) | |
| 74 line += "</i>"; | |
| 75 | |
| 51 if (count > 1) | 76 if (count > 1) |
| 52 line += base::StringPrintf(" (%d)", count); | 77 line += base::StringPrintf(" (%d)", count); |
| 53 line += "\n"; | 78 line += "\n"; |
| 54 return line; | 79 return line; |
| 55 } | 80 } |
| 56 | 81 |
| 57 bool LogEntry::ContentEquals(const LogEntry& other) const { | 82 bool LogEntry::ContentEquals(const LogEntry& other) const { |
| 58 return module == other.module && | 83 return file == other.file && |
| 84 file_line == other.file_line && | |
| 59 event == other.event && | 85 event == other.event && |
| 60 description == other.description; | 86 description == other.description; |
| 61 } | 87 } |
| 62 | 88 |
| 63 typedef std::deque<LogEntry> LogEntryList; | 89 typedef std::deque<LogEntry> LogEntryList; |
|
pneubeck (no reviews)
2013/05/13 13:16:25
depending on how frequent you expect log calls, th
stevenjb
2013/05/13 19:36:39
That doesn't really seem like a good code complexi
| |
| 64 | 90 |
| 65 class NetworkEventLog { | 91 class NetworkEventLog { |
| 66 public: | 92 public: |
| 67 NetworkEventLog() {} | 93 NetworkEventLog() {} |
| 68 ~NetworkEventLog() {} | 94 ~NetworkEventLog() {} |
| 69 | 95 |
| 70 void AddEntry(const LogEntry& entry); | 96 void AddLogEntry(const LogEntry& entry); |
| 71 | 97 |
| 72 std::string GetAsString(StringOrder order, | 98 std::string GetAsString(StringOrder order, |
| 99 const std::string& format, | |
| 100 int max_level, | |
|
gauravsh
2013/05/13 00:34:51
Why is this not a LogLevel?
stevenjb
2013/05/13 19:36:39
Done.
| |
| 73 size_t max_events); | 101 size_t max_events); |
| 74 | 102 |
| 75 private: | 103 private: |
| 76 LogEntryList entries_; | 104 LogEntryList entries_; |
| 77 | 105 |
| 78 DISALLOW_COPY_AND_ASSIGN(NetworkEventLog); | 106 DISALLOW_COPY_AND_ASSIGN(NetworkEventLog); |
| 79 }; | 107 }; |
| 80 | 108 |
| 81 void NetworkEventLog::AddEntry(const LogEntry& entry) { | 109 void NetworkEventLog::AddLogEntry(const LogEntry& entry) { |
| 82 if (!entries_.empty()) { | 110 if (!entries_.empty()) { |
| 83 LogEntry& last = entries_.back(); | 111 LogEntry& last = entries_.back(); |
| 84 if (last.ContentEquals(entry)) { | 112 if (last.ContentEquals(entry)) { |
| 85 // Update count and time for identical events to avoid log spam. | 113 // Update count and time for identical events to avoid log spam. |
| 86 ++last.count; | 114 ++last.count; |
| 115 last.log_level = std::min(last.log_level, entry.log_level); | |
| 87 last.time = base::Time::Now(); | 116 last.time = base::Time::Now(); |
| 88 return; | 117 return; |
| 89 } | 118 } |
| 90 } | 119 } |
| 91 if (entries_.size() >= kMaxNetworkEventLogEntries) | 120 if (entries_.size() >= kMaxNetworkEventLogEntries) |
| 92 entries_.pop_front(); | 121 entries_.pop_front(); |
| 93 entries_.push_back(entry); | 122 entries_.push_back(entry); |
| 94 VLOG(1) << entry.ToString(); | 123 if (entry.log_level == LOG_LEVEL_ERROR) |
| 124 LOG(ERROR) << entry.ToString("time,file,desc"); | |
| 125 else | |
| 126 VLOG(1) << entry.ToString("time,file,desc"); | |
| 95 } | 127 } |
| 96 | 128 |
| 97 std::string NetworkEventLog::GetAsString(StringOrder order, | 129 std::string NetworkEventLog::GetAsString(StringOrder order, |
| 130 const std::string& format, | |
| 131 int max_level, | |
| 98 size_t max_events) { | 132 size_t max_events) { |
| 99 if (entries_.empty()) | 133 if (entries_.empty()) |
| 100 return "No Log Entries."; | 134 return "No Log Entries."; |
| 101 | 135 |
| 102 std::string result; | 136 std::string result; |
| 103 if (order == OLDEST_FIRST) { | 137 if (order == OLDEST_FIRST) { |
| 104 size_t offset = 0; | 138 size_t offset = 0; |
| 105 if (max_events > 0 && max_events < entries_.size()) | 139 if (max_events > 0 && max_events < entries_.size()) { |
| 106 offset = entries_.size() - max_events; | 140 offset = entries_.size() - max_events; |
| 141 // Iterate backwards through the list, decramenting the offset for entries | |
|
gauravsh
2013/05/13 00:34:51
decrementing
stevenjb
2013/05/13 19:36:39
Done.
| |
| 142 // that will be skipped. | |
| 143 for (LogEntryList::const_reverse_iterator riter = entries_.rbegin(); | |
| 144 riter != entries_.rend(); ++riter) { | |
| 145 if (riter->log_level > max_level) { | |
| 146 if (--offset == 0) | |
|
gauravsh
2013/05/13 00:34:51
BUG? Wouldn't this end up decrementing the offset
stevenjb
2013/05/13 19:36:39
You're right, I need to check the shown events aga
| |
| 147 break; | |
| 148 } | |
| 149 } | |
| 150 } | |
| 107 for (LogEntryList::const_iterator iter = entries_.begin() + offset; | 151 for (LogEntryList::const_iterator iter = entries_.begin() + offset; |
| 108 iter != entries_.end(); ++iter) { | 152 iter != entries_.end(); ++iter) { |
| 109 result += (*iter).ToString(); | 153 if (iter->log_level > max_level) |
| 154 continue; | |
| 155 result += (*iter).ToString(format); | |
| 110 } | 156 } |
| 111 } else { | 157 } else { |
| 112 size_t nlines = 0; | 158 size_t nlines = 0; |
| 113 // Iterate backwards through the list to show the most recent entries first. | 159 // Iterate backwards through the list to show the most recent entries first. |
| 114 for (LogEntryList::const_reverse_iterator riter = entries_.rbegin(); | 160 for (LogEntryList::const_reverse_iterator riter = entries_.rbegin(); |
| 115 riter != entries_.rend(); ++riter) { | 161 riter != entries_.rend(); ++riter) { |
| 116 result += (*riter).ToString(); | 162 if (riter->log_level > max_level) |
| 163 continue; | |
| 164 result += (*riter).ToString(format); | |
| 117 if (max_events > 0 && ++nlines >= max_events) | 165 if (max_events > 0 && ++nlines >= max_events) |
| 118 break; | 166 break; |
| 119 } | 167 } |
| 120 } | 168 } |
| 121 return result; | 169 return result; |
| 122 } | 170 } |
| 123 | 171 |
| 124 } // namespace | 172 } // namespace |
| 125 | 173 |
| 126 NetworkEventLog* g_network_event_log = NULL; | 174 NetworkEventLog* g_network_event_log = NULL; |
| 175 const int kDefaultLogLevel = 1; | |
| 127 const size_t kMaxNetworkEventLogEntries = 1000; | 176 const size_t kMaxNetworkEventLogEntries = 1000; |
| 128 | 177 |
| 129 void Initialize() { | 178 void Initialize() { |
| 130 if (g_network_event_log) | 179 if (g_network_event_log) |
| 131 delete g_network_event_log; // reset log | 180 delete g_network_event_log; // reset log |
| 132 g_network_event_log = new NetworkEventLog(); | 181 g_network_event_log = new NetworkEventLog(); |
| 133 } | 182 } |
| 134 | 183 |
| 135 void Shutdown() { | 184 void Shutdown() { |
| 136 delete g_network_event_log; | 185 delete g_network_event_log; |
| 137 g_network_event_log = NULL; | 186 g_network_event_log = NULL; |
| 138 } | 187 } |
| 139 | 188 |
| 140 bool IsInitialized() { | 189 bool IsInitialized() { |
| 141 return g_network_event_log != NULL; | 190 return g_network_event_log != NULL; |
| 142 } | 191 } |
| 143 | 192 |
| 144 void AddEntry(const std::string& module, | 193 void AddEntry(const char* file, |
| 194 int file_line, | |
| 195 LogLevel log_level, | |
| 145 const std::string& event, | 196 const std::string& event, |
| 146 const std::string& description) { | 197 const std::string& description) { |
| 147 LogEntry entry(module, event, description); | 198 std::string filestr; |
|
pneubeck (no reviews)
2013/05/13 13:16:25
FilePath::BaseName()
stevenjb
2013/05/13 19:36:39
Done.
| |
| 199 if (file) { | |
| 200 filestr = std::string(file); | |
| 201 size_t n = filestr.find_last_of('/'); | |
| 202 if (n) | |
| 203 filestr = filestr.substr(n+1); | |
| 204 } | |
| 205 LogEntry entry(filestr, file_line, log_level, event, description); | |
| 148 if (!g_network_event_log) { | 206 if (!g_network_event_log) { |
| 149 VLOG(1) << entry.ToString(); | 207 VLOG(1) << entry.ToString("time,file,desc"); |
|
pneubeck (no reviews)
2013/05/13 13:16:25
this should respect the log level.
stevenjb
2013/05/13 19:36:39
Done.
| |
| 150 return; | 208 return; |
| 151 } | 209 } |
| 152 g_network_event_log->AddEntry(entry); | 210 g_network_event_log->AddLogEntry(entry); |
| 153 } | 211 } |
| 154 | 212 |
| 155 std::string GetAsString(StringOrder order, size_t max_events) { | 213 std::string GetAsString(StringOrder order, |
| 214 const std::string& format, | |
| 215 int max_level, | |
| 216 size_t max_events) { | |
| 156 if (!g_network_event_log) | 217 if (!g_network_event_log) |
| 157 return "NetworkEventLog not intitialized."; | 218 return "NetworkEventLog not intitialized."; |
| 158 return g_network_event_log->GetAsString(order, max_events); | 219 return g_network_event_log->GetAsString(order, format, max_level, max_events); |
| 220 } | |
| 221 | |
| 222 std::string DBusValueAsString(const base::Value& value) { | |
| 223 if (value.GetType() == base::Value::TYPE_BOOLEAN) { | |
| 224 bool bval = false; | |
| 225 value.GetAsBoolean(&bval); | |
| 226 return bval ? "true" : "false"; | |
| 227 } else if (value.GetType() == base::Value::TYPE_INTEGER) { | |
| 228 int intval = 0; | |
| 229 value.GetAsInteger(&intval); | |
| 230 return base::StringPrintf("%d", intval); | |
| 231 } else if (value.GetType() == base::Value::TYPE_DOUBLE) { | |
| 232 double dval = 0; | |
| 233 value.GetAsDouble(&dval); | |
| 234 return base::StringPrintf("%g", dval); | |
| 235 } else if (value.GetType() == base::Value::TYPE_STRING) { | |
| 236 std::string vstr; | |
| 237 value.GetAsString(&vstr); | |
| 238 return vstr; | |
| 239 } | |
| 240 return ""; | |
| 159 } | 241 } |
| 160 | 242 |
| 161 } // namespace network_event_log | 243 } // namespace network_event_log |
| 162 | 244 |
| 163 } // namespace chromeos | 245 } // namespace chromeos |
| OLD | NEW |