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

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

Issue 5187613258416128: Issue #1234 - Rewrite internals of debug facility (Closed)
Patch Set: rebase to current public tip Created June 28, 2015, 3:25 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/plugin/PluginDebug.h ('k') | src/plugin/PluginSettings.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "PluginClientBase.h"
21 #include "PluginMutex.h" 21 #include "PluginMutex.h"
22 #include "PluginSettings.h" 22 #include "PluginClientBase.h"
23 23 #include "../shared/Utils.h"
24 class CPluginDebugLock : public CPluginMutex 24 #include <iomanip>
25 { 25 #include <memory>
26 26
27 private: 27 namespace
28 28 {
29 static CComAutoCriticalSection s_criticalSectionDebugLock; 29 class CPluginDebugLock
30 30 : public CPluginMutex
31 public: 31 {
32 32 private:
33 CPluginDebugLock() : CPluginMutex(L"DebugFile", PLUGIN_ERROR_MUTEX_DEBUG_FILE) 33 static CComAutoCriticalSection s_criticalSectionDebugLock;
sergei 2015/10/12 12:46:20 What will happen if we remove `s_criticalSectionDe
Eric 2015/10/13 17:33:19 The problem right now (and also in the later versi
sergei 2015/11/30 14:15:03 The plan is clear but the reason we need `s_critic
Eric 2015/11/30 17:39:01 There's only one occurrence of 'CPluginDebugLock',
sergei 2015/11/30 18:14:29 There is already CPluginMutex and it serializes th
Eric 2015/12/01 20:43:57 Now I see what you're getting at. Yes, the critica
sergei 2015/12/02 13:52:59 Acknowledged.
34 { 34
35 s_criticalSectionDebugLock.Lock(); 35 public:
36 CPluginDebugLock()
37 : CPluginMutex(L"DebugFile", PLUGIN_ERROR_MUTEX_DEBUG_FILE)
38 {
39 s_criticalSectionDebugLock.Lock();
40 }
41
42 ~CPluginDebugLock()
43 {
44 s_criticalSectionDebugLock.Unlock();
45 }
46 };
47
48 CComAutoCriticalSection CPluginDebugLock::s_criticalSectionDebugLock;
49
50 class LogText
sergei 2015/10/12 12:46:20 virtual destructor is missed here, the derived cla
Eric 2015/10/13 17:33:19 Yep. I'll add it after I get a rebase posted.
51 {
52 public:
53 virtual std::string Text() const = 0;
54 };
55
56 class LogTextFixed
57 : public LogText
58 {
59 protected:
60 const std::string fixedText;
61
62 public:
63 explicit LogTextFixed(const std::string& text)
64 : fixedText(text)
65 {}
66
67 explicit LogTextFixed(const std::exception& ex)
68 : fixedText(std::string("!!! Exception: ") + ex.what())
69 {}
70
71 virtual std::string Text() const override
72 {
73 return fixedText;
74 }
75 };
76
77 class LogTextErrorCode
78 : public LogTextFixed
79 {
80 protected:
81 const DWORD errorCode;
82
83 public:
84 LogTextErrorCode(DWORD errorCode, const std::string& text)
85 : LogTextFixed(text), errorCode(errorCode)
86 {}
87
88 virtual std::string Text() const override
89 {
90 std::ostringstream ss;
91 ss << fixedText << ". error = " << errorCode << " (0x";
92 ss << std::setfill('0') << std::setw(2 * sizeof(DWORD)) << std::hex << err orCode;
93 ss << ")";
94 return ss.str();
95 }
96 };
97
98 /**
99 * Wrapper around SYSTEMTIME allows initialization of 'const' instances.
100 */
101 struct SystemTime
102 : public SYSTEMTIME
103 {
104 SystemTime()
105 {
106 ::GetSystemTime(static_cast<SYSTEMTIME*>(this));
107 }
108 };
109
110 class LogEntry
111 {
112 const std::unique_ptr<LogText> text;
113
114 std::string InitialPrefix() const
115 {
116 std::stringstream ss;
117 ss << std::setfill('0') << std::setw(2) << st.wHour;
118 ss << ":";
119 ss << std::setfill('0') << std::setw(2) << st.wMinute;
120 ss << ":";
121 ss << std::setfill('0') << std::setw(2) << st.wSecond;
122 ss << ".";
123 ss << std::setfill('0') << std::setw(3) << st.wMilliseconds;
124 ss << " [";
125 ss << std::setfill(' ') << std::setw(5) << threadId;
126 ss << "] - ";
127 return ss.str();
128 }
129
130 std::string SubsequentPrefix() const
131 {
132 return " + ";
133 }
134
135 public:
136 /**
137 * The time at which the log-generating statement executes.
138 */
139 const SystemTime st;
140
141 /**
142 * The process within which the log-generating statement executes.
143 */
144 const DWORD processId;
145
146 /**
147 * The thread within which the log-generating statement executes.
148 */
149 const DWORD threadId;
150
151 explicit LogEntry(LogText* text)
152 : processId(::GetCurrentProcessId()), threadId(::GetCurrentThreadId()), te xt(text)
153 {}
154
155 LogEntry(LogText* text, DWORD processId, DWORD threadId)
156 : processId(processId), threadId(threadId), text(text)
157 {}
158
159 void Write(std::ostream& out) const
160 {
161 CPluginDebugLock lock;
Eric 2015/11/30 17:39:01 This is the sentry object. 'Write()' is currently
162 if (lock.IsLocked())
163 {
164 auto lines = text->Text();
165 size_t linePosition = 0;
166 while (true)
167 {
168 auto eolPosition = lines.find('\n', linePosition);
169 auto prefix = linePosition == 0 ? InitialPrefix() : SubsequentPrefix() ;
170 out << prefix;
171 if (eolPosition == std::string::npos)
172 {
173 out << lines.substr(linePosition) << "\n";
174 break;
175 }
176 else
177 {
178 out << lines.substr(linePosition, eolPosition - linePosition) << "\n ";
179 linePosition = eolPosition + 1;
180 }
181 }
182 out.flush();
183 }
184 }
185
186 void WriteFile(const std::wstring& logFileName) const
187 {
188 std::ofstream out;
189 out.open(logFileName, std::ios::app);
190 Write(out);
191 }
192 };
193
194 std::wstring GetDataPath(const std::wstring& filename)
195 {
196 return GetAppDataPath() + L"\\" + filename;
36 } 197 }
37 198
38 ~CPluginDebugLock() 199 void LogWriteDefault(const LogEntry& le)
39 { 200 {
40 s_criticalSectionDebugLock.Unlock(); 201 std::wstring debugFileName = GetDataPath(L"debug_" + std::to_wstring(le.proc essId) + L".txt");
202 le.WriteFile(debugFileName);
41 } 203 }
42 }; 204
43 205 void LogWriteResult(const LogEntry& le)
44 CComAutoCriticalSection CPluginDebugLock::s_criticalSectionDebugLock; 206 {
207 std::wstring debugFileName = GetDataPath(L"debug_result.txt");
208 le.WriteFile(debugFileName);
209 }
210 }
211
212 #ifdef ENABLE_DEBUG_INFO
213
214 void CPluginDebug::Debug(const std::string& text)
215 {
216 LogWriteDefault(LogEntry(new LogTextFixed(text)));
217 }
218
219 void CPluginDebug::Debug(const std::wstring& text)
220 {
221 Debug(ToUtf8String(text));
222 }
223
224 #endif
45 225
46 void CPluginDebug::DebugSystemException(const std::system_error& ex, int errorId , int errorSubid, const std::string& description) 226 void CPluginDebug::DebugSystemException(const std::system_error& ex, int errorId , int errorSubid, const std::string& description)
47 { 227 {
48 std::string message = description + ", " + ex.code().message() + ", " + ex.wha t(); 228 std::string message = description + ", " + ex.code().message() + ", " + ex.wha t();
49 DEBUG_ERROR_LOG(ex.code().value(), errorId, errorSubid, message); 229 DEBUG_ERROR_LOG(ex.code().value(), errorId, errorSubid, message);
50 } 230 }
51 231
52 #ifdef ENABLE_DEBUG_INFO
53
54 void DebugLegacy(const CString& text, DWORD dwProcessId, DWORD dwThreadId)
55 {
56 #ifdef USE_CONSOLE
57 CONSOLE("%s", CT2A(text.GetString(), CP_UTF8));
58 #endif
59
60 if (CPluginSettings::HasInstance())
61 {
62 #ifdef ENABLE_DEBUG_SPLIT_FILE
63 CPluginSettings* settings = CPluginSettings::GetInstance();
64
65 bool isWorkingThread = settings->IsWorkingThread(dwThreadId);
66
67 std::wstring processor;
68 wchar_t tmp[10];
69 _itow_s(::GetCurrentProcessId(), tmp, 10);
70 if (isWorkingThread)
71 processor = L"tab" + std::wstring(tmp) + L"_thread";
72 else
73 processor = L"tab" + std::wstring(tmp) + L"_ui";
74 #else
75 if (dwProcessId == 0)
76 {
77 dwProcessId = ::GetCurrentProcessId();
78 }
79 if (dwThreadId == 0)
80 {
81 dwThreadId = ::GetCurrentThreadId();
82 }
83
84 CStringA processInfo;
85 processInfo.Format("%4.4u.%4.4u - ", dwProcessId, dwThreadId);
86 #endif
87 SYSTEMTIME st;
88 ::GetSystemTime(&st);
89
90 CStringA sysTime;
91 sysTime.Format("%2.2d:%2.2d:%2.2d.%3.3d - ", st.wHour, st.wMinute, st.wSecon d, st.wMilliseconds);
92
93 CPluginDebugLock lock;
94 if (lock.IsLocked())
95 {
96 std::ofstream debugFile;
97
98 #ifdef ENABLE_DEBUG_SPLIT_FILE
99 debugFile.open(GetDataPath(L"debug_" + processor + L".txt"), std::ios::app );
100 #else
101 debugFile.open(GetDataPath(L"debug.txt"), std::ios::app);
102 #endif
103 int pos = 0;
104 CStringA line = text.Tokenize(L"\n\r", pos);
105
106 while (pos >= 0)
107 {
108 debugFile.write(sysTime.GetBuffer(), sysTime.GetLength());
109 #ifndef ENABLE_DEBUG_SPLIT_FILE
110 debugFile.write(processInfo.GetBuffer(), processInfo.GetLength());
111 #endif
112 debugFile.write(line.GetBuffer(), line.GetLength());
113 debugFile.write("\n", 1);
114
115 line = text.Tokenize(L"\n\r", pos);
116 }
117
118 debugFile.flush();
119 }
120 }
121 }
122
123 void CPluginDebug::Debug(const std::string& text, DWORD processId, DWORD threadI d)
124 {
125 DebugLegacy(CString(text.c_str()), processId, threadId);
126 }
127
128 void CPluginDebug::Debug(const std::wstring& text, DWORD processId, DWORD thread Id)
129 {
130 DebugLegacy(ToCString(text), processId, threadId);
131 }
132
133 #endif
134
135 #if (defined ENABLE_DEBUG_INFO) 232 #if (defined ENABLE_DEBUG_INFO)
136 233
137 void CPluginDebug::DebugException(const std::exception& ex) 234 void CPluginDebug::DebugException(const std::exception& ex)
138 { 235 {
139 auto error = std::string("!!! Exception:") + ex.what(); 236 auto lt = new LogTextFixed(ex);
237 LogEntry le(lt);
140 #ifdef ENABLE_DEBUG_ERROR 238 #ifdef ENABLE_DEBUG_ERROR
141 Debug(error); 239 LogWriteDefault(le);
142 #endif 240 #endif
143 241 DEBUG_SELFTEST(
144 DEBUG_SELFTEST("************************************************************** ******************\n" + error + "\n********************************************* ***********************************") 242 "*************************************************************************** *****\n"
145 } 243 + lt->text() + "\n"
146 244 "*************************************************************************** *****")
147 void DebugErrorCodeLegacy(DWORD errorCode, const CString& error, DWORD dwProcess Id, DWORD dwThreadId) 245 }
148 { 246
149 CString errorCodeText; 247 void CPluginDebug::DebugErrorCode(DWORD errorCode, const std::string& error, DWO RD processId, DWORD threadId)
150 errorCodeText.Format(L"%u (0x%8.8x)", errorCode, errorCode); 248 {
151 249 auto lt = new LogTextErrorCode(errorCode, error);
152 CString finalError = error + L". error=" + errorCodeText; 250 LogEntry le(lt, processId, threadId);
153
154 #ifdef ENABLE_DEBUG_ERROR 251 #ifdef ENABLE_DEBUG_ERROR
155 DebugLegacy(finalError, dwProcessId, dwThreadId); 252 LogWriteDefault(le);
156 #endif 253 #endif
157 254 DEBUG_SELFTEST(
158 DEBUG_SELFTEST(L"************************************************************* *******************\n" + finalError + "\n*************************************** *****************************************") 255 "*************************************************************************** *****\n"
159 } 256 + lt->text() + "\n"
160 257 "*************************************************************************** *****")
161 void CPluginDebug::DebugErrorCode(DWORD errorCode, const std::string& error, DWO RD processId, DWORD threadId) 258 }
162 { 259
163 DebugErrorCodeLegacy(errorCode, CString(error.c_str()), processId, threadId); 260 #endif
164 }
165
166 #endif
167 261
168 // ============================================================================ 262 // ============================================================================
169 // Debug result 263 // Debug result
170 // ============================================================================ 264 // ============================================================================
171 265
172 #ifdef ENABLE_DEBUG_RESULT 266 #ifdef ENABLE_DEBUG_RESULT
173 267
174 void DebugResultLegacy(const CString& text)
175 {
176 SYSTEMTIME st;
177 ::GetSystemTime(&st);
178
179 CStringA sysTime;
180 sysTime.Format("%2.2d:%2.2d:%2.2d.%3.3d - ", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
181
182 CStringA textA = text;
183
184 CPluginDebugLock lock;
185 if (lock.IsLocked())
186 {
187 std::ofstream debugFile;
188
189 debugFile.open(GetDataPath(L"debug_result.txt"), std::ios::app);
190 debugFile.write(sysTime.GetBuffer(), sysTime.GetLength());
191 debugFile.write(LPCSTR(textA), textA.GetLength());
192 debugFile.write("\n", 1);
193 debugFile.flush();
194 }
195 }
196
197 void CPluginDebug::DebugResult(const std::wstring& text) 268 void CPluginDebug::DebugResult(const std::wstring& text)
198 { 269 {
199 DebugResultLegacy(ToCString(text)); 270 LogWriteResult(LogEntry(new LogTextFixed(ToUtf8String(text))));
200 } 271 }
201 272
202 void CPluginDebug::DebugResultDomain(const std::wstring& domain) 273 void CPluginDebug::DebugResultDomain(const std::wstring& domain)
203 { 274 {
204 DebugResult(L"================================================================ ================================================================================ ==========================================="); 275 DebugResult(
205 DebugResult(domain); 276 L"========================================================================== ===============\n"
206 DebugResult(L"================================================================ ================================================================================ ==========================================="); 277 + domain + L"\n"
278 L"========================================================================== ===============");
207 } 279 }
208 280
281 namespace
282 {
283 void DebugResultFormat(const std::wstring& action, const std::wstring& type, c onst std::wstring& param1, const std::wstring& param2)
284 {
285 std::wostringstream ss;
286 ss << std::setw(7) << std::setiosflags(std::ios::left) << action;
287 ss << L" ";
288 ss << std::setw(12) << std::setiosflags(std::ios::left) << type;
289 ss << L" " << param1 << L" " << param2;
290 CPluginDebug::DebugResult(ss.str());
291 }
292
293 std::wstring Shorten(const std::wstring& s)
294 {
295 auto n = s.length();
296 if (n <= 100) return s;
297 auto r = s.substr(0, 67);
298 r += L"...";
299 r += s.substr(n - 30, 30);
300 return r;
301 }
302 }
209 303
210 void CPluginDebug::DebugResultBlocking(const std::wstring& type, const std::wstr ing& src, const std::wstring& domain) 304 void CPluginDebug::DebugResultBlocking(const std::wstring& type, const std::wstr ing& src, const std::wstring& domain)
211 { 305 {
212 CString srcTrunc = ToCString(src); 306 DebugResultFormat(L"Blocked", type, domain.empty() ? L"-" : domain, Shorten(sr c));
213 if (src.length() > 100)
214 {
215 srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30);
216 }
217
218 CString blocking;
219 blocking.Format(L"Blocked %-12s %-20s %s", ToCString(type), domain.empty()? L"-" : ToCString(domain), srcTrunc);
220
221 DebugResultLegacy(blocking);
222 } 307 }
223 308
224 309
225 void CPluginDebug::DebugResultHiding(const std::wstring& tag, const std::wstring & id, const std::wstring& filter) 310 void CPluginDebug::DebugResultHiding(const std::wstring& tag, const std::wstring & id, const std::wstring& filter)
226 { 311 {
227 CString srcTrunc = ToCString(id); 312 DebugResultFormat(L"Hidden", tag, L"- " + Shorten(id), filter);
228 if (srcTrunc.GetLength() > 100)
229 {
230 srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30);
231 }
232
233 CString blocking;
234 blocking.Format(L"Hidden %-12s - %s %s", ToCString(tag), srcTrunc, ToCStri ng(filter));
235
236 DebugResultLegacy(blocking);
237 } 313 }
238 314
239 #endif // ENABLE_DEBUG_RESULT 315 #endif // ENABLE_DEBUG_RESULT
240 316
241 317
242 #ifdef ENABLE_DEBUG_RESULT_IGNORED 318 #ifdef ENABLE_DEBUG_RESULT_IGNORED
243 319
244 void CPluginDebug::DebugResultIgnoring(const std::wstring& type, const std::wstr ing& src, const std::wstring& domain) 320 void CPluginDebug::DebugResultIgnoring(const std::wstring& type, const std::wstr ing& src, const std::wstring& domain)
245 { 321 {
246 CString srcTrunc = ToCString(src); 322 DebugResultFormat(L"Ignored", type, domain.empty() ? L"-" : domain, Shorten(sr c));
247 if (src.length() > 100)
248 {
249 srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30);
250 }
251
252 CString blocking;
253 blocking.Format(L"Ignored %-12s %s %s", ToCString(type), domain.empty()? L" -" : ToCString(domain), srcTrunc);
254
255 DebugResultLegacy(blocking);
256 } 323 }
257 324
258 #endif // ENABLE_DEBUG_RESULT_IGNORED 325 #endif // ENABLE_DEBUG_RESULT_IGNORED
OLDNEW
« no previous file with comments | « src/plugin/PluginDebug.h ('k') | src/plugin/PluginSettings.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld