From a3e5296bf2350e55289736cfe34221fab947d7b2 Mon Sep 17 00:00:00 2001 From: Adam Honse Date: Tue, 5 May 2026 20:20:21 -0500 Subject: [PATCH] LogManager cleanup --- .../CorsairDRAMController.cpp | 2 +- .../ENESMBusController/ENESMBusController.cpp | 2 +- .../RGBController_LenovoUSB.cpp | 2 +- .../LogitechProtocolCommon.cpp | 2 +- DetectionManager.cpp | 4 +- LogManager.cpp | 529 ++++++++++-------- LogManager.h | 191 ++++--- OpenRGBPluginAPI.cpp | 4 +- OpenRGBPluginAPI.h | 2 +- OpenRGBPluginInterface.h | 2 +- ResourceManager.cpp | 2 +- cli.cpp | 24 +- qt/OpenRGBConsolePage/OpenRGBConsolePage.cpp | 14 +- qt/OpenRGBDialog/OpenRGBDialog.cpp | 26 +- 14 files changed, 481 insertions(+), 325 deletions(-) diff --git a/Controllers/CorsairDRAMController/CorsairDRAMController.cpp b/Controllers/CorsairDRAMController/CorsairDRAMController.cpp index a516020fd..834191ac9 100644 --- a/Controllers/CorsairDRAMController/CorsairDRAMController.cpp +++ b/Controllers/CorsairDRAMController/CorsairDRAMController.cpp @@ -366,7 +366,7 @@ void CorsairDRAMController::ReadDeviceInfo() /*-----------------------------------------------------*\ | Log Device Information Data | \*-----------------------------------------------------*/ - if(LogManager::get()->getLoglevel() >= LL_TRACE) + if(LogManager::get()->GetLogLevel() >= LL_TRACE) { char device_info_buf[256]; unsigned int pos; diff --git a/Controllers/ENESMBusController/ENESMBusController.cpp b/Controllers/ENESMBusController/ENESMBusController.cpp index 4697de718..749a4f831 100644 --- a/Controllers/ENESMBusController/ENESMBusController.cpp +++ b/Controllers/ENESMBusController/ENESMBusController.cpp @@ -53,7 +53,7 @@ ENESMBusController::ENESMBusController(ENESMBusInterface* interface, ene_dev_id | If this is running with TRACE or higher loglevel | | then dump the entire Feature list to log | \*-------------------------------------------------*/ - if(LogManager::get()->getLoglevel() >= LL_TRACE) + if(LogManager::get()->GetLogLevel() >= LL_TRACE) { LOG_TRACE("[ENE SMBus] ENE config table for 0x%02X:", dev); LOG_TRACE(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", config_table[0], config_table[1], config_table[2], config_table[3], diff --git a/Controllers/LenovoControllers/LenovoUSBController/RGBController_LenovoUSB.cpp b/Controllers/LenovoControllers/LenovoUSBController/RGBController_LenovoUSB.cpp index c38b86ffd..c8e022b3f 100644 --- a/Controllers/LenovoControllers/LenovoUSBController/RGBController_LenovoUSB.cpp +++ b/Controllers/LenovoControllers/LenovoUSBController/RGBController_LenovoUSB.cpp @@ -74,7 +74,7 @@ RGBController_LenovoUSB::RGBController_LenovoUSB(LenovoUSBController* controller type = DEVICE_TYPE_KEYBOARD; vendor = "Lenovo"; - if(LogManager::get()->getLoglevel() >= LL_TRACE) + if(LogManager::get()->GetLogLevel() >= LL_TRACE) { DumpControllerInformation(); } diff --git a/Controllers/LogitechController/LogitechProtocolCommon.cpp b/Controllers/LogitechController/LogitechProtocolCommon.cpp index 1fc21b5ea..16250ecdc 100644 --- a/Controllers/LogitechController/LogitechProtocolCommon.cpp +++ b/Controllers/LogitechController/LogitechProtocolCommon.cpp @@ -172,7 +172,7 @@ void logitech_device::initialiseDevice() | If this is running with DEBUG or higher loglevel then | | dump the entire Feature list to log | \*-----------------------------------------------------------------*/ - if(LogManager::get()->getLoglevel() > 4) + if(LogManager::get()->GetLogLevel() >= LL_DEBUG) { getDeviceFeatureList(); //This will populate the feature list } diff --git a/DetectionManager.cpp b/DetectionManager.cpp index 989b68699..66c6bcad2 100644 --- a/DetectionManager.cpp +++ b/DetectionManager.cpp @@ -1312,7 +1312,7 @@ void DetectionManager::BackgroundHIDInit() \*---------------------------------------------------------*/ void DetectionManager::RunHIDDetector(hid_device_info* current_hid_device, json detector_settings) { - if(LogManager::get()->getLoglevel() >= LL_DEBUG) + if(LogManager::get()->GetLogLevel() >= LL_DEBUG) { const char* manu_name = StringUtils::wchar_to_char(current_hid_device->manufacturer_string); const char* prod_name = StringUtils::wchar_to_char(current_hid_device->product_string); @@ -1426,7 +1426,7 @@ void DetectionManager::RunHIDDetector(hid_device_info* current_hid_device, json void DetectionManager::RunHIDWrappedDetector(const hidapi_wrapper* wrapper, hid_device_info* current_hid_device, json detector_settings) { - if(LogManager::get()->getLoglevel() >= LL_DEBUG) + if(LogManager::get()->GetLogLevel() >= LL_DEBUG) { const char* manu_name = StringUtils::wchar_to_char(current_hid_device->manufacturer_string); const char* prod_name = StringUtils::wchar_to_char(current_hid_device->product_string); diff --git a/LogManager.cpp b/LogManager.cpp index 4b1434257..eeb361b5b 100644 --- a/LogManager.cpp +++ b/LogManager.cpp @@ -16,7 +16,7 @@ #include "JsonUtils.h" #include "LogManager.h" -const char* LogManager::log_codes[] = {"FATAL:", "ERROR:", "Warning:", "Info:", "Verbose:", "Debug:", "Trace:", "Dialog:"}; +const char* LogManager::LOG_CODES[] = {"Fatal", "Error", "Warning", "Info", "Verbose", "Debug", "Trace", "Dialog"}; const char* TimestampPattern = "%04d%02d%02d_%02d%02d%02d"; @@ -25,45 +25,119 @@ const char* TimestampPattern = "%04d%02d%02d_%02d%02d%02d"; \*---------------------------------------------------------*/ const char* TimestampRegex = "[0-9]{8}_[0-9]{6}"; +/*---------------------------------------------------------*\ +| LogManager name for log entries | +\*---------------------------------------------------------*/ +const char* LOGMANAGER = "LogManager"; + +/*---------------------------------------------------------*\ +| LogManager Global Instance Pointer | +\*---------------------------------------------------------*/ +LogManager* LogManager::instance; + LogManager::LogManager() { - base_clock = std::chrono::steady_clock::now(); - log_console_enabled = false; - log_file_enabled = true; -} - -LogManager* LogManager::get() -{ - static LogManager* _instance = nullptr; - static std::mutex instance_mutex; - std::lock_guard grd(instance_mutex); - /*-----------------------------------------------------*\ - | Create a new instance if one does not exist | + | Initialize global instance pointer the when created | + | There should only ever be one instance of | + | LogManager | \*-----------------------------------------------------*/ - if(!_instance) + if(!instance) { - _instance = new LogManager(); - } - - return _instance; -} - -unsigned int LogManager::getLoglevel() -{ - if(log_console_enabled) - { - return(LL_TRACE); + instance = this; } + /*-----------------------------------------------------*\ + | If, for whatever reason, LogManager already exists, | + | delete this instance as only one should exist | + \*-----------------------------------------------------*/ else { - return(loglevel); + delete this; + return; } + + base_clock = std::chrono::steady_clock::now(); + log_console_enabled = false; + loglevel = LL_INFO; + print_source = false; + verbosity = LL_WARNING; } -void LogManager::configure(json config, const filesystem::path& defaultDir) +LogManager::~LogManager() { - std::lock_guard grd(entry_mutex); + +} + +/*---------------------------------------------------------*\ +| LogManager Global Instance Accessor | +\*---------------------------------------------------------*/ +LogManager* LogManager::get() +{ + /*-----------------------------------------------------*\ + | If LogManager does not exist yet, create it | + \*-----------------------------------------------------*/ + if(!instance) + { + instance = new LogManager(); + } + + return instance; +} + +/*---------------------------------------------------------*\ +| Callback Registration | +\*---------------------------------------------------------*/ +void LogManager::RegisterLogManagerCallback(LogManagerCallback new_callback, void * new_callback_arg) +{ + LogManagerCallbackMutex.lock(); + + for(size_t idx = 0; idx < LogManagerCallbacks.size(); idx++) + { + if(LogManagerCallbacks[idx] == new_callback && LogManagerCallbackArgs[idx] == new_callback_arg) + { + LogManagerCallbackMutex.unlock(); + + LOG_TRACE("[%s] Tried to register an already registered LogManager callback, skipping. Total callbacks registered: %d", LOGMANAGER, LogManagerCallbacks.size()); + + return; + } + } + + LogManagerCallbacks.push_back(new_callback); + LogManagerCallbackArgs.push_back(new_callback_arg); + + LogManagerCallbackMutex.unlock(); + + LOG_TRACE("[%s] Registered LogManager callback. Total callbacks registered: %d", LOGMANAGER, LogManagerCallbacks.size()); +} + +void LogManager::UnregisterLogManagerCallback(LogManagerCallback callback, void * callback_arg) +{ + LogManagerCallbackMutex.lock(); + + for(size_t idx = 0; idx < LogManagerCallbacks.size(); idx++) + { + if(LogManagerCallbacks[idx] == callback && LogManagerCallbackArgs[idx] == callback_arg) + { + LogManagerCallbacks.erase(LogManagerCallbacks.begin() + idx); + LogManagerCallbackArgs.erase(LogManagerCallbackArgs.begin() + idx); + } + } + + LogManagerCallbackMutex.unlock(); + + LOG_TRACE("[%s] Unregistered LogManager callback. Total callbacks registered: %d", LOGMANAGER, LogManagerCallbackArgs.size()); +} + +/*---------------------------------------------------------*\ +| Configuration | +\*---------------------------------------------------------*/ +void LogManager::Configure(json config, const filesystem::path& config_dir) +{ + /*-----------------------------------------------------*\ + | Lock the entry mitex while configuring | + \*-----------------------------------------------------*/ + std::lock_guard guard(entry_mutex); /*-----------------------------------------------------*\ | If the log is not open, create a new log file | @@ -79,8 +153,8 @@ void LogManager::configure(json config, const filesystem::path& defaultDir) | i.e. with the lexicographically smallest filename | | 0 or less equals no limit (default) | \*-------------------------------------------------*/ - int loglimit = JsonUtils::JsonGetInt(config, "file_count_limit"); - log_file_enabled = JsonUtils::JsonGetBool(config, "log_file"); + int loglimit = JsonUtils::JsonGetInt(config, "file_count_limit"); + bool log_file_enabled = JsonUtils::JsonGetBool(config, "log_file", true); /*-------------------------------------------------*\ | Default template for the logfile name | @@ -112,7 +186,7 @@ void LogManager::configure(json config, const filesystem::path& defaultDir) filesystem::path p = filesystem::u8path(logname); if(p.is_relative()) { - p = defaultDir / "logs" / logname; + p = config_dir / "logs" / logname; } filesystem::create_directories(p.parent_path()); @@ -157,41 +231,228 @@ void LogManager::configure(json config, const filesystem::path& defaultDir) /*-----------------------------------------------------*\ | Check log console configuration | \*-----------------------------------------------------*/ - if(config.contains("log_console")) - { - log_console_enabled = config["log_console"]; - } + log_console_enabled = JsonUtils::JsonGetBool(config, "log_console"); /*-----------------------------------------------------*\ | Flush the log | \*-----------------------------------------------------*/ - _flush(); + flush(); } -void LogManager::_flush() +/*---------------------------------------------------------*\ +| Log Buffer Functions | +\*---------------------------------------------------------*/ +void LogManager::ClearLogBuffer() { + all_messages.clear(); +} + +std::vector LogManager::GetLogBuffer() +{ + return(all_messages); +} + +/*---------------------------------------------------------*\ +| Log Level Functions | +\*---------------------------------------------------------*/ +unsigned int LogManager::GetLogLevel() +{ + return(loglevel); +} + +unsigned int LogManager::GetVerbosity() +{ + return(verbosity); +} + +void LogManager::SetLogLevel(unsigned int level) +{ + /*-----------------------------------------------------*\ + | Check that the new log level is valid, otherwise set | + | it within the valid range | + \*-----------------------------------------------------*/ + if(level > LL_TRACE) + { + level = LL_TRACE; + } + + LOG_DEBUG("[%s] LogLevel set to %d", LOGMANAGER, level); + + /*-----------------------------------------------------*\ + | Set the new log level | + \*-----------------------------------------------------*/ + loglevel = level; +} + +void LogManager::SetVerbosity(unsigned int level) +{ + /*-----------------------------------------------------*\ + | Check that the new verbosity is valid, otherwise set | + | it within the valid range | + \*-----------------------------------------------------*/ + if(level > LL_TRACE) + { + level = LL_TRACE; + } + + LOG_DEBUG("[%s] Verbosity set to %d", LOGMANAGER, level); + + /*-----------------------------------------------------*\ + | Set the new verbosity | + \*-----------------------------------------------------*/ + verbosity = level; +} + +/*---------------------------------------------------------*\ +| Log Format Functions | +\*---------------------------------------------------------*/ +void LogManager::SetPrintSource(bool print) +{ + LOG_DEBUG("[LogManager] Source code location printouts were %s", print ? "enabled" : "disabled"); + print_source = print; +} + +/*---------------------------------------------------------*\ +| Logging Functions | +\*---------------------------------------------------------*/ +void LogManager::LogEntry(const char* filename, int line, unsigned int level, const char* fmt, ...) +{ + va_list va; + va_start(va, fmt); + + LogEntry_va(filename, line, level, fmt, va); + + va_end(va); +} + +void LogManager::LogEntry_va(const char* filename, int line, unsigned int level, const char* fmt, va_list va) +{ + /*-----------------------------------------------------*\ + | Lock the entry mutex while adding an entry | + \*-----------------------------------------------------*/ + std::lock_guard guard(entry_mutex); + + /*-----------------------------------------------------*\ + | If a critical message occurs, enable source | + | printing and set loglevel and verbosity to highest | + \*-----------------------------------------------------*/ + if(level == LL_FATAL) + { + print_source = true; + loglevel = LL_DEBUG; + verbosity = LL_DEBUG; + } + + /*-----------------------------------------------------*\ + | Create a new message | + \*-----------------------------------------------------*/ + PLogMessage message = std::make_shared(); + + /*-----------------------------------------------------*\ + | Resize the buffer, then fill in the message text | + \*-----------------------------------------------------*/ + va_list va2; + va_copy(va2, va); + int len = vsnprintf(nullptr, 0, fmt, va); + message->text.resize(len); + vsnprintf(&(message->text[0]), len + 1, fmt, va2); + va_end(va2); + + /*-----------------------------------------------------*\ + | Fill in message information | + \*-----------------------------------------------------*/ + message->level = level; + message->filename = filename; + message->line = line; + message->timestamp = std::chrono::duration_cast(std::chrono::steady_clock::now() - base_clock).count(); + + /*-----------------------------------------------------*\ + | Remove newlines in the log text unless this is a | + | dialog | + \*-----------------------------------------------------*/ + if(level != LL_DIALOG) + { + message->text.erase(std::remove(message->text.begin(), message->text.end(), '\n'), message->text.end()); + message->text.erase(std::remove(message->text.begin(), message->text.end(), '\r'), message->text.end()); + } + + /*-----------------------------------------------------*\ + | If this is a dialog message, call the dialog show | + | callback | + \*-----------------------------------------------------*/ + if(level == LL_DIALOG) + { + for(size_t idx = 0; idx < LogManagerCallbacks.size(); idx++) + { + LogManagerCallbacks[idx](LogManagerCallbackArgs[idx], LOGMANAGER_UPDATE_REASON_SHOW_DIALOG, message); + } + } + else + { + for(size_t idx = 0; idx < LogManagerCallbacks.size(); idx++) + { + LogManagerCallbacks[idx](LogManagerCallbackArgs[idx], LOGMANAGER_UPDATE_REASON_LOG_ENTRY, message); + } + } + + /*-----------------------------------------------------*\ + | If the message is within the current verbosity, print | + | it on the screen | + \*-----------------------------------------------------*/ + if(level <= verbosity || level == LL_DIALOG) + { + std::cout << std::left << "[" << std::setw(10) << message->timestamp << "]"; + std::cout << std::left << "[" << std::setw(7) << LOG_CODES[message->level] << "]"; + if(print_source) + { + std::cout << " [" << message->filename << ":" << message->line << "]"; + } + std::cout << message->text; + std::cout << std::endl; + } + + /*-----------------------------------------------------*\ + | Add the message to the logfile queue | + \*-----------------------------------------------------*/ + temp_messages.push_back(message); + + if(log_console_enabled) + { + all_messages.push_back(message); + } + + /*-----------------------------------------------------*\ + | Flush the queues | + \*-----------------------------------------------------*/ + flush(); +} + +/*---------------------------------------------------------*\ +| Private Functions | +\*---------------------------------------------------------*/ +void LogManager::flush() +{ + /*-----------------------------------------------------*\ + | Lock the entry mutex while flushing | + \*-----------------------------------------------------*/ + std::lock_guard guard(entry_mutex); + /*-----------------------------------------------------*\ | If the log is open, write out buffered messages | \*-----------------------------------------------------*/ if(log_stream.is_open()) { - for(size_t msg = 0; msg < temp_messages.size(); ++msg) + for(std::size_t message_idx = 0; message_idx < temp_messages.size(); message_idx++) { - if(temp_messages[msg]->level <= loglevel || temp_messages[msg]->level == LL_DIALOG) + if(temp_messages[message_idx]->level <= loglevel || temp_messages[message_idx]->level == LL_DIALOG) { - /*-----------------------------------------*\ - | Put the timestamp here | - \*-----------------------------------------*/ - std::chrono::milliseconds counter = std::chrono::duration_cast(temp_messages[msg]->counted_second); - log_stream << std::left << std::setw(6) << counter.count() << "|"; - log_stream << std::left << std::setw(9) << log_codes[temp_messages[msg]->level]; - log_stream << temp_messages[msg]->buffer; - + log_stream << std::left << "[" << std::setw(10) << temp_messages[message_idx]->timestamp << "]"; + log_stream << std::left << "[" << std::setw(7) << LOG_CODES[temp_messages[message_idx]->level] << "]"; if(print_source) { - log_stream << " [" << temp_messages[msg]->filename << ":" << temp_messages[msg]->line << "]"; + std::cout << " [" << temp_messages[message_idx]->filename << ":" << temp_messages[message_idx]->line << "]"; } - + log_stream << temp_messages[message_idx]->text; log_stream << std::endl; } } @@ -208,176 +469,6 @@ void LogManager::_flush() } } -void LogManager::flush() -{ - std::lock_guard grd(entry_mutex); - _flush(); -} - -void LogManager::append_va(const char* filename, int line, unsigned int level, const char* fmt, va_list va) -{ - std::lock_guard grd(entry_mutex); - - /*-----------------------------------------------------*\ - | If a critical message occurs, enable source | - | printing and set loglevel and verbosity to highest | - \*-----------------------------------------------------*/ - if(level == LL_FATAL) - { - print_source = true; - loglevel = LL_DEBUG; - verbosity = LL_DEBUG; - } - - /*-----------------------------------------------------*\ - | Create a new message | - \*-----------------------------------------------------*/ - PLogMessage mes = std::make_shared(); - - /*-----------------------------------------------------*\ - | Resize the buffer, then fill in the message text | - \*-----------------------------------------------------*/ - va_list va2; - va_copy(va2, va); - int len = vsnprintf(nullptr, 0, fmt, va); - mes->buffer.resize(len); - vsnprintf(&(mes->buffer[0]), len + 1, fmt, va2); - va_end(va2); - - /*-----------------------------------------------------*\ - | Fill in message information | - \*-----------------------------------------------------*/ - mes->level = level; - mes->filename = filename; - mes->line = line; - mes->counted_second = std::chrono::steady_clock::now() - base_clock; - - /*-----------------------------------------------------*\ - | If this is a dialog message, call the dialog show | - | callback | - \*-----------------------------------------------------*/ - if(level == LL_DIALOG) - { - for(size_t idx = 0; idx < dialog_show_callbacks.size(); idx++) - { - dialog_show_callbacks[idx](dialog_show_callback_args[idx], mes); - } - } - - /*-----------------------------------------------------*\ - | If the message is within the current verbosity, print | - | it on the screen | - | TODO: Put the timestamp here | - \*-----------------------------------------------------*/ - if(level <= verbosity || level == LL_DIALOG) - { - std::cout << mes->buffer; - if(print_source) - { - std::cout << " [" << mes->filename << ":" << mes->line << "]"; - } - std::cout << std::endl; - } - - /*-----------------------------------------------------*\ - | Add the message to the logfile queue | - \*-----------------------------------------------------*/ - temp_messages.push_back(mes); - - if(log_console_enabled) - { - all_messages.push_back(mes); - } - - /*-----------------------------------------------------*\ - | Flush the queues | - \*-----------------------------------------------------*/ - _flush(); -} - -std::vector LogManager::messages() -{ - return all_messages; -} - -void LogManager::clearMessages() -{ - all_messages.clear(); -} - -void LogManager::append(const char* filename, int line, unsigned int level, const char* fmt, ...) -{ - va_list va; - va_start(va, fmt); - - append_va(filename, line, level, fmt, va); - - va_end(va); -} - -void LogManager::setLoglevel(unsigned int level) -{ - /*-----------------------------------------------------*\ - | Check that the new log level is valid, otherwise set | - | it within the valid range | - \*-----------------------------------------------------*/ - if(level > LL_TRACE) - { - level = LL_TRACE; - } - - LOG_DEBUG("[LogManager] Loglevel set to %d", level); - - /*-----------------------------------------------------*\ - | Set the new log level | - \*-----------------------------------------------------*/ - loglevel = level; -} - -void LogManager::setVerbosity(unsigned int level) -{ - /*-----------------------------------------------------*\ - | Check that the new verbosity is valid, otherwise set | - | it within the valid range | - \*-----------------------------------------------------*/ - if(level > LL_TRACE) - { - level = LL_TRACE; - } - - LOG_DEBUG("[LogManager] Verbosity set to %d", level); - - /*-----------------------------------------------------*\ - | Set the new verbosity | - \*-----------------------------------------------------*/ - verbosity = level; -} - -void LogManager::setPrintSource(bool v) -{ - LOG_DEBUG("[LogManager] Source code location printouts were %s", v ? "enabled" : "disabled"); - print_source = v; -} - -void LogManager::RegisterDialogShowCallback(LogDialogShowCallback callback, void* receiver) -{ - LOG_DEBUG("[LogManager] dialog show callback registered"); - dialog_show_callbacks.push_back(callback); - dialog_show_callback_args.push_back(receiver); -} - -void LogManager::UnregisterDialogShowCallback(LogDialogShowCallback callback, void* receiver) -{ - for(size_t idx = 0; idx < dialog_show_callbacks.size(); idx++) - { - if(dialog_show_callbacks[idx] == callback && dialog_show_callback_args[idx] == receiver) - { - dialog_show_callbacks.erase(dialog_show_callbacks.begin() + idx); - dialog_show_callback_args.erase(dialog_show_callback_args.begin() + idx); - } - } -} - void LogManager::rotate_logs(const filesystem::path& folder, const filesystem::path& templ, int max_count) { if(max_count < 1) diff --git a/LogManager.h b/LogManager.h index 1f37f08e8..b0571f07e 100644 --- a/LogManager.h +++ b/LogManager.h @@ -7,8 +7,7 @@ | SPDX-License-Identifier: GPL-2.0-or-later | \*---------------------------------------------------------*/ -#ifndef LOGMANAGER_H -#define LOGMANAGER_H +#pragma once #include #include @@ -41,77 +40,139 @@ enum LL_DIALOG // Log messages to be shown in a GUI dialog box }; -struct LogMessage +typedef struct { - std::string buffer; - unsigned int level; - const char* filename; - int line; - std::chrono::duration counted_second; - // int timestamp or float time_offset? TBD -}; + unsigned int level; + unsigned int line; + unsigned int timestamp; + std::string filename; + std::string text; +} LogMessage; + typedef std::shared_ptr PLogMessage; -typedef void(*LogDialogShowCallback)(void*, PLogMessage); + +/*---------------------------------------------------------*\ +| Callback Types | +\*---------------------------------------------------------*/ +typedef void(*LogManagerCallback)(void*, unsigned int, PLogMessage); + +/*---------------------------------------------------------*\ +| LogManager Update Reason Codes | +\*---------------------------------------------------------*/ +enum +{ + LOGMANAGER_UPDATE_REASON_LOG_ENTRY, /* Log entry */ + LOGMANAGER_UPDATE_REASON_SHOW_DIALOG, /* Show dialog */ +}; class LogManager { -private: - LogManager(); - LogManager(const LogManager&) = delete; - LogManager(LogManager&&) = delete; - ~LogManager(); - std::recursive_mutex entry_mutex; - std::mutex section_mutex; - std::ofstream log_stream; - - std::vector dialog_show_callbacks; - std::vector dialog_show_callback_args; - - // A temporary log message storage to hold them until the stream opens - std::vector temp_messages; - - // A log message storage that will be displayed in the app - std::vector all_messages; - - // A flag that marks if the message source file name and line number should be printed on screen - bool print_source = false; - - // Logfile max level - unsigned int loglevel = LL_INFO; - - // Verbosity (stdout) max level - unsigned int verbosity = LL_WARNING; - - //Clock from LogManager creation - std::chrono::time_point base_clock; - - // A non-guarded flush() - void _flush(); - - void rotate_logs(const filesystem::path& folder, const filesystem::path& templ, int max_count); - public: - static LogManager* get(); - void configure(json config, const filesystem::path & defaultDir); - void flush(); - void append(const char* filename, int line, unsigned int level, const char* fmt, ...); - void append_va(const char* filename, int line, unsigned int level, const char* fmt, va_list va); - void setLoglevel(unsigned int); - void setVerbosity(unsigned int); - void setPrintSource(bool); - void RegisterDialogShowCallback(LogDialogShowCallback callback, void* receiver); - void UnregisterDialogShowCallback(LogDialogShowCallback callback, void* receiver); - unsigned int getLoglevel(); - unsigned int getVerbosity() {return verbosity;} - void clearMessages(); - std::vector messages(); + LogManager(); + ~LogManager(); - bool log_console_enabled; - bool log_file_enabled; - static const char* log_codes[]; + /*-----------------------------------------------------*\ + | LogManager Global Instance Accessor | + \*-----------------------------------------------------*/ + static LogManager* get(); + + /*-----------------------------------------------------*\ + | Callback Registration | + \*-----------------------------------------------------*/ + void RegisterLogManagerCallback(LogManagerCallback callback, void* receiver); + void UnregisterLogManagerCallback(LogManagerCallback callback, void* receiver); + + /*-----------------------------------------------------*\ + | Configuration | + \*-----------------------------------------------------*/ + void Configure(json config, const filesystem::path& config_dir); + + /*-----------------------------------------------------*\ + | Log Buffer Functions | + \*-----------------------------------------------------*/ + void ClearLogBuffer(); + std::vector GetLogBuffer(); + + /*-----------------------------------------------------*\ + | Log Level Functions | + \*-----------------------------------------------------*/ + unsigned int GetLogLevel(); + unsigned int GetVerbosity(); + + void SetLogLevel(unsigned int); + void SetVerbosity(unsigned int); + + /*-----------------------------------------------------*\ + | Log Format Functions | + \*-----------------------------------------------------*/ + void SetPrintSource(bool print); + + /*-----------------------------------------------------*\ + | Log Entry Functions | + \*-----------------------------------------------------*/ + void LogEntry(const char* filename, int line, unsigned int level, const char* fmt, ...); + void LogEntry_va(const char* filename, int line, unsigned int level, const char* fmt, va_list va); + + /*-----------------------------------------------------*\ + | Log Code String Constants | + \*-----------------------------------------------------*/ + static const char* LOG_CODES[]; + +private: + /*-----------------------------------------------------*\ + | Static pointer to shared instance of LogManager | + \*-----------------------------------------------------*/ + static LogManager* instance; + + /*-----------------------------------------------------*\ + | Log Levels | + \*-----------------------------------------------------*/ + unsigned int loglevel; + unsigned int verbosity; + + /*-----------------------------------------------------*\ + | Log Formatting | + \*-----------------------------------------------------*/ + std::chrono::time_point + base_clock; + bool log_console_enabled; + bool print_source; + + /*-----------------------------------------------------*\ + | Log Mutexes | + \*-----------------------------------------------------*/ + std::recursive_mutex entry_mutex; + std::mutex section_mutex; + + /*-----------------------------------------------------*\ + | Log File Output Stream | + \*-----------------------------------------------------*/ + std::ofstream log_stream; + + /*-----------------------------------------------------*\ + | LogManager Callbacks | + \*-----------------------------------------------------*/ + std::vector LogManagerCallbacks; + std::vector LogManagerCallbackArgs; + std::mutex LogManagerCallbackMutex; + + /*-----------------------------------------------------*\ + | Log Buffers | + \*-----------------------------------------------------*/ + std::vector temp_messages; + std::vector all_messages; + + /*-----------------------------------------------------*\ + | Private Functions | + \*-----------------------------------------------------*/ + void flush(); + void rotate_logs(const filesystem::path& folder, const filesystem::path& templ, int max_count); }; -#define LogAppend(level, ...) LogManager::get()->append(__FILE__, __LINE__, level, __VA_ARGS__) +/*---------------------------------------------------------*\ +| Log Macros | +\*---------------------------------------------------------*/ +#define LogAppend(level, ...) LogManager::get()->LogEntry(__FILE__, __LINE__, level, __VA_ARGS__) #define LOG_FATAL(...) LogAppend(LL_FATAL, __VA_ARGS__) #define LOG_ERROR(...) LogAppend(LL_ERROR, __VA_ARGS__) #define LOG_WARNING(...) LogAppend(LL_WARNING, __VA_ARGS__) @@ -120,5 +181,3 @@ public: #define LOG_DEBUG(...) LogAppend(LL_DEBUG, __VA_ARGS__) #define LOG_TRACE(...) LogAppend(LL_TRACE, __VA_ARGS__) #define LOG_DIALOG(...) LogAppend(LL_DIALOG, __VA_ARGS__) - -#endif // LOGMANAGER_H diff --git a/OpenRGBPluginAPI.cpp b/OpenRGBPluginAPI.cpp index 469687bb5..129538937 100644 --- a/OpenRGBPluginAPI.cpp +++ b/OpenRGBPluginAPI.cpp @@ -23,12 +23,12 @@ OpenRGBPluginAPI::OpenRGBPluginAPI() /*---------------------------------------------------------*\ | LogManager APIs | \*---------------------------------------------------------*/ -void OpenRGBPluginAPI::append(const char* filename, int line, unsigned int level, const char* fmt, ...) +void OpenRGBPluginAPI::LogEntry(const char* filename, int line, unsigned int level, const char* fmt, ...) { va_list va; va_start(va, fmt); - log_manager->append_va(filename, line, level, fmt, va); + log_manager->LogEntry_va(filename, line, level, fmt, va); va_end(va); } diff --git a/OpenRGBPluginAPI.h b/OpenRGBPluginAPI.h index 66bd07bea..4ee5f704f 100644 --- a/OpenRGBPluginAPI.h +++ b/OpenRGBPluginAPI.h @@ -26,7 +26,7 @@ public: /*-----------------------------------------------------*\ | LogManager APIs | \*-----------------------------------------------------*/ - void append(const char* filename, int line, unsigned int level, const char* fmt, ...); + void LogEntry(const char* filename, int line, unsigned int level, const char* fmt, ...); /*-----------------------------------------------------*\ | PluginManager APIs | diff --git a/OpenRGBPluginInterface.h b/OpenRGBPluginInterface.h index 4a695a86d..ca2460f26 100644 --- a/OpenRGBPluginInterface.h +++ b/OpenRGBPluginInterface.h @@ -77,7 +77,7 @@ public: /*-----------------------------------------------------*\ | LogManager APIs | \*-----------------------------------------------------*/ - virtual void append(const char* filename, int line, unsigned int level, const char* fmt, ...) = 0; + virtual void LogEntry(const char* filename, int line, unsigned int level, const char* fmt, ...) = 0; /*-----------------------------------------------------*\ | PluginManager APIs | diff --git a/ResourceManager.cpp b/ResourceManager.cpp index 76345984c..a77fe4bfc 100644 --- a/ResourceManager.cpp +++ b/ResourceManager.cpp @@ -226,7 +226,7 @@ ResourceManager::ResourceManager() /*-----------------------------------------------------*\ | Configure the log manager | \*-----------------------------------------------------*/ - LogManager::get()->configure(settings_manager->GetSettings("LogManager"), GetConfigurationDirectory()); + LogManager::get()->Configure(settings_manager->GetSettings("LogManager"), GetConfigurationDirectory()); /*-----------------------------------------------------*\ | Load sizes list from file | diff --git a/cli.cpp b/cli.cpp index 98b567d5d..80e369cb6 100644 --- a/cli.cpp +++ b/cli.cpp @@ -1471,11 +1471,11 @@ unsigned int cli_pre_detection(int argc, char* argv[]) int level = std::stoi(argument); if (level >= 0 && level <= LL_TRACE) { - LogManager::get()->setLoglevel(level); + LogManager::get()->SetLogLevel(level); } else { - LOG_ERROR("[CLI] Loglevel out of range: %d (0-6)", level); + LOG_ERROR("[CLI] LogLevel out of range: %d (0-6)", level); print_help = true; break; } @@ -1484,31 +1484,31 @@ unsigned int cli_pre_detection(int argc, char* argv[]) { if(!strcasecmp(argument.c_str(), "fatal")) { - LogManager::get()->setLoglevel(LL_FATAL); + LogManager::get()->SetLogLevel(LL_FATAL); } else if(!strcasecmp(argument.c_str(), "error")) { - LogManager::get()->setLoglevel(LL_ERROR); + LogManager::get()->SetLogLevel(LL_ERROR); } else if(!strcasecmp(argument.c_str(), "warning")) { - LogManager::get()->setLoglevel(LL_WARNING); + LogManager::get()->SetLogLevel(LL_WARNING); } else if(!strcasecmp(argument.c_str(), "info")) { - LogManager::get()->setLoglevel(LL_INFO); + LogManager::get()->SetLogLevel(LL_INFO); } else if(!strcasecmp(argument.c_str(), "verbose")) { - LogManager::get()->setLoglevel(LL_VERBOSE); + LogManager::get()->SetLogLevel(LL_VERBOSE); } else if(!strcasecmp(argument.c_str(), "debug")) { - LogManager::get()->setLoglevel(LL_DEBUG); + LogManager::get()->SetLogLevel(LL_DEBUG); } else if(!strcasecmp(argument.c_str(), "trace")) { - LogManager::get()->setLoglevel(LL_TRACE); + LogManager::get()->SetLogLevel(LL_TRACE); } else { @@ -1649,7 +1649,7 @@ unsigned int cli_pre_detection(int argc, char* argv[]) \*---------------------------------------------------------*/ else if(option == "--verbose" || option == "-v") { - LogManager::get()->setVerbosity(LL_VERBOSE); + LogManager::get()->SetVerbosity(LL_VERBOSE); cfg_args++; } @@ -1658,7 +1658,7 @@ unsigned int cli_pre_detection(int argc, char* argv[]) \*---------------------------------------------------------*/ else if(option == "--very-verbose" || option == "-vv") { - LogManager::get()->setVerbosity(LL_TRACE); + LogManager::get()->SetVerbosity(LL_TRACE); cfg_args++; } @@ -1667,7 +1667,7 @@ unsigned int cli_pre_detection(int argc, char* argv[]) \*---------------------------------------------------------*/ else if(option == "--print-source") { - LogManager::get()->setPrintSource(true); + LogManager::get()->SetPrintSource(true); cfg_args++; } diff --git a/qt/OpenRGBConsolePage/OpenRGBConsolePage.cpp b/qt/OpenRGBConsolePage/OpenRGBConsolePage.cpp index 324aa6dc2..bcdc8d43f 100644 --- a/qt/OpenRGBConsolePage/OpenRGBConsolePage.cpp +++ b/qt/OpenRGBConsolePage/OpenRGBConsolePage.cpp @@ -28,7 +28,7 @@ OpenRGBConsolePage::OpenRGBConsolePage(QWidget *parent) : "Trace" }); - ui->log_level->setCurrentIndex(LogManager::get()->getLoglevel()); + ui->log_level->setCurrentIndex(LogManager::get()->GetLogLevel()); ui->log_level->blockSignals(false); #ifdef _WIN32 @@ -41,18 +41,18 @@ void OpenRGBConsolePage::Refresh() { QString log; - unsigned int current_level = LogManager::get()->getLoglevel(); + unsigned int current_level = LogManager::get()->GetLogLevel(); - for(PLogMessage& message: LogManager::get()->messages()) + for(PLogMessage& message: LogManager::get()->GetLogBuffer()) { unsigned int message_level = message.get()->level; if(message_level <= current_level || message_level == LL_DIALOG) { log += "["; - log += LogManager::log_codes[message_level]; + log += LogManager::LOG_CODES[message_level]; log += "] "; - log += QString::fromStdString(message.get()->buffer); + log += QString::fromStdString(message.get()->text); log += "\n"; } } @@ -62,12 +62,12 @@ void OpenRGBConsolePage::Refresh() void OpenRGBConsolePage::on_log_level_currentIndexChanged(int index) { - LogManager::get()->setLoglevel(index); + LogManager::get()->SetLogLevel(index); } void OpenRGBConsolePage::on_clear_clicked() { - LogManager::get()->clearMessages(); + LogManager::get()->ClearLogBuffer(); ui->logs->clear(); } diff --git a/qt/OpenRGBDialog/OpenRGBDialog.cpp b/qt/OpenRGBDialog/OpenRGBDialog.cpp index 57ffe014c..30b5d5678 100644 --- a/qt/OpenRGBDialog/OpenRGBDialog.cpp +++ b/qt/OpenRGBDialog/OpenRGBDialog.cpp @@ -45,6 +45,19 @@ #include "macutils.h" #endif +static void OpenRGBDialogLogManagerCallback(void * this_ptr, unsigned int update_reason, PLogMessage message) +{ + OpenRGBDialog * this_obj = (OpenRGBDialog *)this_ptr; + + switch(update_reason) + { + case LOGMANAGER_UPDATE_REASON_SHOW_DIALOG: + this_obj->SetDialogMessage(message); + QMetaObject::invokeMethod(this_obj, "onShowDialogMessage", Qt::QueuedConnection); + break; + } +} + static void OpenRGBDialogProfileManagerCallback(void * this_ptr, unsigned int update_reason) { OpenRGBDialog * this_obj = (OpenRGBDialog *)this_ptr; @@ -111,13 +124,6 @@ static void DeletePluginCallback(void * this_ptr, OpenRGBPluginEntry* plugin) this_obj->RemovePlugin(plugin); } -static void DialogShowCallback(void * this_ptr, PLogMessage msg) -{ - OpenRGBDialog * this_obj = (OpenRGBDialog *)this_ptr; - - this_obj->SetDialogMessage(msg); - QMetaObject::invokeMethod(this_obj, "onShowDialogMessage", Qt::QueuedConnection); -} bool OpenRGBDialog::IsMinimizeOnClose() { @@ -280,9 +286,9 @@ OpenRGBDialog::OpenRGBDialog(QWidget *parent) : QMainWindow(parent), ui(new Ui:: ResourceManager::get()->GetSettingsManager()->RegisterSettingsManagerCallback(OpenRGBDialogSettingsManagerCallback, this); /*-----------------------------------------------------*\ - | Register dialog show callback with log manager | + | Register log manager callbacks | \*-----------------------------------------------------*/ - LogManager::get()->RegisterDialogShowCallback(DialogShowCallback, this); + LogManager::get()->RegisterLogManagerCallback(OpenRGBDialogLogManagerCallback, this); /*-----------------------------------------------------*\ | Initialize page pointers | @@ -1228,7 +1234,7 @@ void OpenRGBDialog::UpdateDevicesList() void OpenRGBDialog::SetDialogMessage(PLogMessage msg) { - dialog_message = QString::fromStdString(msg->buffer); + dialog_message = QString::fromStdString(msg->text); } void OpenRGBDialog::SetLanguage(std::string locale)