2#ifndef _LOGIT_CONSOLE_LOGGER_HPP_INCLUDED
3#define _LOGIT_CONSOLE_LOGGER_HPP_INCLUDED
14#include <emscripten/emscripten.h>
70 std::lock_guard<std::mutex> lock(
m_mutex);
78 std::lock_guard<std::mutex> lock(
m_mutex);
89 void log(
const LogRecord& record,
const std::string& message)
override {
92 std::lock_guard<std::mutex> lock(
m_mutex);
93 handle_ansi_colors_emscripten(message);
96 std::unique_lock<std::mutex> lock(
m_mutex);
100 handle_ansi_colors_windows(message);
103 std::cout << message << std::endl;
109 std::lock_guard<std::mutex> lock(
m_mutex);
112 handle_ansi_colors_windows(message);
115 std::cout << message << std::endl;
135 return std::string();
181 std::unique_lock<std::mutex> lock(
m_mutex);
197 enum class WinColor {
218 void handle_ansi_colors_windows(
const std::string& message)
const {
219 std::string::size_type start = 0;
220 std::string::size_type pos = 0;
222 HANDLE handle_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
224 while ((pos = message.find(
"\033[", start)) != std::string::npos) {
227 std::cout << message.substr(start, pos - start);
231 std::string::size_type end_pos = message.find(
'm', pos);
232 if (end_pos != std::string::npos) {
234 std::string ansi_code = message.substr(pos + 2, end_pos - pos - 2);
235 apply_color_from_ansi_code(ansi_code, handle_stdout);
245 if (start < message.size()) {
246 std::cout << message.substr(start);
248 if (!message.empty()) std::cout << std::endl;
251 SetConsoleTextAttribute(handle_stdout,
static_cast<WORD
>(text_color_to_win_color(
m_config.default_color)));
257 void apply_color_from_ansi_code(
const std::string& ansi_code, HANDLE handle_stdout)
const {
258 WORD color_value =
static_cast<WORD
>(text_color_to_win_color(
m_config.default_color));
259 const int code = std::stoi(ansi_code);
261 case 30: color_value =
static_cast<WORD
>(WinColor::Black);
break;
262 case 31: color_value =
static_cast<WORD
>(WinColor::DarkRed);
break;
263 case 32: color_value =
static_cast<WORD
>(WinColor::DarkGreen);
break;
264 case 33: color_value =
static_cast<WORD
>(WinColor::DarkYellow);
break;
265 case 34: color_value =
static_cast<WORD
>(WinColor::DarkBlue);
break;
266 case 35: color_value =
static_cast<WORD
>(WinColor::DarkMagenta);
break;
267 case 36: color_value =
static_cast<WORD
>(WinColor::DarkCyan);
break;
268 case 37: color_value =
static_cast<WORD
>(WinColor::Gray);
break;
269 case 90: color_value =
static_cast<WORD
>(WinColor::DarkGray);
break;
270 case 91: color_value =
static_cast<WORD
>(WinColor::Red);
break;
271 case 92: color_value =
static_cast<WORD
>(WinColor::Green);
break;
272 case 93: color_value =
static_cast<WORD
>(WinColor::Yellow);
break;
273 case 94: color_value =
static_cast<WORD
>(WinColor::Blue);
break;
274 case 95: color_value =
static_cast<WORD
>(WinColor::Magenta);
break;
275 case 96: color_value =
static_cast<WORD
>(WinColor::Cyan);
break;
276 case 97: color_value =
static_cast<WORD
>(WinColor::White);
break;
282 SetConsoleTextAttribute(handle_stdout, color_value);
288 WinColor text_color_to_win_color(
const TextColor& color)
const {
306 default:
return WinColor::White;
311# ifdef __EMSCRIPTEN__
313 const char* text_color_to_css(
TextColor color)
const {
331 default:
return "inherit";
336 std::string css_color_from_ansi(
const std::string& code)
const {
337 int value = std::stoi(code);
339 case 30:
return "black";
340 case 31:
return "darkred";
341 case 32:
return "darkgreen";
342 case 33:
return "olive";
343 case 34:
return "darkblue";
344 case 35:
return "purple";
345 case 36:
return "teal";
346 case 37:
return "lightgray";
347 case 90:
return "gray";
348 case 91:
return "red";
349 case 92:
return "green";
350 case 93:
return "yellow";
351 case 94:
return "blue";
352 case 95:
return "magenta";
353 case 96:
return "cyan";
354 case 97:
return "white";
355 default:
return text_color_to_css(
m_config.default_color);
360 void handle_ansi_colors_emscripten(
const std::string& message)
const {
361 std::string current_color = text_color_to_css(
m_config.default_color);
362 std::string::size_type start = 0;
363 std::string::size_type pos = 0;
365 while ((pos = message.find(
"\033[", start)) != std::string::npos) {
367 std::string part = message.substr(start, pos - start);
368 EM_ASM_({ console.log(
'%c' + UTF8ToString($0),
'color: ' + UTF8ToString($1)); }, part.c_str(), current_color.c_str());
370 std::string::size_type end_pos = message.find(
'm', pos);
371 if (end_pos != std::string::npos) {
372 std::string ansi_code = message.substr(pos + 2, end_pos - pos - 2);
373 current_color = css_color_from_ansi(ansi_code);
380 if (start < message.size()) {
381 std::string part = message.substr(start);
382 EM_ASM_({ console.log(
'%c' + UTF8ToString($0),
'color: ' + UTF8ToString($1)); }, part.c_str(), current_color.c_str());
389# ifdef __EMSCRIPTEN__
392# elif defined(_WIN32)
393 handle_ansi_colors_windows(std::string());
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 ¶m) const override
Retrieves a floating-point parameter from the logger.
LogLevel get_log_level() const override
Gets the minimal log level for this 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 ¶m) const override
Retrieves a string parameter from the logger.
void set_config(const Config &config)
Sets the logger configuration.
int64_t get_int_param(const LoggerParam ¶m) const override
Retrieves an integer parameter from the logger.
ConsoleLogger(const bool async)
Constructor with asynchronous flag.
std::atomic< int > m_log_level
void set_log_level(LogLevel level) override
Sets the minimal log level for this logger.
Config get_config()
Gets the current logger configuration.
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.
void reset_color()
Resets the console text color to the default.
Interface for loggers that handle log message output.
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.
#define LOGIT_CURRENT_TIMESTAMP_MS()
Macro to get the current timestamp in milliseconds.
#define LOGIT_DEFAULT_COLOR
Defines the default color for console output.
The primary namespace for the LogIt++ library.
std::string to_string(LogLevel level, int mode=0)
Convert LogLevel to a std::string representation.
@ LOG_LVL_TRACE
Trace level logging.
LoggerParam
Enumeration for different logger parameters that can be retrieved.
@ TimeSinceLastLog
The time elapsed since the last log in seconds.
@ LastLogTimestamp
The timestamp of the last log.
TextColor
Text colors for console output.
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.
const int64_t timestamp_ms
Timestamp in milliseconds.