LogIt++
Loading...
Searching...
No Matches
ConsoleLogger.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef _LOGIT_CONSOLE_LOGGER_HPP_INCLUDED
3#define _LOGIT_CONSOLE_LOGGER_HPP_INCLUDED
6
7#include "ILogger.hpp"
8#include <iostream>
9#if defined(_WIN32)
10#include <windows.h>
11#endif
12#include <mutex>
13#include <atomic>
14
15namespace logit {
16
28 class ConsoleLogger : public ILogger {
29 public:
30
33 struct Config {
34 TextColor default_color = LOGIT_DEFAULT_COLOR;
35 bool async = true;
36 };
37
41 }
42
45 ConsoleLogger(const Config& config) : m_config(config) {
47 }
48
51 ConsoleLogger(const bool async) {
52 m_config.async = async;
54 }
55
56 virtual ~ConsoleLogger() = default;
57
61 void set_config(const Config& config) {
62 std::lock_guard<std::mutex> lock(m_mutex);
63 m_config = config;
64 }
65
70 std::lock_guard<std::mutex> lock(m_mutex);
71 return m_config;
72 }
73
81 void log(const LogRecord& record, const std::string& message) override {
83 std::unique_lock<std::mutex> lock(m_mutex);
84 if (!m_config.async) {
85# if defined(__MINGW32__) || defined(_WIN32)
86 // For Windows, parse the message for ANSI color codes and apply them
88# else
89 // For other systems, output the message as is
90 std::cout << message << std::endl;
91# endif
92 return;
93 }
94 lock.unlock();
95 TaskExecutor::get_instance().add_task([this, message](){
96 std::lock_guard<std::mutex> lock(m_mutex);
97# if defined(_WIN32)
98 // For Windows, parse the message for ANSI color codes and apply them
100# else
101 // For other systems, output the message as is
102 std::cout << message << std::endl;
103# endif
104 });
105 }
106
114 std::string get_string_param(const LoggerParam& param) const override {
115 switch (param) {
116 case LoggerParam::LastLogTimestamp: return std::to_string(get_last_log_ts());
117 case LoggerParam::TimeSinceLastLog: return std::to_string(get_time_since_last_log());
118 default:
119 break;
120 };
121 return std::string();
122 }
123
127 int64_t get_int_param(const LoggerParam& param) const override {
128 switch (param) {
131 default:
132 break;
133 };
134 return 0;
135 }
136
140 double get_float_param(const LoggerParam& param) const override {
141 switch (param) {
142 case LoggerParam::LastLogTimestamp: return (double)get_last_log_ts() / 1000.0;
143 case LoggerParam::TimeSinceLastLog: return (double)get_time_since_last_log() / 1000.0;
144 default:
145 break;
146 };
147 return 0.0;
148 }
149
152 void wait() override {
153 std::unique_lock<std::mutex> lock(m_mutex);
154 if (!m_config.async) return;
155 lock.unlock();
157 }
158
159 private:
160 mutable std::mutex m_mutex;
162 std::atomic<int64_t> m_last_log_ts = ATOMIC_VAR_INIT(0);
163
164# if defined(_WIN32)
165
166 // Windows console colors
167 enum class WinColor {
168 Black = 0,
175 Gray = 7,
177 Blue = 9,
178 Green = 10,
179 Cyan = 11,
180 Red = 12,
182 Yellow = 14,
183 White = 15,
184 };
185
188 void handle_ansi_colors_windows(const std::string& message) const {
189 std::string::size_type start = 0;
190 std::string::size_type pos = 0;
191
192 HANDLE handle_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
193
194 while ((pos = message.find("\033[", start)) != std::string::npos) {
195 // Output the part of the string before the ANSI code
196 if (pos > start) {
197 std::cout << message.substr(start, pos - start);
198 }
199
200 // Find the end of the ANSI code
201 std::string::size_type end_pos = message.find('m', pos);
202 if (end_pos != std::string::npos) {
203 // Extract the ANSI code
204 std::string ansi_code = message.substr(pos + 2, end_pos - pos - 2);
205 apply_color_from_ansi_code(ansi_code, handle_stdout);
206
207 // Update position
208 start = end_pos + 1;
209 } else {
210 break;
211 }
212 }
213
214 // Output any remaining part of the message
215 if (start < message.size()) {
216 std::cout << message.substr(start);
217 }
218 if (!message.empty()) std::cout << std::endl;
219
220 // Reset the console color to default
221 SetConsoleTextAttribute(handle_stdout, static_cast<WORD>(text_color_to_win_color(m_config.default_color)));
222 }
223
227 void apply_color_from_ansi_code(const std::string& ansi_code, HANDLE handle_stdout) const {
228 WORD color_value = static_cast<WORD>(text_color_to_win_color(m_config.default_color)); // Default color
229 const int code = std::stoi(ansi_code);
230 switch (code) {
231 case 30: color_value = static_cast<WORD>(WinColor::Black); break;
232 case 31: color_value = static_cast<WORD>(WinColor::DarkRed); break;
233 case 32: color_value = static_cast<WORD>(WinColor::DarkGreen); break;
234 case 33: color_value = static_cast<WORD>(WinColor::DarkYellow); break;
235 case 34: color_value = static_cast<WORD>(WinColor::DarkBlue); break;
236 case 35: color_value = static_cast<WORD>(WinColor::DarkMagenta); break;
237 case 36: color_value = static_cast<WORD>(WinColor::DarkCyan); break;
238 case 37: color_value = static_cast<WORD>(WinColor::Gray); break;
239 case 90: color_value = static_cast<WORD>(WinColor::DarkGray); break;
240 case 91: color_value = static_cast<WORD>(WinColor::Red); break;
241 case 92: color_value = static_cast<WORD>(WinColor::Green); break;
242 case 93: color_value = static_cast<WORD>(WinColor::Yellow); break;
243 case 94: color_value = static_cast<WORD>(WinColor::Blue); break;
244 case 95: color_value = static_cast<WORD>(WinColor::Magenta); break;
245 case 96: color_value = static_cast<WORD>(WinColor::Cyan); break;
246 case 97: color_value = static_cast<WORD>(WinColor::White); break;
247 default:
248 // Unknown code, use default color
249 break;
250 };
251 // Set the console text attribute to the desired color
252 SetConsoleTextAttribute(handle_stdout, color_value);
253 }
254
279# endif
280
282 void reset_color() {
283# if defined(_WIN32)
284 handle_ansi_colors_windows(std::string());
285# else
286 std::cout << to_string(m_config.default_color);
287# endif
288 }
289
292 int64_t get_last_log_ts() const {
293 return m_last_log_ts;
294 }
295
298 int64_t get_time_since_last_log() const {
299 return LOGIT_CURRENT_TIMESTAMP_MS() - m_last_log_ts;
300 }
301 }; // ConsoleLogger
302
303}; // namespace logit
304
305#endif // _LOGIT_CONSOLE_LOGGER_HPP_INCLUDED
Defines the interface for loggers used in the logging system.
void log(const LogRecord &record, const std::string &message) override
Logs a message to the console with thread safety.
ConsoleLogger()
Default constructor that uses default configuration.
double get_float_param(const LoggerParam &param) const override
Retrieves a floating-point parameter from the logger.
std::mutex m_mutex
Mutex to protect console output.
int64_t get_last_log_ts() const
Retrieves the timestamp of the last log.
virtual ~ConsoleLogger()=default
int64_t get_time_since_last_log() const
Retrieves the time since the last log.
std::string get_string_param(const LoggerParam &param) const override
Retrieves a string parameter from the logger.
WinColor text_color_to_win_color(const TextColor &color) const
Convert TextColor to WinColor.
void set_config(const Config &config)
Sets the logger configuration. This method sets the logger's configuration and ensures thread safety ...
void handle_ansi_colors_windows(const std::string &message) const
Handle ANSI color codes in the message for Windows console.
int64_t get_int_param(const LoggerParam &param) const override
Retrieves an integer parameter from the logger.
ConsoleLogger(const bool async)
Constructor with asynchronous flag.
void apply_color_from_ansi_code(const std::string &ansi_code, HANDLE handle_stdout) const
Apply color based on ANSI code for Windows console.
Config get_config()
Gets the current logger configuration. Returns the logger's configuration with thread safety ensured.
std::atomic< int64_t > m_last_log_ts
ConsoleLogger(const Config &config)
Constructor with custom configuration.
Config m_config
Configuration for the console logger.
void wait() override
Waits for all asynchronous tasks to complete. If asynchronous logging is enabled, waits for all pendi...
void reset_color()
Resets the console text color to the default.
Interface for loggers that handle log message output.
Definition ILogger.hpp:25
void add_task(std::function< void()> task)
Adds a task to the queue in a thread-safe manner.
void wait()
Waits for all tasks in the queue to be processed.
static TaskExecutor & get_instance()
Get the singleton instance of the TaskExecutor.
The primary namespace for the LogIt++ library.
std::string to_string(LogLevel level, int mode=0)
Convert LogLevel to a std::string representation.
Definition Enums.hpp:89
LoggerParam
Enumeration for different logger parameters that can be retrieved.
Definition Enums.hpp:46
@ TimeSinceLastLog
The time elapsed since the last log in seconds.
Definition Enums.hpp:50
@ LastLogTimestamp
The timestamp of the last log.
Definition Enums.hpp:49
TextColor
Text colors for console output.
Definition Enums.hpp:25
Configuration for the console logger.
bool async
Flag indicating whether logging should be asynchronous.
TextColor default_color
Default text color for console output.
Stores log metadata and content.
Definition LogRecord.hpp:13
const int64_t timestamp_ms
Timestamp in milliseconds.
Definition LogRecord.hpp:15