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 offset = entries_.size() - max_events; |
186 // Iterate backwards through the list, decrementing the offset for entries | |
187 // that will be skipped. | |
188 size_t shown_events = 0; | |
189 for (LogEntryList::const_reverse_iterator riter = entries_.rbegin(); | |
190 riter != entries_.rend(); ++riter) { | |
191 if (riter->log_level > max_level) { | |
192 if (--offset == 0) | |
193 break; | |
194 } | |
195 if (++shown_events >= max_events) | |
gauravsh
2013/05/14 00:01:39
You want an else here, or this will bail too early
stevenjb
2013/05/14 00:27:42
Bah, where's my brain, must be Monday. I was think
| |
196 break; | |
197 } | |
198 } | |
107 for (LogEntryList::const_iterator iter = entries_.begin() + offset; | 199 for (LogEntryList::const_iterator iter = entries_.begin() + offset; |
108 iter != entries_.end(); ++iter) { | 200 iter != entries_.end(); ++iter) { |
109 result += (*iter).ToString(); | 201 if (iter->log_level > max_level) |
202 continue; | |
203 result += (*iter).ToString(show_time, show_file, show_desc, format_html); | |
110 } | 204 } |
111 } else { | 205 } else { |
112 size_t nlines = 0; | 206 size_t nlines = 0; |
113 // Iterate backwards through the list to show the most recent entries first. | 207 // Iterate backwards through the list to show the most recent entries first. |
114 for (LogEntryList::const_reverse_iterator riter = entries_.rbegin(); | 208 for (LogEntryList::const_reverse_iterator riter = entries_.rbegin(); |
115 riter != entries_.rend(); ++riter) { | 209 riter != entries_.rend(); ++riter) { |
116 result += (*riter).ToString(); | 210 if (riter->log_level > max_level) |
211 continue; | |
212 result += (*riter).ToString(show_time, show_file, show_desc, format_html); | |
117 if (max_events > 0 && ++nlines >= max_events) | 213 if (max_events > 0 && ++nlines >= max_events) |
118 break; | 214 break; |
119 } | 215 } |
120 } | 216 } |
121 return result; | 217 return result; |
122 } | 218 } |
123 | 219 |
124 } // namespace | 220 } // namespace |
125 | 221 |
126 NetworkEventLog* g_network_event_log = NULL; | 222 NetworkEventLog* g_network_event_log = NULL; |
223 const LogLevel kDefaultLogLevel = LOG_LEVEL_EVENT; | |
127 const size_t kMaxNetworkEventLogEntries = 1000; | 224 const size_t kMaxNetworkEventLogEntries = 1000; |
128 | 225 |
129 void Initialize() { | 226 void Initialize() { |
130 if (g_network_event_log) | 227 if (g_network_event_log) |
131 delete g_network_event_log; // reset log | 228 delete g_network_event_log; // reset log |
132 g_network_event_log = new NetworkEventLog(); | 229 g_network_event_log = new NetworkEventLog(); |
133 } | 230 } |
134 | 231 |
135 void Shutdown() { | 232 void Shutdown() { |
136 delete g_network_event_log; | 233 delete g_network_event_log; |
137 g_network_event_log = NULL; | 234 g_network_event_log = NULL; |
138 } | 235 } |
139 | 236 |
140 bool IsInitialized() { | 237 bool IsInitialized() { |
141 return g_network_event_log != NULL; | 238 return g_network_event_log != NULL; |
142 } | 239 } |
143 | 240 |
144 void AddEntry(const std::string& module, | 241 namespace internal { |
242 | |
243 void AddEntry(const char* file, | |
244 int file_line, | |
245 LogLevel log_level, | |
145 const std::string& event, | 246 const std::string& event, |
146 const std::string& description) { | 247 const std::string& description) { |
147 LogEntry entry(module, event, description); | 248 std::string filestr; |
249 if (file) | |
250 filestr = base::FilePath(std::string(file)).BaseName().value(); | |
251 LogEntry entry(filestr, file_line, log_level, event, description); | |
148 if (!g_network_event_log) { | 252 if (!g_network_event_log) { |
149 VLOG(1) << entry.ToString(); | 253 entry.SendToVLogOrErrorLog(); |
150 return; | 254 return; |
151 } | 255 } |
152 g_network_event_log->AddEntry(entry); | 256 g_network_event_log->AddLogEntry(entry); |
153 } | 257 } |
154 | 258 |
155 std::string GetAsString(StringOrder order, size_t max_events) { | 259 } // namespace internal |
260 | |
261 std::string GetAsString(StringOrder order, | |
262 const std::string& format, | |
263 LogLevel max_level, | |
264 size_t max_events) { | |
156 if (!g_network_event_log) | 265 if (!g_network_event_log) |
157 return "NetworkEventLog not intitialized."; | 266 return "NetworkEventLog not initialized."; |
158 return g_network_event_log->GetAsString(order, max_events); | 267 return g_network_event_log->GetAsString(order, format, max_level, max_events); |
159 } | 268 } |
160 | 269 |
161 } // namespace network_event_log | 270 } // namespace network_event_log |
162 | 271 |
163 } // namespace chromeos | 272 } // namespace chromeos |
OLD | NEW |