From 895d4d417299faa0b8dafdde2065ceb55754c1e7 Mon Sep 17 00:00:00 2001 From: Dale Glass Date: Mon, 12 Oct 2020 17:40:21 +0200 Subject: [PATCH 1/3] Improve logging: color, ms timestamps, PID, thread id via environment variable Set VIRCADIA_LOG_OPTIONS to a string containing these keywords: color milliseconds process_id thread_id The separator doesn't matter. Example: $ export VIRCADIA_LOG_OPTIONS="color milliseconds" --- libraries/shared/src/LogHandler.cpp | 53 ++++++++++++++++++++++++++++- libraries/shared/src/LogHandler.h | 3 +- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index aff4de6e3a..e8d296f136 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -32,6 +32,26 @@ LogHandler& LogHandler::getInstance() { return staticInstance; } +LogHandler::LogHandler() { + QString log_options = qgetenv("VIRCADIA_LOG_OPTIONS").toLower(); + + if (log_options.contains("color")) { + _useColor = 1; + } + + if (log_options.contains("process_id")) { + _shouldOutputProcessID = true; + } + + if (log_options.contains("thread_id")) { + _shouldOutputThreadID = true; + } + + if (log_options.contains("milliseconds")) { + _shouldDisplayMilliseconds = true; + } +} + const char* stringForLogType(LogMsgType msgType) { switch (msgType) { case LogInfo: @@ -51,6 +71,29 @@ const char* stringForLogType(LogMsgType msgType) { } } +const char* colorForLogType(LogMsgType msgType) { + switch (msgType) { + case LogInfo: + return "\u001b[37;1m"; // Bold white + case LogDebug: + return ""; + case LogWarning: + return "\u001b[35;1m"; // Bright magenta + case LogCritical: + return "\u001b[31;1m"; // Bright red + case LogFatal: + return "\u001b[31;1m"; // Bright red + case LogSuppressed: + return ""; + default: + return ""; + } +} + +const char* colorReset() { + return "\u001b[0m"; +} + // the following will produce 11/18 13:55:36 const QString DATE_STRING_FORMAT = "MM/dd hh:mm:ss"; @@ -133,7 +176,15 @@ QString LogHandler::printMessage(LogMsgType type, const QMessageLogContext& cont QString logMessage = QString("%1 %2\n").arg(prefixString, message.split('\n').join('\n' + prefixString + " ")); - fprintf(stdout, "%s", qPrintable(logMessage)); + const char* color = ""; + const char* resetColor = ""; + + if (_useColor) { + color = colorForLogType(type); + resetColor = colorReset(); + } + + fprintf(stdout, "%s%s%s", color, qPrintable(logMessage), resetColor); #ifdef Q_OS_WIN // On windows, this will output log lines into the Visual Studio "output" tab OutputDebugStringA(qPrintable(logMessage)); diff --git a/libraries/shared/src/LogHandler.h b/libraries/shared/src/LogHandler.h index 8f84899b78..7bd5c69c63 100644 --- a/libraries/shared/src/LogHandler.h +++ b/libraries/shared/src/LogHandler.h @@ -57,7 +57,7 @@ public: void setupRepeatedMessageFlusher(); private: - LogHandler() = default; + LogHandler(); ~LogHandler() = default; void flushRepeatedMessages(); @@ -66,6 +66,7 @@ private: bool _shouldOutputProcessID { false }; bool _shouldOutputThreadID { false }; bool _shouldDisplayMilliseconds { false }; + bool _useColor { false }; int _currentMessageID { 0 }; struct RepeatedMessageRecord { From 112459042265626c4585878b4b531bbf7f8ee977 Mon Sep 17 00:00:00 2001 From: Dale Glass Date: Fri, 16 Oct 2020 20:16:44 +0200 Subject: [PATCH 2/3] Enable color by default on Unix, change to comma separators. Also emit a message if an unrecognized log option is used. --- libraries/shared/src/LogHandler.cpp | 40 +++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index e8d296f136..5009fe9194 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -17,6 +17,10 @@ #ifdef Q_OS_WIN #include #endif +#ifdef Q_OS_UNIX +#include +#include +#endif #include #include @@ -33,22 +37,36 @@ LogHandler& LogHandler::getInstance() { } LogHandler::LogHandler() { - QString log_options = qgetenv("VIRCADIA_LOG_OPTIONS").toLower(); + QString logOptions = qgetenv("VIRCADIA_LOG_OPTIONS").toLower(); - if (log_options.contains("color")) { - _useColor = 1; +#ifdef Q_OS_UNIX + // Enable color by default if we're on Unix, and output is a tty (so we're not being piped into something) + // + // On Windows the situation is more complex, and color is supported or not depending on version and + // registry settings, so for now it's off by default and it's up to the user to do what's required. + if (isatty(fileno(stdout))) { + _useColor = true; } +#endif - if (log_options.contains("process_id")) { - _shouldOutputProcessID = true; - } + auto optionList = logOptions.split(","); - if (log_options.contains("thread_id")) { - _shouldOutputThreadID = true; - } + for(auto option : optionList) { + option = option.trimmed(); - if (log_options.contains("milliseconds")) { - _shouldDisplayMilliseconds = true; + if (option == "color") { + _useColor = true; + } else if (option == "nocolor") { + _useColor = false; + } else if (option == "process_id") { + _shouldOutputProcessID = true; + } else if (option == "thread_id") { + _shouldOutputThreadID = true; + } else if (option == "milliseconds") { + _shouldDisplayMilliseconds = true; + } else if (option != "") { + fprintf(stdout, "Unrecognized option in VIRCADIA_LOG_OPTIONS: '%s'\n", option.toUtf8().constData()); + } } } From 6c25b9470d1d73f4c39d4adf8ea050cc9faf5931 Mon Sep 17 00:00:00 2001 From: daleglass <51060919+daleglass@users.noreply.github.com> Date: Thu, 29 Oct 2020 19:20:18 +0100 Subject: [PATCH 3/3] Update libraries/shared/src/LogHandler.cpp Co-authored-by: kasenvr <52365539+kasenvr@users.noreply.github.com> --- libraries/shared/src/LogHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/LogHandler.cpp b/libraries/shared/src/LogHandler.cpp index 5009fe9194..72d53f0bcb 100644 --- a/libraries/shared/src/LogHandler.cpp +++ b/libraries/shared/src/LogHandler.cpp @@ -51,7 +51,7 @@ LogHandler::LogHandler() { auto optionList = logOptions.split(","); - for(auto option : optionList) { + for (auto option : optionList) { option = option.trimmed(); if (option == "color") {