OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/device_event_log_impl.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <list> | 8 #include <list> |
9 | 9 |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
11 #include "base/json/json_string_value_serializer.h" | 11 #include "base/json/json_string_value_serializer.h" |
12 #include "base/json/json_writer.h" | 12 #include "base/json/json_writer.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
15 #include "base/strings/string_tokenizer.h" | 15 #include "base/strings/string_tokenizer.h" |
16 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
17 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
18 #include "base/values.h" | 18 #include "base/values.h" |
19 #include "net/base/escape.h" | 19 #include "net/base/escape.h" |
20 | 20 |
21 namespace chromeos { | 21 namespace chromeos { |
22 namespace network_event_log { | 22 |
| 23 namespace device_event_log { |
23 | 24 |
24 namespace { | 25 namespace { |
25 | 26 |
| 27 const char* kLogLevelName[] = {"Error", "User", "Event", "Debug"}; |
| 28 |
| 29 const char* kLogTypeNetworkDesc = "Network"; |
| 30 const char* kLogTypePowerDesc = "Power"; |
| 31 |
| 32 std::string GetLogTypeString(LogType type) { |
| 33 if (type == LOG_TYPE_NETWORK) |
| 34 return kLogTypeNetworkDesc; |
| 35 if (type == LOG_TYPE_POWER) |
| 36 return kLogTypePowerDesc; |
| 37 NOTREACHED(); |
| 38 return "Unknown"; |
| 39 } |
| 40 |
26 std::string DateAndTimeWithMicroseconds(const base::Time& time) { | 41 std::string DateAndTimeWithMicroseconds(const base::Time& time) { |
27 base::Time::Exploded exploded; | 42 base::Time::Exploded exploded; |
28 time.LocalExplode(&exploded); | 43 time.LocalExplode(&exploded); |
29 // base::Time::Exploded does not include microseconds, but sometimes we need | 44 // base::Time::Exploded does not include microseconds, but sometimes we need |
30 // microseconds, so append '.' + usecs to the end of the formatted string. | 45 // microseconds, so append '.' + usecs to the end of the formatted string. |
31 int usecs = static_cast<int>(fmod(time.ToDoubleT() * 1000000, 1000000)); | 46 int usecs = static_cast<int>(fmod(time.ToDoubleT() * 1000000, 1000000)); |
32 return base::StringPrintf("%04d/%02d/%02d %02d:%02d:%02d.%06d", | 47 return base::StringPrintf("%04d/%02d/%02d %02d:%02d:%02d.%06d", exploded.year, |
33 exploded.year, | 48 exploded.month, exploded.day_of_month, |
34 exploded.month, | 49 exploded.hour, exploded.minute, exploded.second, |
35 exploded.day_of_month, | |
36 exploded.hour, | |
37 exploded.minute, | |
38 exploded.second, | |
39 usecs); | 50 usecs); |
40 } | 51 } |
41 | 52 |
42 std::string TimeWithSeconds(const base::Time& time) { | 53 std::string TimeWithSeconds(const base::Time& time) { |
43 base::Time::Exploded exploded; | 54 base::Time::Exploded exploded; |
44 time.LocalExplode(&exploded); | 55 time.LocalExplode(&exploded); |
45 return base::StringPrintf("%02d:%02d:%02d", | 56 return base::StringPrintf("%02d:%02d:%02d", exploded.hour, exploded.minute, |
46 exploded.hour, | |
47 exploded.minute, | |
48 exploded.second); | 57 exploded.second); |
49 } | 58 } |
50 | 59 |
51 std::string TimeWithMillieconds(const base::Time& time) { | 60 std::string TimeWithMillieconds(const base::Time& time) { |
52 base::Time::Exploded exploded; | 61 base::Time::Exploded exploded; |
53 time.LocalExplode(&exploded); | 62 time.LocalExplode(&exploded); |
54 return base::StringPrintf("%02d:%02d:%02d.%03d", | 63 return base::StringPrintf("%02d:%02d:%02d.%03d", exploded.hour, |
55 exploded.hour, | 64 exploded.minute, exploded.second, |
56 exploded.minute, | |
57 exploded.second, | |
58 exploded.millisecond); | 65 exploded.millisecond); |
59 } | 66 } |
60 | 67 |
61 class NetworkEventLog; | 68 // Defined below for easier review. TODO(stevenjb): Move implementation here. |
62 NetworkEventLog* g_network_event_log = NULL; | 69 std::string GetHtmlText(LogLevel log_level, const std::string& event); |
63 size_t g_max_network_event_log_entries = 4000; | |
64 const char* kLogLevelName[] = {"Error", "User", "Event", "Debug"}; | |
65 | 70 |
66 struct LogEntry { | 71 std::string LogEntryToString(const DeviceEventLogImpl::LogEntry& log_entry, |
67 LogEntry(const std::string& file, | 72 bool show_time, |
68 int file_line, | 73 bool show_file, |
69 LogLevel log_level, | 74 bool show_type, |
70 const std::string& event, | 75 bool show_level, |
71 const std::string& description); | 76 bool format_html) { |
72 | |
73 std::string ToString(bool show_time, | |
74 bool show_file, | |
75 bool show_level, | |
76 bool show_desc, | |
77 bool format_html) const; | |
78 void ToDictionary(base::DictionaryValue*) const; | |
79 | |
80 std::string GetNormalText(bool show_desc) const; | |
81 std::string GetHtmlText(bool show_desc) const; | |
82 std::string GetAsJSON() const; | |
83 | |
84 void SendToVLogOrErrorLog() const; | |
85 | |
86 bool ContentEquals(const LogEntry& other) const; | |
87 | |
88 std::string file; | |
89 int file_line; | |
90 LogLevel log_level; | |
91 std::string event; | |
92 std::string description; | |
93 base::Time time; | |
94 int count; | |
95 }; | |
96 | |
97 LogEntry::LogEntry(const std::string& file, | |
98 int file_line, | |
99 LogLevel log_level, | |
100 const std::string& event, | |
101 const std::string& description) | |
102 : file(file), | |
103 file_line(file_line), | |
104 log_level(log_level), | |
105 event(event), | |
106 description(description), | |
107 time(base::Time::Now()), | |
108 count(1) {} | |
109 | |
110 std::string LogEntry::ToString(bool show_time, | |
111 bool show_file, | |
112 bool show_level, | |
113 bool show_desc, | |
114 bool format_html) const { | |
115 std::string line; | 77 std::string line; |
116 if (show_time) | 78 if (show_time) |
117 line += "[" + TimeWithMillieconds(time) + "] "; | 79 line += "[" + TimeWithMillieconds(log_entry.time) + "] "; |
| 80 if (show_type) |
| 81 line += GetLogTypeString(log_entry.log_type) + ": "; |
118 if (show_level) { | 82 if (show_level) { |
119 const char* kLevelDesc[] = { | 83 const char* kLevelDesc[] = {"ERROR", "USER", "EVENT", "DEBUG"}; |
120 "ERROR", | 84 line += base::StringPrintf("%s: ", kLevelDesc[log_entry.log_level]); |
121 "USER", | |
122 "EVENT", | |
123 "DEBUG" | |
124 }; | |
125 line += base::StringPrintf("%s: ", kLevelDesc[log_level]); | |
126 } | 85 } |
127 if (show_file) { | 86 if (show_file) { |
128 std::string filestr = format_html ? net::EscapeForHTML(file) : file; | 87 std::string filestr = |
129 line += base::StringPrintf("%s:%d ", file.c_str(), file_line); | 88 format_html ? net::EscapeForHTML(log_entry.file) : log_entry.file; |
| 89 line += base::StringPrintf("%s:%d ", log_entry.file.c_str(), |
| 90 log_entry.file_line); |
130 } | 91 } |
131 line += format_html ? GetHtmlText(show_desc) : GetNormalText(show_desc); | 92 line += format_html ? GetHtmlText(log_entry.log_level, log_entry.event) |
132 if (count > 1) | 93 : log_entry.event; |
133 line += base::StringPrintf(" (%d)", count); | 94 if (log_entry.count > 1) |
| 95 line += base::StringPrintf(" (%d)", log_entry.count); |
134 return line; | 96 return line; |
135 } | 97 } |
136 | 98 |
137 void LogEntry::ToDictionary(base::DictionaryValue* output) const { | 99 void LogEntryToDictionary(const DeviceEventLogImpl::LogEntry& log_entry, |
138 output->SetString("timestamp", DateAndTimeWithMicroseconds(time)); | 100 base::DictionaryValue* output) { |
139 output->SetString("timestampshort", TimeWithSeconds(time)); | 101 output->SetString("timestamp", DateAndTimeWithMicroseconds(log_entry.time)); |
140 output->SetString("level", kLogLevelName[log_level]); | 102 output->SetString("timestampshort", TimeWithSeconds(log_entry.time)); |
141 output->SetString("file", | 103 output->SetString("level", kLogLevelName[log_entry.log_level]); |
142 base::StringPrintf("%s:%d ", file.c_str(), file_line)); | 104 output->SetString("type", GetLogTypeString(log_entry.log_type)); |
143 output->SetString("event", event); | 105 output->SetString("file", base::StringPrintf("%s:%d ", log_entry.file.c_str(), |
144 output->SetString("description", description); | 106 log_entry.file_line)); |
| 107 output->SetString("event", log_entry.event); |
145 } | 108 } |
146 | 109 |
147 std::string LogEntry::GetAsJSON() const { | 110 std::string LogEntryAsJSON(const DeviceEventLogImpl::LogEntry& log_entry) { |
148 base::DictionaryValue entry; | 111 base::DictionaryValue entry_dict; |
149 ToDictionary(&entry); | 112 LogEntryToDictionary(log_entry, &entry_dict); |
150 std::string json; | 113 std::string json; |
151 JSONStringValueSerializer serializer(&json); | 114 JSONStringValueSerializer serializer(&json); |
152 if (!serializer.Serialize(entry)) { | 115 if (!serializer.Serialize(entry_dict)) { |
153 LOG(ERROR) << "Failed to serialize to JSON"; | 116 LOG(ERROR) << "Failed to serialize to JSON"; |
154 } | 117 } |
155 return json; | 118 return json; |
156 } | 119 } |
157 | 120 |
158 std::string LogEntry::GetNormalText(bool show_desc) const { | 121 std::string GetHtmlText(LogLevel log_level, const std::string& event) { |
159 std::string text = event; | |
160 if (show_desc && !description.empty()) | |
161 text += ": " + description; | |
162 return text; | |
163 } | |
164 | |
165 std::string LogEntry::GetHtmlText(bool show_desc) const { | |
166 std::string text; | 122 std::string text; |
167 if (log_level == LOG_LEVEL_DEBUG) | 123 if (log_level == LOG_LEVEL_DEBUG) |
168 text += "<i>"; | 124 text += "<i>"; |
169 else if (log_level == LOG_LEVEL_USER) | 125 else if (log_level == LOG_LEVEL_USER) |
170 text += "<b>"; | 126 text += "<b>"; |
171 else if (log_level == LOG_LEVEL_ERROR) | 127 else if (log_level == LOG_LEVEL_ERROR) |
172 text += "<b><i>"; | 128 text += "<b><i>"; |
173 | 129 |
174 text += event; | 130 text += net::EscapeForHTML(event); |
175 if (show_desc && !description.empty()) | |
176 text += ": " + net::EscapeForHTML(description); | |
177 | 131 |
178 if (log_level == LOG_LEVEL_DEBUG) | 132 if (log_level == LOG_LEVEL_DEBUG) |
179 text += "</i>"; | 133 text += "</i>"; |
180 else if (log_level == LOG_LEVEL_USER) | 134 else if (log_level == LOG_LEVEL_USER) |
181 text += "</b>"; | 135 text += "</b>"; |
182 else if (log_level == LOG_LEVEL_ERROR) | 136 else if (log_level == LOG_LEVEL_ERROR) |
183 text += "</i></b>"; | 137 text += "</i></b>"; |
184 return text; | 138 return text; |
185 } | 139 } |
186 | 140 |
187 void LogEntry::SendToVLogOrErrorLog() const { | 141 void SendLogEntryToVLogOrErrorLog( |
188 if (log_level != LOG_LEVEL_ERROR && !VLOG_IS_ON(1)) | 142 const DeviceEventLogImpl::LogEntry& log_entry) { |
| 143 if (log_entry.log_level != LOG_LEVEL_ERROR && !VLOG_IS_ON(1)) |
189 return; | 144 return; |
190 const bool show_time = true; | 145 const bool show_time = true; |
191 const bool show_file = true; | 146 const bool show_file = true; |
| 147 const bool show_type = true; |
192 const bool show_level = false; | 148 const bool show_level = false; |
193 const bool show_desc = true; | |
194 const bool format_html = false; | 149 const bool format_html = false; |
195 std::string output = | 150 std::string output = LogEntryToString(log_entry, show_time, show_file, |
196 ToString(show_time, show_file, show_level, show_desc, format_html); | 151 show_type, show_level, format_html); |
197 if (log_level == LOG_LEVEL_ERROR) | 152 if (log_entry.log_level == LOG_LEVEL_ERROR) |
198 LOG(ERROR) << output; | 153 LOG(ERROR) << output; |
199 else | 154 else |
200 VLOG(1) << output; | 155 VLOG(1) << output; |
201 } | 156 } |
202 | 157 |
203 bool LogEntry::ContentEquals(const LogEntry& other) const { | 158 bool LogEntryMatches(const DeviceEventLogImpl::LogEntry& first, |
204 return file == other.file && | 159 const DeviceEventLogImpl::LogEntry& second) { |
205 file_line == other.file_line && | 160 return first.file == second.file && first.file_line == second.file_line && |
206 event == other.event && | 161 first.log_level == second.log_level && |
207 description == other.description; | 162 first.log_type == second.log_type && first.event == second.event; |
| 163 } |
| 164 |
| 165 bool LogEntryMatchesType(const DeviceEventLogImpl::LogEntry& entry, |
| 166 LogType type) { |
| 167 if (type == LOG_TYPE_ALL) |
| 168 return true; |
| 169 if (type == LOG_TYPE_NON_NETWORK && entry.log_type != LOG_TYPE_NETWORK) |
| 170 return true; |
| 171 return type == entry.log_type; |
208 } | 172 } |
209 | 173 |
210 void GetFormat(const std::string& format_string, | 174 void GetFormat(const std::string& format_string, |
211 bool* show_time, | 175 bool* show_time, |
212 bool* show_file, | 176 bool* show_file, |
| 177 bool* show_type, |
213 bool* show_level, | 178 bool* show_level, |
214 bool* show_desc, | |
215 bool* format_html, | 179 bool* format_html, |
216 bool* format_json) { | 180 bool* format_json) { |
217 base::StringTokenizer tokens(format_string, ","); | 181 base::StringTokenizer tokens(format_string, ","); |
218 *show_time = false; | 182 *show_time = false; |
219 *show_file = false; | 183 *show_file = false; |
| 184 *show_type = false; |
220 *show_level = false; | 185 *show_level = false; |
221 *show_desc = false; | |
222 *format_html = false; | 186 *format_html = false; |
223 *format_json = false; | 187 *format_json = false; |
224 while (tokens.GetNext()) { | 188 while (tokens.GetNext()) { |
225 std::string tok(tokens.token()); | 189 std::string tok(tokens.token()); |
226 if (tok == "time") | 190 if (tok == "time") |
227 *show_time = true; | 191 *show_time = true; |
228 if (tok == "file") | 192 if (tok == "file") |
229 *show_file = true; | 193 *show_file = true; |
| 194 if (tok == "type") |
| 195 *show_type = true; |
230 if (tok == "level") | 196 if (tok == "level") |
231 *show_level = true; | 197 *show_level = true; |
232 if (tok == "desc") | |
233 *show_desc = true; | |
234 if (tok == "html") | 198 if (tok == "html") |
235 *format_html = true; | 199 *format_html = true; |
236 if (tok == "json") | 200 if (tok == "json") |
237 *format_json = true; | 201 *format_json = true; |
238 } | 202 } |
239 } | 203 } |
240 | 204 |
241 typedef std::list<LogEntry> LogEntryList; | 205 } // namespace |
242 | 206 |
243 class NetworkEventLog { | 207 // static |
244 public: | 208 void DeviceEventLogImpl::SendToVLogOrErrorLog(const char* file, |
245 NetworkEventLog() {} | 209 int file_line, |
246 ~NetworkEventLog() {} | 210 LogType log_type, |
| 211 LogLevel log_level, |
| 212 const std::string& event) { |
| 213 LogEntry entry(file, file_line, log_type, log_level, event); |
| 214 SendLogEntryToVLogOrErrorLog(entry); |
| 215 } |
247 | 216 |
248 void AddLogEntry(const LogEntry& entry); | 217 DeviceEventLogImpl::DeviceEventLogImpl(size_t max_entries) |
| 218 : max_entries_(max_entries) { |
| 219 } |
249 | 220 |
250 std::string GetAsString(StringOrder order, | 221 DeviceEventLogImpl::~DeviceEventLogImpl() { |
251 const std::string& format, | 222 } |
252 LogLevel max_level, | |
253 size_t max_events); | |
254 | 223 |
255 LogEntryList& entries() { return entries_; } | 224 void DeviceEventLogImpl::AddEntry(const char* file, |
| 225 int file_line, |
| 226 LogType log_type, |
| 227 LogLevel log_level, |
| 228 const std::string& event) { |
| 229 LogEntry entry(file, file_line, log_type, log_level, event); |
| 230 AddLogEntry(entry); |
| 231 } |
256 | 232 |
257 private: | 233 void DeviceEventLogImpl::AddLogEntry(const LogEntry& entry) { |
258 LogEntryList entries_; | |
259 | |
260 DISALLOW_COPY_AND_ASSIGN(NetworkEventLog); | |
261 }; | |
262 | |
263 void NetworkEventLog::AddLogEntry(const LogEntry& entry) { | |
264 if (!entries_.empty()) { | 234 if (!entries_.empty()) { |
265 LogEntry& last = entries_.back(); | 235 LogEntry& last = entries_.back(); |
266 if (last.ContentEquals(entry)) { | 236 if (LogEntryMatches(last, entry)) { |
267 // Update count and time for identical events to avoid log spam. | 237 // Update count and time for identical events to avoid log spam. |
268 ++last.count; | 238 ++last.count; |
269 last.log_level = std::min(last.log_level, entry.log_level); | 239 last.log_level = std::min(last.log_level, entry.log_level); |
270 last.time = base::Time::Now(); | 240 last.time = base::Time::Now(); |
271 return; | 241 return; |
272 } | 242 } |
273 } | 243 } |
274 if (entries_.size() >= g_max_network_event_log_entries) { | 244 if (entries_.size() >= max_entries_) { |
275 const size_t max_error_entries = g_max_network_event_log_entries / 2; | 245 const size_t max_error_entries = max_entries_ / 2; |
276 // Remove the first (oldest) non-error entry, or the oldest entry if more | 246 // Remove the first (oldest) non-error entry, or the oldest entry if more |
277 // than half the entries are errors. | 247 // than half the entries are errors. |
278 size_t error_count = 0; | 248 size_t error_count = 0; |
279 for (LogEntryList::iterator iter = entries_.begin(); iter != entries_.end(); | 249 for (LogEntryList::iterator iter = entries_.begin(); iter != entries_.end(); |
280 ++iter) { | 250 ++iter) { |
281 if (iter->log_level != LOG_LEVEL_ERROR) { | 251 if (iter->log_level != LOG_LEVEL_ERROR) { |
282 entries_.erase(iter); | 252 entries_.erase(iter); |
283 break; | 253 break; |
284 } | 254 } |
285 if (++error_count > max_error_entries) { | 255 if (++error_count > max_error_entries) { |
286 // Too many error entries, remove the oldest entry. | 256 // Too many error entries, remove the oldest entry. |
287 entries_.pop_front(); | 257 entries_.pop_front(); |
288 break; | 258 break; |
289 } | 259 } |
290 } | 260 } |
291 } | 261 } |
292 entries_.push_back(entry); | 262 entries_.push_back(entry); |
293 entry.SendToVLogOrErrorLog(); | 263 SendLogEntryToVLogOrErrorLog(entry); |
294 } | 264 } |
295 | 265 |
296 std::string NetworkEventLog::GetAsString(StringOrder order, | 266 std::string DeviceEventLogImpl::GetAsString(StringOrder order, |
297 const std::string& format, | 267 const std::string& format, |
298 LogLevel max_level, | 268 LogType log_type, |
299 size_t max_events) { | 269 LogLevel max_level, |
| 270 size_t max_events) { |
300 if (entries_.empty()) | 271 if (entries_.empty()) |
301 return "No Log Entries."; | 272 return "No Log Entries."; |
302 | 273 |
303 bool show_time, show_file, show_level, show_desc, format_html, format_json; | 274 bool show_time, show_file, show_type, show_level, format_html, format_json; |
304 GetFormat(format, | 275 GetFormat(format, &show_time, &show_file, &show_type, &show_level, |
305 &show_time, | 276 &format_html, &format_json); |
306 &show_file, | |
307 &show_level, | |
308 &show_desc, | |
309 &format_html, | |
310 &format_json); | |
311 | 277 |
312 std::string result; | 278 std::string result; |
313 base::ListValue log_entries; | 279 base::ListValue log_entries; |
314 if (order == OLDEST_FIRST) { | 280 if (order == OLDEST_FIRST) { |
315 size_t offset = 0; | 281 size_t offset = 0; |
316 if (max_events > 0 && max_events < entries_.size()) { | 282 if (max_events > 0 && max_events < entries_.size()) { |
317 // Iterate backwards through the list skipping uninteresting entries to | 283 // Iterate backwards through the list skipping uninteresting entries to |
318 // determine the first entry to include. | 284 // determine the first entry to include. |
319 size_t shown_events = 0; | 285 size_t shown_events = 0; |
320 size_t num_entries = 0; | 286 size_t num_entries = 0; |
321 for (LogEntryList::const_reverse_iterator riter = entries_.rbegin(); | 287 for (LogEntryList::const_reverse_iterator riter = entries_.rbegin(); |
322 riter != entries_.rend(); | 288 riter != entries_.rend(); ++riter) { |
323 ++riter) { | |
324 ++num_entries; | 289 ++num_entries; |
| 290 if (!LogEntryMatchesType(*riter, log_type)) |
| 291 continue; |
325 if (riter->log_level > max_level) | 292 if (riter->log_level > max_level) |
326 continue; | 293 continue; |
327 if (++shown_events >= max_events) | 294 if (++shown_events >= max_events) |
328 break; | 295 break; |
329 } | 296 } |
330 offset = entries_.size() - num_entries; | 297 offset = entries_.size() - num_entries; |
331 } | 298 } |
332 for (LogEntryList::const_iterator iter = entries_.begin(); | 299 for (LogEntryList::const_iterator iter = entries_.begin(); |
333 iter != entries_.end(); | 300 iter != entries_.end(); ++iter) { |
334 ++iter) { | |
335 if (offset > 0) { | 301 if (offset > 0) { |
336 --offset; | 302 --offset; |
337 continue; | 303 continue; |
338 } | 304 } |
| 305 if (!LogEntryMatchesType(*iter, log_type)) |
| 306 continue; |
339 if (iter->log_level > max_level) | 307 if (iter->log_level > max_level) |
340 continue; | 308 continue; |
341 if (format_json) { | 309 if (format_json) { |
342 log_entries.AppendString((*iter).GetAsJSON()); | 310 log_entries.AppendString(LogEntryAsJSON(*iter)); |
343 } else { | 311 } else { |
344 result += (*iter).ToString( | 312 result += LogEntryToString(*iter, show_time, show_file, show_type, |
345 show_time, show_file, show_level, show_desc, format_html); | 313 show_level, format_html); |
346 result += "\n"; | 314 result += "\n"; |
347 } | 315 } |
348 } | 316 } |
349 } else { | 317 } else { |
350 size_t nlines = 0; | 318 size_t nlines = 0; |
351 // Iterate backwards through the list to show the most recent entries first. | 319 // Iterate backwards through the list to show the most recent entries first. |
352 for (LogEntryList::const_reverse_iterator riter = entries_.rbegin(); | 320 for (LogEntryList::const_reverse_iterator riter = entries_.rbegin(); |
353 riter != entries_.rend(); | 321 riter != entries_.rend(); ++riter) { |
354 ++riter) { | 322 if (!LogEntryMatchesType(*riter, log_type)) |
| 323 continue; |
355 if (riter->log_level > max_level) | 324 if (riter->log_level > max_level) |
356 continue; | 325 continue; |
357 if (format_json) { | 326 if (format_json) { |
358 log_entries.AppendString((*riter).GetAsJSON()); | 327 log_entries.AppendString(LogEntryAsJSON(*riter)); |
359 } else { | 328 } else { |
360 result += (*riter).ToString( | 329 result += LogEntryToString(*riter, show_time, show_file, show_type, |
361 show_time, show_file, show_level, show_desc, format_html); | 330 show_level, format_html); |
362 result += "\n"; | 331 result += "\n"; |
363 } | 332 } |
364 if (max_events > 0 && ++nlines >= max_events) | 333 if (max_events > 0 && ++nlines >= max_events) |
365 break; | 334 break; |
366 } | 335 } |
367 } | 336 } |
368 if (format_json) { | 337 if (format_json) { |
369 JSONStringValueSerializer serializer(&result); | 338 JSONStringValueSerializer serializer(&result); |
370 serializer.Serialize(log_entries); | 339 serializer.Serialize(log_entries); |
371 } | 340 } |
372 | 341 |
373 return result; | 342 return result; |
374 } | 343 } |
375 | 344 |
376 } // namespace | 345 DeviceEventLogImpl::LogEntry::LogEntry(const char* filedesc, |
377 | 346 int file_line, |
378 const LogLevel kDefaultLogLevel = LOG_LEVEL_EVENT; | 347 LogType log_type, |
379 | 348 LogLevel log_level, |
380 void Initialize() { | 349 const std::string& event) |
381 if (g_network_event_log) | 350 : file_line(file_line), |
382 delete g_network_event_log; // reset log | 351 log_type(log_type), |
383 g_network_event_log = new NetworkEventLog(); | 352 log_level(log_level), |
| 353 event(event), |
| 354 time(base::Time::Now()), |
| 355 count(1) { |
| 356 if (filedesc) |
| 357 file = base::FilePath(std::string(filedesc)).BaseName().value(); |
384 } | 358 } |
385 | 359 |
386 void Shutdown() { | 360 } // namespace device_event_log |
387 delete g_network_event_log; | |
388 g_network_event_log = NULL; | |
389 } | |
390 | 361 |
391 bool IsInitialized() { return g_network_event_log != NULL; } | |
392 | |
393 namespace internal { | |
394 | |
395 size_t GetMaxLogEntries() { return g_max_network_event_log_entries; } | |
396 | |
397 void SetMaxLogEntries(size_t max_entries) { | |
398 g_max_network_event_log_entries = max_entries; | |
399 if (!g_network_event_log) | |
400 return; | |
401 while (g_network_event_log->entries().size() > max_entries) | |
402 g_network_event_log->entries().pop_front(); | |
403 } | |
404 | |
405 void AddEntry(const char* file, | |
406 int file_line, | |
407 LogLevel log_level, | |
408 const std::string& event, | |
409 const std::string& description) { | |
410 std::string filestr; | |
411 if (file) | |
412 filestr = base::FilePath(std::string(file)).BaseName().value(); | |
413 LogEntry entry(filestr, file_line, log_level, event, description); | |
414 if (!g_network_event_log) { | |
415 entry.SendToVLogOrErrorLog(); | |
416 return; | |
417 } | |
418 g_network_event_log->AddLogEntry(entry); | |
419 } | |
420 | |
421 } // namespace internal | |
422 | |
423 std::string GetAsString(StringOrder order, | |
424 const std::string& format, | |
425 LogLevel max_level, | |
426 size_t max_events) { | |
427 if (!g_network_event_log) | |
428 return "NetworkEventLog not initialized."; | |
429 return g_network_event_log->GetAsString(order, format, max_level, max_events); | |
430 } | |
431 | |
432 std::string ValueAsString(const base::Value& value) { | |
433 std::string vstr; | |
434 base::JSONWriter::WriteWithOptions( | |
435 &value, base::JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &vstr); | |
436 return vstr.empty() ? "''" : vstr; | |
437 } | |
438 | |
439 } // namespace network_event_log | |
440 } // namespace chromeos | 362 } // namespace chromeos |
OLD | NEW |