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

Unified Diff: src/plugin/PluginDebug.cpp

Issue 5187613258416128: Issue #1234 - Rewrite internals of debug facility (Closed)
Patch Set: rebase only Created Nov. 26, 2015, 1:02 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/plugin/PluginDebug.h ('k') | src/plugin/PluginSettings.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/plugin/PluginDebug.cpp
===================================================================
--- a/src/plugin/PluginDebug.cpp
+++ b/src/plugin/PluginDebug.cpp
@@ -19,148 +19,243 @@
#include "PluginDebug.h"
#include "PluginClientBase.h"
#include "PluginMutex.h"
-#include "PluginSettings.h"
+#include "PluginClientBase.h"
+#include "../shared/Utils.h"
+#include <iomanip>
+#include <memory>
-class CPluginDebugLock : public CPluginMutex
+namespace
{
+ class CPluginDebugLock
+ : public CPluginMutex
+ {
+ private:
+ static CComAutoCriticalSection s_criticalSectionDebugLock;
-private:
+ public:
+ CPluginDebugLock()
+ : CPluginMutex(L"DebugFile", PLUGIN_ERROR_MUTEX_DEBUG_FILE)
+ {
+ s_criticalSectionDebugLock.Lock();
+ }
- static CComAutoCriticalSection s_criticalSectionDebugLock;
+ ~CPluginDebugLock()
+ {
+ s_criticalSectionDebugLock.Unlock();
+ }
+ };
-public:
+ CComAutoCriticalSection CPluginDebugLock::s_criticalSectionDebugLock;
- CPluginDebugLock() : CPluginMutex(L"DebugFile", PLUGIN_ERROR_MUTEX_DEBUG_FILE)
+ class LogText
{
- s_criticalSectionDebugLock.Lock();
+ public:
+ virtual std::string Text() const = 0;
+ virtual ~LogText() {};
+ };
+
+ class LogTextFixed
sergei 2015/12/02 13:53:00 What about naming of classes differently? Let's a
Eric 2015/12/02 15:01:24 No. Naming the subclasses of 'class LogText' with
+ : public LogText
+ {
+ protected:
+ const std::string fixedText;
+
+ public:
+ explicit LogTextFixed(const std::string& text)
+ : fixedText(text)
+ {}
+
+ explicit LogTextFixed(const std::exception& ex)
+ : fixedText(std::string("!!! Exception: ") + ex.what())
+ {}
+
+ virtual std::string Text() const override
sergei 2015/11/30 14:15:03 I would propose to omit `virtual` when we use `ove
Eric 2015/11/30 17:39:01 It's good to have both in place. Makes the intent
sergei 2015/11/30 18:14:29 Actually, I would like to note that it's not relat
Eric 2015/12/01 20:43:58 OK.
+ {
+ return fixedText;
+ }
+ };
+
+ class LogTextErrorCode
+ : public LogTextFixed
+ {
+ protected:
+ const DWORD errorCode;
+
+ public:
+ LogTextErrorCode(DWORD errorCode, const std::string& text)
+ : LogTextFixed(text), errorCode(errorCode)
+ {}
+
+ virtual std::string Text() const override
+ {
+ std::ostringstream ss;
+ ss << fixedText << ". error = " << errorCode << " (0x";
+ ss << std::setfill('0') << std::setw(2 * sizeof(DWORD)) << std::hex << errorCode;
+ ss << ")";
+ return ss.str();
+ }
+ };
+
+ /**
+ * Wrapper around SYSTEMTIME allows initialization of 'const' instances.
+ */
+ struct SystemTime
+ : public SYSTEMTIME
+ {
+ SystemTime()
+ {
+ ::GetSystemTime(static_cast<SYSTEMTIME*>(this));
+ }
+ };
+
+ class LogEntry
+ {
+ const std::unique_ptr<LogText> text;
sergei 2015/12/02 13:53:00 Just in case, what is the reason of extensively pu
Eric 2015/12/02 15:01:24 'const' members mean "initialized only at construc
+
+ std::string InitialPrefix() const
+ {
+ std::stringstream ss;
+ ss << std::setfill('0') << std::setw(2) << st.wHour;
+ ss << ":";
+ ss << std::setfill('0') << std::setw(2) << st.wMinute;
+ ss << ":";
+ ss << std::setfill('0') << std::setw(2) << st.wSecond;
+ ss << ".";
+ ss << std::setfill('0') << std::setw(3) << st.wMilliseconds;
+ ss << " [";
+ ss << std::setfill(' ') << std::setw(5) << threadId;
+ ss << "] - ";
+ return ss.str();
+ }
+
+ std::string SubsequentPrefix() const
+ {
+ return " + ";
+ }
+
+ public:
+ /**
+ * The time at which the log-generating statement executes.
+ */
+ const SystemTime st;
+
+ /**
+ * The process within which the log-generating statement executes.
+ */
+ const DWORD processId;
+
+ /**
+ * The thread within which the log-generating statement executes.
+ */
+ const DWORD threadId;
+
+ explicit LogEntry(LogText* text)
+ : processId(::GetCurrentProcessId()), threadId(::GetCurrentThreadId()), text(text)
+ {}
+
+ LogEntry(LogText* text, DWORD processId, DWORD threadId)
+ : processId(processId), threadId(threadId), text(text)
+ {}
+
+ void Write(std::ostream& out) const
+ {
+ CPluginDebugLock lock;
+ if (lock.IsLocked())
+ {
+ auto lines = text->Text();
+ size_t linePosition = 0;
+ while (true)
+ {
+ auto eolPosition = lines.find('\n', linePosition);
+ auto prefix = linePosition == 0 ? InitialPrefix() : SubsequentPrefix();
+ out << prefix;
+ if (eolPosition == std::string::npos)
+ {
+ out << lines.substr(linePosition) << "\n";
+ break;
+ }
+ else
+ {
+ out << lines.substr(linePosition, eolPosition - linePosition) << "\n";
+ linePosition = eolPosition + 1;
+ }
+ }
+ out.flush();
+ }
+ }
+
+ void WriteFile(const std::wstring& logFileName) const
+ {
+ std::ofstream out;
+ out.open(logFileName, std::ios::app);
sergei 2015/12/02 13:53:00 I wonder whether we need a synchronization here. E
Eric 2015/12/02 15:01:24 Easy answer: This locking behavior is the same as
+ Write(out);
+ }
+ };
+
+ std::wstring GetDataPath(const std::wstring& filename)
+ {
+ return GetAppDataPath() + L"\\" + filename;
}
- ~CPluginDebugLock()
+ void LogWriteDefault(const LogEntry& le)
{
- s_criticalSectionDebugLock.Unlock();
+ std::wstring debugFileName = GetDataPath(L"debug_" + std::to_wstring(le.processId) + L".txt");
+ le.WriteFile(debugFileName);
}
-};
-CComAutoCriticalSection CPluginDebugLock::s_criticalSectionDebugLock;
+ void LogWriteResult(const LogEntry& le)
+ {
+ std::wstring debugFileName = GetDataPath(L"debug_result.txt");
+ le.WriteFile(debugFileName);
+ }
+}
+
+#ifdef ENABLE_DEBUG_INFO
+
+void CPluginDebug::Debug(const std::string& text)
+{
+ LogWriteDefault(LogEntry(new LogTextFixed(text)));
+}
+
+void CPluginDebug::Debug(const std::wstring& text)
+{
+ Debug(ToUtf8String(text));
+}
+
+#endif
void CPluginDebug::DebugSystemException(const std::system_error& ex, int errorId, int errorSubid, const std::string& description)
{
- std::string message = description + ", " + ex.code().message() + ", " + ex.what();
- DEBUG_ERROR_LOG(ex.code().value(), errorId, errorSubid, message);
+ std::string message = description + ", " + ex.code().message() + ", " + ex.what();
+ DEBUG_ERROR_LOG(ex.code().value(), errorId, errorSubid, message);
}
-#ifdef ENABLE_DEBUG_INFO
-
-void DebugLegacy(const CString& text, DWORD dwProcessId, DWORD dwThreadId)
-{
-#ifdef USE_CONSOLE
- CONSOLE("%s", CT2A(text.GetString(), CP_UTF8));
-#endif
-
- if (CPluginSettings::HasInstance())
- {
-#ifdef ENABLE_DEBUG_SPLIT_FILE
- CPluginSettings* settings = CPluginSettings::GetInstance();
-
- bool isWorkingThread = settings->IsWorkingThread(dwThreadId);
-
- std::wstring processor;
- wchar_t tmp[10];
- _itow_s(::GetCurrentProcessId(), tmp, 10);
- if (isWorkingThread)
- processor = L"tab" + std::wstring(tmp) + L"_thread";
- else
- processor = L"tab" + std::wstring(tmp) + L"_ui";
-#else
- if (dwProcessId == 0)
- {
- dwProcessId = ::GetCurrentProcessId();
- }
- if (dwThreadId == 0)
- {
- dwThreadId = ::GetCurrentThreadId();
- }
-
- CStringA processInfo;
- processInfo.Format("%4.4u.%4.4u - ", dwProcessId, dwThreadId);
-#endif
- SYSTEMTIME st;
- ::GetSystemTime(&st);
-
- CStringA sysTime;
- sysTime.Format("%2.2d:%2.2d:%2.2d.%3.3d - ", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
-
- CPluginDebugLock lock;
- if (lock.IsLocked())
- {
- std::ofstream debugFile;
-
-#ifdef ENABLE_DEBUG_SPLIT_FILE
- debugFile.open(GetDataPath(L"debug_" + processor + L".txt"), std::ios::app);
-#else
- debugFile.open(GetDataPath(L"debug.txt"), std::ios::app);
-#endif
- int pos = 0;
- CStringA line = text.Tokenize(L"\n\r", pos);
-
- while (pos >= 0)
- {
- debugFile.write(sysTime.GetBuffer(), sysTime.GetLength());
-#ifndef ENABLE_DEBUG_SPLIT_FILE
- debugFile.write(processInfo.GetBuffer(), processInfo.GetLength());
-#endif
- debugFile.write(line.GetBuffer(), line.GetLength());
- debugFile.write("\n", 1);
-
- line = text.Tokenize(L"\n\r", pos);
- }
-
- debugFile.flush();
- }
- }
-}
-
-void CPluginDebug::Debug(const std::string& text, DWORD processId, DWORD threadId)
-{
- DebugLegacy(CString(text.c_str()), processId, threadId);
-}
-
-void CPluginDebug::Debug(const std::wstring& text, DWORD processId, DWORD threadId)
-{
- DebugLegacy(ToCString(text), processId, threadId);
-}
-
-#endif
-
#if (defined ENABLE_DEBUG_INFO)
void CPluginDebug::DebugException(const std::exception& ex)
{
- auto error = std::string("!!! Exception:") + ex.what();
+ auto lt = new LogTextFixed(ex);
+ LogEntry le(lt);
#ifdef ENABLE_DEBUG_ERROR
- Debug(error);
+ LogWriteDefault(le);
#endif
-
- DEBUG_SELFTEST("********************************************************************************\n" + error + "\n********************************************************************************")
-}
-
-void DebugErrorCodeLegacy(DWORD errorCode, const CString& error, DWORD dwProcessId, DWORD dwThreadId)
-{
- CString errorCodeText;
- errorCodeText.Format(L"%u (0x%8.8x)", errorCode, errorCode);
-
- CString finalError = error + L". error=" + errorCodeText;
-
-#ifdef ENABLE_DEBUG_ERROR
- DebugLegacy(finalError, dwProcessId, dwThreadId);
-#endif
-
- DEBUG_SELFTEST(L"********************************************************************************\n" + finalError + "\n********************************************************************************")
+ DEBUG_SELFTEST(
+ "********************************************************************************\n"
+ + lt->text() + "\n"
+ "********************************************************************************")
}
void CPluginDebug::DebugErrorCode(DWORD errorCode, const std::string& error, DWORD processId, DWORD threadId)
{
- DebugErrorCodeLegacy(errorCode, CString(error.c_str()), processId, threadId);
+ auto lt = new LogTextErrorCode(errorCode, error);
+ LogEntry le(lt, processId, threadId);
+#ifdef ENABLE_DEBUG_ERROR
+ LogWriteDefault(le);
+#endif
+ DEBUG_SELFTEST(
+ "********************************************************************************\n"
+ + lt->text() + "\n"
+ "********************************************************************************")
}
#endif
@@ -171,69 +266,51 @@
#ifdef ENABLE_DEBUG_RESULT
-void DebugResultLegacy(const CString& text)
-{
- SYSTEMTIME st;
- ::GetSystemTime(&st);
-
- CStringA sysTime;
- sysTime.Format("%2.2d:%2.2d:%2.2d.%3.3d - ", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
-
- CStringA textA = text;
-
- CPluginDebugLock lock;
- if (lock.IsLocked())
- {
- std::ofstream debugFile;
-
- debugFile.open(GetDataPath(L"debug_result.txt"), std::ios::app);
- debugFile.write(sysTime.GetBuffer(), sysTime.GetLength());
- debugFile.write(LPCSTR(textA), textA.GetLength());
- debugFile.write("\n", 1);
- debugFile.flush();
- }
-}
-
void CPluginDebug::DebugResult(const std::wstring& text)
{
- DebugResultLegacy(ToCString(text));
+ LogWriteResult(LogEntry(new LogTextFixed(ToUtf8String(text))));
}
void CPluginDebug::DebugResultDomain(const std::wstring& domain)
{
- DebugResult(L"===========================================================================================================================================================================================");
- DebugResult(domain);
- DebugResult(L"===========================================================================================================================================================================================");
+ DebugResult(
+ L"=========================================================================================\n"
+ + domain + L"\n"
+ L"=========================================================================================");
}
+namespace
+{
+ void DebugResultFormat(const std::wstring& action, const std::wstring& type, const std::wstring& param1, const std::wstring& param2)
+ {
+ std::wostringstream ss;
+ ss << std::setw(7) << std::setiosflags(std::ios::left) << action;
+ ss << L" ";
+ ss << std::setw(12) << std::setiosflags(std::ios::left) << type;
+ ss << L" " << param1 << L" " << param2;
+ CPluginDebug::DebugResult(ss.str());
+ }
+
+ std::wstring Shorten(const std::wstring& s)
+ {
+ auto n = s.length();
+ if (n <= 100) return s;
+ auto r = s.substr(0, 67);
+ r += L"...";
+ r += s.substr(n - 30, 30);
+ return r;
+ }
+}
void CPluginDebug::DebugResultBlocking(const std::wstring& type, const std::wstring& src, const std::wstring& domain)
{
- CString srcTrunc = ToCString(src);
- if (src.length() > 100)
- {
- srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30);
- }
-
- CString blocking;
- blocking.Format(L"Blocked %-12s %-20s %s", ToCString(type), domain.empty()? L"-" : ToCString(domain), srcTrunc);
-
- DebugResultLegacy(blocking);
+ DebugResultFormat(L"Blocked", type, domain.empty() ? L"-" : domain, Shorten(src));
}
void CPluginDebug::DebugResultHiding(const std::wstring& tag, const std::wstring& id, const std::wstring& filter)
{
- CString srcTrunc = ToCString(id);
- if (srcTrunc.GetLength() > 100)
- {
- srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30);
- }
-
- CString blocking;
- blocking.Format(L"Hidden %-12s - %s %s", ToCString(tag), srcTrunc, ToCString(filter));
-
- DebugResultLegacy(blocking);
+ DebugResultFormat(L"Hidden", tag, L"- " + Shorten(id), filter);
}
#endif // ENABLE_DEBUG_RESULT
@@ -243,16 +320,7 @@
void CPluginDebug::DebugResultIgnoring(const std::wstring& type, const std::wstring& src, const std::wstring& domain)
{
- CString srcTrunc = ToCString(src);
- if (src.length() > 100)
- {
- srcTrunc = srcTrunc.Left(67) + L"..." + srcTrunc.Right(30);
- }
-
- CString blocking;
- blocking.Format(L"Ignored %-12s %s %s", ToCString(type), domain.empty()? L"-" : ToCString(domain), srcTrunc);
-
- DebugResultLegacy(blocking);
+ DebugResultFormat(L"Ignored", type, domain.empty() ? L"-" : domain, Shorten(src));
}
#endif // ENABLE_DEBUG_RESULT_IGNORED
« 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