ifm3d
log_writer_console_colored.h
1 // -*- c++ -*-
2 /*
3  * Copyright 2023-present ifm electronic, gmbh
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef IFM3D_COMMON_LOGGING_LOG_WRITER_CONSOLE_COLORED_H
8 #define IFM3D_COMMON_LOGGING_LOG_WRITER_CONSOLE_COLORED_H
9 
10 #include <ifm3d/common/logging/log_writer_console.h>
11 #ifdef _WIN32
12 # ifndef WIN32_LEAN_AND_MEAN
13 # define WIN32_LEAN_AND_MEAN
14 # endif
15 # define NOMINMAX
16 # include <windows.h>
17 # undef GetMessage
18 #endif
19 
20 namespace ifm3d
21 {
22  template <class Formatter,
23  typename std::enable_if_t<std::is_same_v<
24  decltype(Formatter::format(
25  ifm3d::LogEntry("", ifm3d::LogLevel::Info, "", "", 1))),
26  std::string>>* = nullptr>
27  class LogWriterConsoleColored : public LogWriterConsole<Formatter>
28  {
29  public:
30  LogWriterConsoleColored(Output out = Output::StdErr)
32  {
33 #ifdef _WIN32
34  colored_output_available_ =
35  this->is_a_tty_ && EnableVirtualTerminalProcessing();
36 #else
37  colored_output_available_ = this->is_a_tty_;
38 #endif
39  }
40 
41  void
42  Write(const LogEntry& entry) override
43  {
44  if (this->colored_output_available_)
45  {
46  const auto str = Formatter::format(entry);
47  const std::lock_guard<std::mutex> lock(this->mutex_);
48  this->SetColor(entry.GetLogLevel());
49  this->out_ << str;
50  this->ResetColor();
51  this->out_ << std::endl;
52  }
53  else
54  {
56  }
57  }
58 
59  protected:
60  bool colored_output_available_ = false;
61 #ifdef _WIN32
62  bool
63  EnableVirtualTerminalProcessing()
64  {
65  HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
66  if (hOut == INVALID_HANDLE_VALUE)
67  {
68  return false;
69  }
70 
71  DWORD dwMode = 0;
72  if (!GetConsoleMode(hOut, &dwMode))
73  {
74  return false;
75  }
76 
77  dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
78  if (!SetConsoleMode(hOut, dwMode))
79  {
80  return false;
81  }
82  return true;
83  }
84 #endif
85 
86  void
87  SetColor(LogLevel log_level)
88  {
89  switch (log_level)
90  {
91  case LogLevel::Critical:
92  this->out_ << "\x1B[97m\x1B[41m"; // white on red background
93  break;
94 
95  case LogLevel::Error:
96  this->out_ << "\x1B[91m"; // red
97  break;
98 
99  case LogLevel::Warning:
100  this->out_ << "\x1B[93m"; // yellow
101  break;
102 
103  case LogLevel::Debug:
104  case LogLevel::Verbose:
105  this->out_ << "\x1B[96m"; // cyan
106  break;
107  default:
108  break;
109  }
110  }
111 
112  void
113  ResetColor()
114  {
115  this->out_ << "\x1B[0m\x1B[0K";
116  }
117  };
118 }
119 #endif // IFM3D_COMMON_LOGGING_LOG_WRITER_CONSOLE_COLORED_H
ifm3d::LogEntry
Definition: log_entry.h:19
ifm3d::LogWriterConsole
Definition: log_writer_console.h:38
ifm3d::LogWriterConsoleColored
Definition: log_writer_console_colored.h:27