Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: src/plugin/PluginDebug.cpp

Issue 29323611: Issue #1234, #2058 - Rewrite log facility, improving thread implementation
Patch Set: Created Aug. 19, 2015, 5:42 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2015 Eyeo GmbH 3 * Copyright (C) 2006-2015 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 #include "PluginStdAfx.h" 18 #include "PluginStdAfx.h"
19 #include "PluginDebug.h" 19 #include "PluginDebug.h"
20 #include "PluginClientBase.h" 20 #include "ActiveQueue.h"
21 #include "PluginMutex.h" 21 #include "PluginMutex.h"
22 #include "PluginClientBase.h"
23 #include "../shared/Utils.h" 22 #include "../shared/Utils.h"
23 #include <Windows.h>
24 #include <iomanip> 24 #include <iomanip>
25 #include <memory> 25 #include <memory>
26 26
27 namespace Trace
28 {
29 Location::Location(int id, int subId)
30 : prefixText()
31 {
32 std::ostringstream ss;
33 ss << "ErrorCode(" << id << "," << subId << ")";
34 postfixText = ss.str();
35 };
36 }
37
27 namespace 38 namespace
28 { 39 {
29 class CPluginDebugLock 40 class CPluginDebugLock
30 : public CPluginMutex 41 : public CPluginMutex
31 { 42 {
32 private: 43 private:
33 static CComAutoCriticalSection s_criticalSectionDebugLock; 44 static CComAutoCriticalSection s_criticalSectionDebugLock;
34 45
35 public: 46 public:
36 CPluginDebugLock() 47 CPluginDebugLock()
37 : CPluginMutex(L"DebugFile", PLUGIN_ERROR_MUTEX_DEBUG_FILE) 48 : CPluginMutex(L"DebugFile", PLUGIN_ERROR_MUTEX_DEBUG_FILE)
38 { 49 {
39 s_criticalSectionDebugLock.Lock(); 50 s_criticalSectionDebugLock.Lock();
40 } 51 }
41 52
42 ~CPluginDebugLock() 53 ~CPluginDebugLock()
43 { 54 {
44 s_criticalSectionDebugLock.Unlock(); 55 s_criticalSectionDebugLock.Unlock();
45 } 56 }
46 }; 57 };
47 58
48 CComAutoCriticalSection CPluginDebugLock::s_criticalSectionDebugLock; 59 CComAutoCriticalSection CPluginDebugLock::s_criticalSectionDebugLock;
49 60
61 /**
62 * The polymorphic part of a log entry.
63 */
50 class LogText 64 class LogText
51 { 65 {
52 public: 66 public:
53 virtual std::string Text() const = 0; 67 virtual std::string Text() const = 0;
54 }; 68 };
55 69
56 class LogTextFixed 70 class LogTextFixed
57 : public LogText 71 : public LogText
58 { 72 {
59 protected: 73 protected:
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 */ 114 */
101 struct SystemTime 115 struct SystemTime
102 : public SYSTEMTIME 116 : public SYSTEMTIME
103 { 117 {
104 SystemTime() 118 SystemTime()
105 { 119 {
106 ::GetSystemTime(static_cast<SYSTEMTIME*>(this)); 120 ::GetSystemTime(static_cast<SYSTEMTIME*>(this));
107 } 121 }
108 }; 122 };
109 123
124 /**
125 * Standard log entry, with variation in the data that generates the log messa ge.
126 */
110 class LogEntry 127 class LogEntry
111 { 128 {
112 const std::unique_ptr<LogText> text; 129 std::unique_ptr<LogText> text;
130
131 const Trace::Location location;
113 132
114 std::string InitialPrefix() const 133 std::string InitialPrefix() const
115 { 134 {
116 std::stringstream ss; 135 std::stringstream ss;
117 ss << std::setfill('0') << std::setw(2) << st.wHour; 136 ss << std::setfill('0') << std::setw(2) << st.wHour;
118 ss << ":"; 137 ss << ":";
119 ss << std::setfill('0') << std::setw(2) << st.wMinute; 138 ss << std::setfill('0') << std::setw(2) << st.wMinute;
120 ss << ":"; 139 ss << ":";
121 ss << std::setfill('0') << std::setw(2) << st.wSecond; 140 ss << std::setfill('0') << std::setw(2) << st.wSecond;
122 ss << "."; 141 ss << ".";
(...skipping 18 matching lines...) Expand all
141 /** 160 /**
142 * The process within which the log-generating statement executes. 161 * The process within which the log-generating statement executes.
143 */ 162 */
144 const DWORD processId; 163 const DWORD processId;
145 164
146 /** 165 /**
147 * The thread within which the log-generating statement executes. 166 * The thread within which the log-generating statement executes.
148 */ 167 */
149 const DWORD threadId; 168 const DWORD threadId;
150 169
151 explicit LogEntry(LogText* text) 170 explicit LogEntry(LogText* text, Trace::Location location)
152 : processId(::GetCurrentProcessId()), threadId(::GetCurrentThreadId()), te xt(text) 171 : text(text), location(location), processId(::GetCurrentProcessId()), thre adId(::GetCurrentThreadId())
153 {} 172 {}
154 173
155 LogEntry(LogText* text, DWORD processId, DWORD threadId) 174 /**
156 : processId(processId), threadId(threadId), text(text) 175 * Move constructor transfers 'text', copies everything else.
176 */
177 LogEntry(LogEntry&& x)
178 : text(std::move(x.text)), location(x.location), st(x.st), processId(x.pro cessId), threadId(x.threadId)
157 {} 179 {}
158 180
181 /**
182 * Copy constructor deleted.
183 */
184 LogEntry(const LogEntry&); // = delete
185
186 /**
187 * Copy assignment deleted.
188 */
189 LogEntry& operator=(const LogEntry&); // = delete
190
159 void Write(std::ostream& out) const 191 void Write(std::ostream& out) const
160 { 192 {
161 CPluginDebugLock lock; 193 CPluginDebugLock lock;
162 if (lock.IsLocked()) 194 if (lock.IsLocked())
163 { 195 {
164 auto lines = text->Text(); 196 auto lines = text->Text();
165 size_t linePosition = 0; 197 size_t linePosition = 0;
166 while (true) 198 while (true)
167 { 199 {
168 auto eolPosition = lines.find('\n', linePosition); 200 // Standard prefix, timestamp and thread ID
169 auto prefix = linePosition == 0 ? InitialPrefix() : SubsequentPrefix() ; 201 auto prefix = linePosition == 0 ? InitialPrefix() : SubsequentPrefix() ;
170 out << prefix; 202 out << prefix;
203
204 // Location prefix, if any
205 if (location.prefixText.length() > 0)
206 {
207 out << location.prefixText << " - ";
208 }
209
210 // One line of the log text itself
211 auto eolPosition = lines.find('\n', linePosition);
171 if (eolPosition == std::string::npos) 212 if (eolPosition == std::string::npos)
172 { 213 {
173 out << lines.substr(linePosition) << "\n"; 214 out << lines.substr(linePosition);
174 break;
175 } 215 }
176 else 216 else
177 { 217 {
178 out << lines.substr(linePosition, eolPosition - linePosition) << "\n "; 218 out << lines.substr(linePosition, eolPosition - linePosition);
179 linePosition = eolPosition + 1; 219 linePosition = eolPosition + 1;
180 } 220 }
221
222 // Location postfix, if any
223 if (location.postfixText.length() > 0)
224 {
225 out << " - ";
226 // Hack to deal with how gyp generates file names for Visual Studio
227 if (location.postfixText.find("..\\..\\") == 0)
228 {
229 out << location.postfixText.substr(6);
230 }
231 else
232 {
233 out << location.postfixText;
234 }
235 }
236 out << "\n";
237
238 // Check to see if that was the last line
239 if (eolPosition == std::string::npos)
240 {
241 break;
242 }
181 } 243 }
182 out.flush(); 244 out.flush();
183 } 245 }
184 } 246 }
185 247
186 void WriteFile(const std::wstring& logFileName) const 248 void WriteFile(const std::wstring& logFileName) const
187 { 249 {
188 std::ofstream out; 250 std::ofstream out;
189 out.open(logFileName, std::ios::app); 251 out.open(logFileName, std::ios::app);
190 Write(out); 252 Write(out);
(...skipping 10 matching lines...) Expand all
201 std::wstring debugFileName = GetDataPath(L"debug_" + std::to_wstring(le.proc essId) + L".txt"); 263 std::wstring debugFileName = GetDataPath(L"debug_" + std::to_wstring(le.proc essId) + L".txt");
202 le.WriteFile(debugFileName); 264 le.WriteFile(debugFileName);
203 } 265 }
204 266
205 void LogWriteResult(const LogEntry& le) 267 void LogWriteResult(const LogEntry& le)
206 { 268 {
207 std::wstring debugFileName = GetDataPath(L"debug_result.txt"); 269 std::wstring debugFileName = GetDataPath(L"debug_result.txt");
208 le.WriteFile(debugFileName); 270 le.WriteFile(debugFileName);
209 } 271 }
210 } 272 }
211 273
274 /**
275 * An active queue of 'LogEntry'.
276 * Life cycle is maintained in conjunction with 'LogQueueReference'.
277 */
278 class LogQueue
279 {
280 /**
281 * Processor for the log queue
282 */
283 static void ProcessLogEntry(const LogEntry&);
284
285 /**
286 * Active queue for processing log entries.
287 */
288 ActiveQueue<LogEntry, decltype(ProcessLogEntry)> queue;
289
290 public:
291 /**
292 * Insert an item into the queue.
293 */
294 static void Insert(LogEntry&& t)
295 {
296 /*
297 * Note that this function(indeed, this class) does not have the
298 * responsibility to ensure that an instance of the queue exists.
299 * See 'LogQueueReference' for the class that does.
300 * The non-null guard here is purely defensive;
301 * we shouldn't ever lose queued events because of it.
302 */
303 if (LogQueueReference::queueMasterReference)
304 {
305 LogQueueReference::queueMasterReference->queue.Insert(std::move(t));
306 }
307 }
308
309 LogQueue()
310 : queue(ProcessLogEntry)
311 {}
312 };
313
314 /**
315 * The processor for the log queue simply writes each log entry to its correspon ding log file.
316 *
317 * At present the only log entries that go through the queue also go to the defa ult log file.
318 * This logic will expand to include other log files as we pass all the log entr ies through the queue.
319 */
320 void LogQueue::ProcessLogEntry(const LogEntry& entry)
321 {
322 LogWriteDefault(entry);
323 }
324
325 /*
326 * Static initializations
327 */
328 LogQueueReference::pointer LogQueueReference::queueMasterReference;
329 std::mutex LogQueueReference::mutex;
330
331 /*
332 * Only initialize the instance reference within the constructor body,
333 * so that it's serialized under the protection of the mutex.
334 */
335 LogQueueReference::LogQueueReference()
336 : queueReference(queueMasterReference)
337 {
338 std::unique_lock<std::mutex> lock(LogQueueReference::mutex);
339 if (!queueMasterReference)
340 {
341 queueMasterReference = pointer(new LogQueue());
342 LogQueue::Insert(LogEntry(new LogTextFixed("LogQueue start"), HERE_F));
343 }
344 queueReference = queueMasterReference;
345 }
346
347 LogQueueReference::~LogQueueReference()
348 {
349 std::unique_lock<std::mutex> lock(LogQueueReference::mutex);
350 queueReference.reset();
351 if (queueMasterReference.use_count() == 1)
352 {
353 LogQueue::Insert(LogEntry(new LogTextFixed("LogQueue stop"), HERE_F));
354 queueMasterReference.reset();
355 }
356 }
357
358
212 #ifdef ENABLE_DEBUG_INFO 359 #ifdef ENABLE_DEBUG_INFO
213 360
214 void CPluginDebug::Debug(const std::string& text) 361 void CPluginDebug::Debug(const std::string& text)
215 { 362 {
216 LogWriteDefault(LogEntry(new LogTextFixed(text))); 363 LogWriteDefault(LogEntry(new LogTextFixed(text), Trace::Location()));
217 } 364 }
218 365
219 void CPluginDebug::Debug(const std::wstring& text) 366 void CPluginDebug::Debug(const std::wstring& text)
220 { 367 {
221 Debug(ToUtf8String(text)); 368 Debug(ToUtf8String(text));
222 } 369 }
223 370
224 #endif 371 #endif
225 372
226 void CPluginDebug::DebugSystemException(const std::system_error& ex, int errorId , int errorSubid, const std::string& description) 373 namespace Trace
227 { 374 {
228 std::string message = description + ", " + ex.code().message() + ", " + ex.wha t(); 375 void SystemException(const std::system_error& ex, const std::string& descripti on, Trace::Location location)
229 DEBUG_ERROR_LOG(ex.code().value(), errorId, errorSubid, message); 376 {
377 std::string message = description + ", " + ex.code().message() + ", " + ex.w hat();
378 ErrorCode(ex.code().value(), message, location);
379 }
230 } 380 }
231 381
232 #if (defined ENABLE_DEBUG_INFO) 382 #if (defined ENABLE_DEBUG_INFO)
233 383
234 void CPluginDebug::DebugException(const std::exception& ex) 384 void CPluginDebug::DebugException(const std::exception& ex, Trace::Location loca tion)
235 { 385 {
236 auto lt = new LogTextFixed(ex); 386 auto lt = new LogTextFixed(ex);
237 LogEntry le(lt); 387 LogEntry le(lt, location);
238 #ifdef ENABLE_DEBUG_ERROR
239 LogWriteDefault(le); 388 LogWriteDefault(le);
240 #endif
241 DEBUG_SELFTEST(
242 "*************************************************************************** *****\n"
243 + lt->text() + "\n"
244 "*************************************************************************** *****")
245 } 389 }
246 390
247 void CPluginDebug::DebugErrorCode(DWORD errorCode, const std::string& error, DWO RD processId, DWORD threadId) 391 void CPluginDebug::DebugErrorCode(DWORD errorCode, const std::string& error, Tra ce::Location location)
248 { 392 {
249 auto lt = new LogTextErrorCode(errorCode, error); 393 auto lt = new LogTextErrorCode(errorCode, error);
250 LogEntry le(lt, processId, threadId); 394 LogEntry le(lt, location);
251 #ifdef ENABLE_DEBUG_ERROR
252 LogWriteDefault(le); 395 LogWriteDefault(le);
253 #endif
254 DEBUG_SELFTEST(
255 "*************************************************************************** *****\n"
256 + lt->text() + "\n"
257 "*************************************************************************** *****")
258 } 396 }
259 397
260 #endif 398 #endif
261 399
262 // ============================================================================ 400 // ============================================================================
263 // Debug result 401 // Debug result
264 // ============================================================================ 402 // ============================================================================
265 403
266 #ifdef ENABLE_DEBUG_RESULT 404 #ifdef ENABLE_DEBUG_RESULT
267 405
268 void CPluginDebug::DebugResult(const std::wstring& text) 406 void CPluginDebug::DebugResult(const std::wstring& text)
269 { 407 {
270 LogWriteResult(LogEntry(new LogTextFixed(ToUtf8String(text)))); 408 LogWriteResult(LogEntry(new LogTextFixed(ToUtf8String(text)), Trace::Location( )));
271 } 409 }
272 410
273 void CPluginDebug::DebugResultDomain(const std::wstring& domain) 411 void CPluginDebug::DebugResultDomain(const std::wstring& domain)
274 { 412 {
275 DebugResult( 413 DebugResult(
276 L"========================================================================== ===============\n" 414 L"========================================================================== ===============\n"
277 + domain + L"\n" 415 + domain + L"\n"
278 L"========================================================================== ==============="); 416 L"========================================================================== ===============");
279 } 417 }
280 418
(...skipping 18 matching lines...) Expand all
299 r += s.substr(n - 30, 30); 437 r += s.substr(n - 30, 30);
300 return r; 438 return r;
301 } 439 }
302 } 440 }
303 441
304 void CPluginDebug::DebugResultBlocking(const std::wstring& type, const std::wstr ing& src, const std::wstring& domain) 442 void CPluginDebug::DebugResultBlocking(const std::wstring& type, const std::wstr ing& src, const std::wstring& domain)
305 { 443 {
306 DebugResultFormat(L"Blocked", type, domain.empty() ? L"-" : domain, Shorten(sr c)); 444 DebugResultFormat(L"Blocked", type, domain.empty() ? L"-" : domain, Shorten(sr c));
307 } 445 }
308 446
309
310 void CPluginDebug::DebugResultHiding(const std::wstring& tag, const std::wstring & id, const std::wstring& filter) 447 void CPluginDebug::DebugResultHiding(const std::wstring& tag, const std::wstring & id, const std::wstring& filter)
311 { 448 {
312 DebugResultFormat(L"Hidden", tag, L"- " + Shorten(id), filter); 449 DebugResultFormat(L"Hidden", tag, L"- " + Shorten(id), filter);
313 } 450 }
314 451
315 #endif // ENABLE_DEBUG_RESULT 452 #endif // ENABLE_DEBUG_RESULT
316 453
317
318 #ifdef ENABLE_DEBUG_RESULT_IGNORED 454 #ifdef ENABLE_DEBUG_RESULT_IGNORED
319 455
320 void CPluginDebug::DebugResultIgnoring(const std::wstring& type, const std::wstr ing& src, const std::wstring& domain) 456 void CPluginDebug::DebugResultIgnoring(const std::wstring& type, const std::wstr ing& src, const std::wstring& domain)
321 { 457 {
322 DebugResultFormat(L"Ignored", type, domain.empty() ? L"-" : domain, Shorten(sr c)); 458 DebugResultFormat(L"Ignored", type, domain.empty() ? L"-" : domain, Shorten(sr c));
323 } 459 }
324 460
325 #endif // ENABLE_DEBUG_RESULT_IGNORED 461 #endif // ENABLE_DEBUG_RESULT_IGNORED
462
463 void Trace::ErrorCode(DWORD errorCode, const std::string& description, Trace::Lo cation location)
464 {
465 LogQueue::Insert(LogEntry(new LogTextErrorCode(errorCode, description), locati on));
466 }
467
468 void Trace::TextFixed(const std::string& description, Trace::Location location)
469 {
470 LogQueue::Insert(LogEntry(new LogTextFixed(description), location));
471 }
OLDNEW

Powered by Google App Engine
This is Rietveld