From aee2a63c2c003a7808b2a04d347cd28c0a464202 Mon Sep 17 00:00:00 2001 From: Christian Rendina Date: Thu, 1 Dec 2022 00:59:30 +0100 Subject: [PATCH] Update ColorCoutSink for WIN32 (#132) * Update ColorCoutSink for WIN32 * Separate sinks between Linux and Windows --- examples/CMakeLists.txt | 22 ++++----- examples/snippet_coloredcout_main.cpp | 14 +++--- sink_snippets/src/g3sinks/ColorCoutSink.h | 39 +++------------- .../src/g3sinks/ColorCoutSinkLinux.h | 35 +++++++++++++++ .../src/g3sinks/ColorCoutSinkWindows.h | 45 +++++++++++++++++++ 5 files changed, 102 insertions(+), 53 deletions(-) create mode 100644 sink_snippets/src/g3sinks/ColorCoutSinkLinux.h create mode 100644 sink_snippets/src/g3sinks/ColorCoutSinkWindows.h 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..336811f 100644 --- a/sink_snippets/src/g3sinks/ColorCoutSink.h +++ b/sink_snippets/src/g3sinks/ColorCoutSink.h @@ -3,40 +3,11 @@ #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 -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(); - } -}; - +#ifdef _WIN32 +#include "ColorCoutSinkWindows.h" +#else +#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_; +};