From 79a168a98355b323348d617a12bf911adf4372e0 Mon Sep 17 00:00:00 2001 From: Christian Rendina Date: Tue, 29 Nov 2022 13:48:41 +0100 Subject: [PATCH 1/3] Update ColorCoutSink for WIN32 --- examples/CMakeLists.txt | 22 ++++++-------- examples/snippet_coloredcout_main.cpp | 14 +++++---- sink_snippets/src/g3sinks/ColorCoutSink.h | 37 +++++++++++++++++++++-- 3 files changed, 52 insertions(+), 21 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 394aa13..0daca2e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -44,19 +44,15 @@ if(CHOICE_SINK_SYSLOG) endif() if(CHOICE_SINK_SNIPPETS) - - # ColoredCout is currently only implemented for UNIX/Linux terminals - if(UNIX) - # Log with color formatting to std::cout - include_directories(${g3sinks_SOURCE_DIR}/sink_snippets/src - ${G3LOG_INCLUDE_DIR}) - add_executable(example_coloredcout snippet_coloredcout_main.cpp) - target_link_libraries( - example_coloredcout - PRIVATE gtest_main - PRIVATE ${G3LOG_LIBRARY}) - target_compile_options(example_coloredcout PRIVATE) - endif() + # Log with color formatting to std::cout + include_directories(${g3sinks_SOURCE_DIR}/sink_snippets/src + ${G3LOG_INCLUDE_DIR}) + add_executable(example_coloredcout snippet_coloredcout_main.cpp) + target_link_libraries( + example_coloredcout + PRIVATE gtest_main + PRIVATE ${G3LOG_LIBRARY}) + target_compile_options(example_coloredcout PRIVATE) # shared memory, file descriptor sink. verifyfilelogdependencies(FILE_LOG_SINK_ERROR) diff --git a/examples/snippet_coloredcout_main.cpp b/examples/snippet_coloredcout_main.cpp index 3d183cf..d1bcd8a 100644 --- a/examples/snippet_coloredcout_main.cpp +++ b/examples/snippet_coloredcout_main.cpp @@ -18,12 +18,14 @@ int main() { LOG(INFO) << "An INFO message in white"; LOG(WARNING) << "A WARNING message will be in yellow"; #if 0 - LOG(FATAL) << "This call will exit the example. A failed CHECK call, \n" - << "a LOG(FATAL) or a fatal crash (seg fault or similar) will show up in RED\n" - << "\n\nThis call will also be DUPLICATED. One FATAL LOG message will be shown through the \n" - << "the crash handler and sent to cout, the LOG call will asynchronously send the LOG output to cout.\n" - << "Depending on when the crash handler sends the cout message the duplicate message will show up in \n" - << "ANY of the defined colors and might be INTERLEAVED with the other messages. Interleaving is to be expected by asynchronously calls" + LOG(FATAL) + << "This call will exit the example. A failed CHECK call, \n" + << "a LOG(FATAL) or a fatal crash (seg fault or similar) will show up in RED\n" + << "\n\nThis call will also be DUPLICATED. One FATAL LOG message will be shown through the \n" + << "the crash handler and sent to cout, the LOG call will asynchronously send the LOG output to cout.\n" + << "Depending on when the crash handler sends the cout message the duplicate message will show up in \n" + << "ANY of the defined colors and might be INTERLEAVED with the other messages. Interleaving is to be " + "expected by asynchronously calls"; #endif } // at this point all enqueued LOGs will have gone through in FIFO order and the logger is shutdown. diff --git a/sink_snippets/src/g3sinks/ColorCoutSink.h b/sink_snippets/src/g3sinks/ColorCoutSink.h index 59123b7..04484d0 100644 --- a/sink_snippets/src/g3sinks/ColorCoutSink.h +++ b/sink_snippets/src/g3sinks/ColorCoutSink.h @@ -3,12 +3,28 @@ #include #include -// NOTE: This works only on Linux/OSX -// TODO KjellKod: For Windows terminals you can tweak this easily: https://stackoverflow.com/a/4053879/1066879 +#ifdef _WIN32 + +#ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN 1 +#endif + +#include +#endif + struct ColorCoutSink { +#ifdef _WIN32 + ColorCoutSink() : hHandle_(GetStdHandle(STD_OUTPUT_HANDLE)) {} + + // Windows colors + // https://docs.microsoft.com/en-us/windows/console/console-screen-buffers#character-attributes + enum FG_Color { YELLOW = FOREGROUND_RED | FOREGROUND_GREEN, RED = FOREGROUND_RED, GREEN = FOREGROUND_GREEN, WHITE = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED }; +#else // Linux xterm color // http://stackoverflow.com/questions/2616906/how-do-i-output-coloured-text-to-a-linux-terminal enum FG_Color {YELLOW = 33, RED = 31, GREEN = 32, WHITE = 37}; +#endif + FG_Color GetColor(const LEVELS level) const { if (level.value == WARNING.value) { return YELLOW; } @@ -19,9 +35,13 @@ struct ColorCoutSink { } void reset() { +#ifdef _WIN32 + SetConsoleTextAttribute(hHandle_, WHITE); +#else std::ostringstream oss; oss << "\033[" << WHITE << "m" << " " << "\033[m" << std::endl; std::cout << oss.str(); +#endif } void ReceiveLogMessage(g3::LogMessageMover logEntry) { @@ -29,12 +49,25 @@ struct ColorCoutSink { auto color = GetColor(level); reset(); + +#ifdef _WIN32 + auto str = logEntry.get().toString(); + SetConsoleTextAttribute(hHandle_, (WORD)color); + DWORD written; + WriteConsoleA(hHandle_, str.c_str(), str.size(), &written, nullptr); +#else std::ostringstream oss; oss << "\033[" << color << "m" << logEntry.get().toString() << "\033[m" << std::endl; std::cout << oss.str(); +#endif reset(); } + +#ifdef _WIN32 + private: + HANDLE hHandle_; +#endif }; From 682d1e01d3de158d625c65bf69b9bd1679f86bdb Mon Sep 17 00:00:00 2001 From: Christian Rendina Date: Tue, 29 Nov 2022 14:01:09 +0100 Subject: [PATCH 2/3] Fix warning for x64 --- sink_snippets/src/g3sinks/ColorCoutSink.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sink_snippets/src/g3sinks/ColorCoutSink.h b/sink_snippets/src/g3sinks/ColorCoutSink.h index 04484d0..99d78e7 100644 --- a/sink_snippets/src/g3sinks/ColorCoutSink.h +++ b/sink_snippets/src/g3sinks/ColorCoutSink.h @@ -54,7 +54,7 @@ struct ColorCoutSink { auto str = logEntry.get().toString(); SetConsoleTextAttribute(hHandle_, (WORD)color); DWORD written; - WriteConsoleA(hHandle_, str.c_str(), str.size(), &written, nullptr); + WriteConsoleA(hHandle_, str.c_str(), (DWORD)str.size(), &written, nullptr); #else std::ostringstream oss; oss << "\033[" << color << "m" From 90a1aefd65a83e229a24c20bfc9f994d693712c6 Mon Sep 17 00:00:00 2001 From: Christian Rendina Date: Tue, 29 Nov 2022 23:58:04 +0100 Subject: [PATCH 3/3] Separate sinks between Linux and Windows --- sink_snippets/src/g3sinks/ColorCoutSink.h | 66 +------------------ .../src/g3sinks/ColorCoutSinkLinux.h | 35 ++++++++++ .../src/g3sinks/ColorCoutSinkWindows.h | 45 +++++++++++++ 3 files changed, 82 insertions(+), 64 deletions(-) create mode 100644 sink_snippets/src/g3sinks/ColorCoutSinkLinux.h create mode 100644 sink_snippets/src/g3sinks/ColorCoutSinkWindows.h diff --git a/sink_snippets/src/g3sinks/ColorCoutSink.h b/sink_snippets/src/g3sinks/ColorCoutSink.h index 04484d0..336811f 100644 --- a/sink_snippets/src/g3sinks/ColorCoutSink.h +++ b/sink_snippets/src/g3sinks/ColorCoutSink.h @@ -4,72 +4,10 @@ #include #ifdef _WIN32 - -#ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN 1 -#endif - -#include -#endif - -struct ColorCoutSink { -#ifdef _WIN32 - ColorCoutSink() : hHandle_(GetStdHandle(STD_OUTPUT_HANDLE)) {} - - // Windows colors - // https://docs.microsoft.com/en-us/windows/console/console-screen-buffers#character-attributes - enum FG_Color { YELLOW = FOREGROUND_RED | FOREGROUND_GREEN, RED = FOREGROUND_RED, GREEN = FOREGROUND_GREEN, WHITE = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED }; -#else - // Linux xterm color - // http://stackoverflow.com/questions/2616906/how-do-i-output-coloured-text-to-a-linux-terminal - enum FG_Color {YELLOW = 33, RED = 31, GREEN = 32, WHITE = 37}; -#endif - - - FG_Color GetColor(const LEVELS level) const { - if (level.value == WARNING.value) { return YELLOW; } - if (level.value == G3LOG_DEBUG.value) { return GREEN; } - if (g3::internal::wasFatal(level)) { return RED; } - - return WHITE; - } - - void reset() { -#ifdef _WIN32 - SetConsoleTextAttribute(hHandle_, WHITE); -#else - std::ostringstream oss; - oss << "\033[" << WHITE << "m" << " " << "\033[m" << std::endl; - std::cout << oss.str(); -#endif - } - - void ReceiveLogMessage(g3::LogMessageMover logEntry) { - auto level = logEntry.get()._level; - auto color = GetColor(level); - - reset(); - -#ifdef _WIN32 - auto str = logEntry.get().toString(); - SetConsoleTextAttribute(hHandle_, (WORD)color); - DWORD written; - WriteConsoleA(hHandle_, str.c_str(), str.size(), &written, nullptr); +#include "ColorCoutSinkWindows.h" #else - std::ostringstream oss; - oss << "\033[" << color << "m" - << logEntry.get().toString() << "\033[m" << std::endl; - std::cout << oss.str(); -#endif - reset(); - } - -#ifdef _WIN32 - private: - HANDLE hHandle_; +#include "ColorCoutSinkLinux.h" #endif -}; - /* Example usage from snippet_coloredcout_main.cpp #include diff --git a/sink_snippets/src/g3sinks/ColorCoutSinkLinux.h b/sink_snippets/src/g3sinks/ColorCoutSinkLinux.h new file mode 100644 index 0000000..f75898a --- /dev/null +++ b/sink_snippets/src/g3sinks/ColorCoutSinkLinux.h @@ -0,0 +1,35 @@ +#pragma once + +struct ColorCoutSink { + // Linux xterm color + // http://stackoverflow.com/questions/2616906/how-do-i-output-coloured-text-to-a-linux-terminal + enum FG_Color {YELLOW = 33, RED = 31, GREEN = 32, WHITE = 37}; + + + FG_Color GetColor(const LEVELS level) const { + if (level.value == WARNING.value) { return YELLOW; } + if (level.value == G3LOG_DEBUG.value) { return GREEN; } + if (g3::internal::wasFatal(level)) { return RED; } + + return WHITE; + } + + void reset() { + std::ostringstream oss; + oss << "\033[" << WHITE << "m" << " " << "\033[m" << std::endl; + std::cout << oss.str(); + } + + void ReceiveLogMessage(g3::LogMessageMover logEntry) { + auto level = logEntry.get()._level; + auto color = GetColor(level); + + reset(); + + std::ostringstream oss; + oss << "\033[" << color << "m" + << logEntry.get().toString() << "\033[m" << std::endl; + std::cout << oss.str(); + reset(); + } +}; diff --git a/sink_snippets/src/g3sinks/ColorCoutSinkWindows.h b/sink_snippets/src/g3sinks/ColorCoutSinkWindows.h new file mode 100644 index 0000000..f50e5ba --- /dev/null +++ b/sink_snippets/src/g3sinks/ColorCoutSinkWindows.h @@ -0,0 +1,45 @@ +#pragma once + +#ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN 1 +#endif + +#include + +struct ColorCoutSink { + ColorCoutSink() : hHandle_(GetStdHandle(STD_OUTPUT_HANDLE)) {} + + // Windows colors + // https://docs.microsoft.com/en-us/windows/console/console-screen-buffers#character-attributes + enum FG_Color { YELLOW = FOREGROUND_RED | FOREGROUND_GREEN, RED = FOREGROUND_RED, GREEN = FOREGROUND_GREEN, WHITE = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED }; + + + FG_Color GetColor(const LEVELS level) const { + if (level.value == WARNING.value) { return YELLOW; } + if (level.value == G3LOG_DEBUG.value) { return GREEN; } + if (g3::internal::wasFatal(level)) { return RED; } + + return WHITE; + } + + void reset() { + SetConsoleTextAttribute(hHandle_, WHITE); + } + + void ReceiveLogMessage(g3::LogMessageMover logEntry) { + auto level = logEntry.get()._level; + auto color = GetColor(level); + + reset(); + + auto str = logEntry.get().toString(); + SetConsoleTextAttribute(hHandle_, (WORD)color); + + std::cout << str; + + reset(); + } + + private: + HANDLE hHandle_; +};