From 7af47ed286f08589de0e779da0f60a5e0ab2b915 Mon Sep 17 00:00:00 2001 From: rvan-mee Date: Tue, 23 Sep 2025 19:48:03 +0200 Subject: [PATCH 1/7] Fix(cmake) Compile flags actually work now --- taskmasterd/CMakeLists.txt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/taskmasterd/CMakeLists.txt b/taskmasterd/CMakeLists.txt index 36f3767..0d5d31f 100644 --- a/taskmasterd/CMakeLists.txt +++ b/taskmasterd/CMakeLists.txt @@ -11,14 +11,20 @@ add_executable(${EXECUTABLE_NAME}) file(GLOB_RECURSE SOURCES "src/*.cpp") # Add compile options -set(COMPILE_OPTIONS -Wall -Wextra -Werror -pedantic -O3 -march=native) -add_compile_options(${COMPILE_OPTIONS}) +set(COMPILE_OPTIONS -Wall -Wextra -Werror -pedantic -O3 -march=native -g) +target_compile_options(${EXECUTABLE_NAME} PRIVATE ${COMPILE_OPTIONS}) + +# Enable fsanitize: +# target_link_options(${EXECUTABLE_NAME} PRIVATE -fsanitize=address) + +message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") + # Link to the needed libs target_link_libraries(${EXECUTABLE_NAME} PRIVATE logger) # add executable sources -target_sources(${EXECUTABLE_NAME} PRIVATE ${SOURCES} main.cpp) +target_sources(${EXECUTABLE_NAME} PRIVATE ${SOURCES}) # include header directory target_include_directories(${EXECUTABLE_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/..) From b1334d9124d41322c9006e7b1d8be4eaaf4db350 Mon Sep 17 00:00:00 2001 From: rvan-mee Date: Tue, 23 Sep 2025 19:49:36 +0200 Subject: [PATCH 2/7] Feat(logger) Adds a basic singleton logger class, accessed through the LOG_* macros. Needs to be tested still. --- libs/logger/include/Logger.hpp | 116 ++++++++++++++++++++++++++++++++- libs/logger/src/Logger.cpp | 106 +++++++++++++++++++++++++++++- taskmasterd/src/main.cpp | 2 + 3 files changed, 219 insertions(+), 5 deletions(-) diff --git a/libs/logger/include/Logger.hpp b/libs/logger/include/Logger.hpp index 064d3a1..d24acfb 100644 --- a/libs/logger/include/Logger.hpp +++ b/libs/logger/include/Logger.hpp @@ -1,12 +1,122 @@ #pragma once +#include +#include +#include +#include #include +#include + +#define COLOR_RESET "\033[0m" +#define COLOR_FATAL "\033[38;5;226m" +#define COLOR_ERROR "\033[38;5;160m" +#define COLOR_WARNING "\033[38;5;208m" +#define COLOR_INFO "\033[38;5;13m" +#define COLOR_DEBUG "\033[38;5;21m" +#define COLOR_GRAY "\033[38;5;232m" namespace Logger { -void Log(const std::string& message); +/** + * @brief Enum describing the severity of the log. + */ +enum class LogType +{ + Fatal, + Error, + Warning, + Info, + Debug, +}; + +/** + * @brief Enum describing how much to log. + * + * @note Debug: Logs all log types. + * Normal: Logs everything except debug. + * Sparse: Only logs Error, Fatal and warnings. + * None: self explanatory. + */ +enum class LogLevel +{ + None, + Sparse, + Normal, + Debug, +}; + +/** + * @brief Singleton logger for a unified output. + * + * @note Debug output will be logged onto the stdout, other logs will be sent to the syslog. + */ +class LogInterface +{ + const bool _enableLoggingStdout; + LogLevel _logLevel; + + /** + * @brief Hidden default constructor. + */ + LogInterface(const char* processName, LogLevel logLevel, bool enableLoggingStdout); + + /** + * @brief Deleted constructor and operator. + */ + LogInterface(const LogInterface&) = delete; + std::unique_ptr& operator=(const LogInterface&) = delete; + + /** + * @brief Returns true or false based on the given log leven and how the Interface is + * initialzed. + */ + bool CanLogLogWithSetLogLevel(LogType logType); + + /** + * @brief Returns a string literal containing the color meant for the given LogType. + */ + constexpr const char* GetLogColor(LogType LogType); + +public: + /** + * @brief Destructor. + */ + ~LogInterface(); + + /** + * @return The singleton instance. + */ + static std::unique_ptr& GetInstance(); + + /** + * @brief Initializes the instance, logging without initializing is not possible. + * + * @param processName The name of the process. + * + * @param logLevel The level at which output will be shown, + * see the LogLevel enum for more details. + * + * @param enableLoggingStdout When enabled, will log the non-debug messages to the + * stdout as well as the syslog. + */ + static void Initialize(const char* processName, LogLevel logLevel, bool enableLoggingStdout); + + /** + * @brief Function used for logging a message in the format for the LogType. + */ + void Log(const char* logMessage, const LogType logType); +}; -} +} /* namespace Logger */ -#define LOG_DEBUG(logMessage) Logger::Log(logMessage); +#define LOG_ERROR(logMessage) \ + Logger::LogInterface::GetInstance()->Log(logMessage, Logger::LogType::Error); +#define LOG_FATAL(logMessage) \ + Logger::LogInterface::GetInstance()->Log(logMessage, Logger::LogType::Fatal); +#define LOG_WARNING(logMessage) \ + Logger::LogInterface::GetInstance()->Log(logMessage, Logger::LogType::Warning); +#define LOG_INFO(logMessage) \ + Logger::LogInterface::GetInstance()->Log(logMessage, Logger::LogType::Info); +#define LOG_DEBUG(logMessage) \ + Logger::LogInterface::GetInstance()->Log(logMessage, Logger::LogType::Debug); diff --git a/libs/logger/src/Logger.cpp b/libs/logger/src/Logger.cpp index 345abc7..6986713 100644 --- a/libs/logger/src/Logger.cpp +++ b/libs/logger/src/Logger.cpp @@ -1,10 +1,112 @@ #include #include +#include namespace Logger { -void Log(const std::string& message) +LogInterface::LogInterface(const char* processName, LogLevel logLevel, bool enableLoggingStdout) + : _logLevel(logLevel), _enableLoggingStdout(enableLoggingStdout) { - std::cout << message << std::endl; + openlog(processName, LOG_NOWAIT, LOG_NOWAIT); } + +LogInterface::~LogInterface() +{ + try { + closelog(); + } catch (const std::exception& e) { + std::cerr << e.what() << '\n'; + } +} + +std::unique_ptr& LogInterface::GetInstance() +{ + static std::unique_ptr logger; + return logger; +} + +void LogInterface::Initialize(const char* processName, LogLevel logLevel, bool enableLoggingStdout) +{ + auto& logger = GetInstance(); + + if (logger != nullptr) { + throw std::runtime_error("Logger is already initialized."); + } + + logger = + std::unique_ptr(new LogInterface(processName, logLevel, enableLoggingStdout)); +} + +bool LogInterface::CanLogLogWithSetLogLevel(LogType logType) +{ + switch (_logLevel) { + case LogLevel::None: + return false; + case LogLevel::Sparse: + return (logType != LogType::Debug && logType != LogType::Info); + case LogLevel::Normal: + return (logType != LogType::Debug); + case LogLevel::Debug: + return true; + default: + return false; + } +} + +constexpr const char* LogInterface::GetLogColor(LogType LogType) +{ + switch (LogType) { + case LogType::Fatal: + return COLOR_FATAL; + case LogType::Error: + return COLOR_ERROR; + case LogType::Warning: + return COLOR_WARNING; + case LogType::Info: + return COLOR_INFO; + case LogType::Debug: + return COLOR_DEBUG; + default: + return ""; + } +} + +void LogInterface::Log(const char* logMessage, const LogType logType) +{ + if (!CanLogLogWithSetLogLevel(logType)) { + return; + } + + if (_enableLoggingStdout || logType == LogType::Debug) { + std::cout << GetLogColor(logType) << logMessage << COLOR_RESET << "\n"; + } + + if (logType != LogType::Debug) { + try { + switch (logType) { + case LogType::Fatal: + syslog(LOG_DAEMON | LOG_ERR, "%s", logMessage); + break; + case LogType::Error: + syslog(LOG_DAEMON | LOG_ERR, "%s", logMessage); + break; + case LogType::Warning: + syslog(LOG_DAEMON | LOG_WARNING, "%s", logMessage); + break; + case LogType::Info: + syslog(LOG_DAEMON | LOG_INFO, "%s", logMessage); + break; + case LogType::Debug: + syslog(LOG_DAEMON | LOG_DEBUG, "%s", logMessage); + break; + default: + break; + } + } catch (const std::exception& e) { + std::cerr << GetLogColor(LogType::Fatal) << "Error using syslog: " << e.what() + << COLOR_RESET "\n"; + } + } +} + } // namespace Logger diff --git a/taskmasterd/src/main.cpp b/taskmasterd/src/main.cpp index 7e3b6ad..b69d30e 100644 --- a/taskmasterd/src/main.cpp +++ b/taskmasterd/src/main.cpp @@ -3,6 +3,8 @@ int main(int argc, char** argv) { + Logger::LogInterface::Initialize(argv[0], Logger::LogLevel::Debug, true); + testFunc(); if (argc > 2) { From bca0e5586d22f11c2dbc18638934646fa5c91d4e Mon Sep 17 00:00:00 2001 From: rvan-mee Date: Thu, 25 Sep 2025 19:39:47 +0200 Subject: [PATCH 3/7] Fix(colors) Swaps the colors used for warning and fatal logging --- libs/logger/include/Logger.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/logger/include/Logger.hpp b/libs/logger/include/Logger.hpp index d24acfb..1b45bea 100644 --- a/libs/logger/include/Logger.hpp +++ b/libs/logger/include/Logger.hpp @@ -8,9 +8,9 @@ #include #define COLOR_RESET "\033[0m" -#define COLOR_FATAL "\033[38;5;226m" +#define COLOR_FATAL "\033[38;5;208m" #define COLOR_ERROR "\033[38;5;160m" -#define COLOR_WARNING "\033[38;5;208m" +#define COLOR_WARNING "\033[38;5;226m" #define COLOR_INFO "\033[38;5;13m" #define COLOR_DEBUG "\033[38;5;21m" #define COLOR_GRAY "\033[38;5;232m" From 54fee9dce0fe70cfaa31aa0b8eb9d99f24a8ed84 Mon Sep 17 00:00:00 2001 From: rvan-mee Date: Thu, 25 Sep 2025 19:40:26 +0200 Subject: [PATCH 4/7] Fix(Debug log) Allows a debug log to be logged to the syslog --- libs/logger/src/Logger.cpp | 46 ++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/libs/logger/src/Logger.cpp b/libs/logger/src/Logger.cpp index 6986713..be190ad 100644 --- a/libs/logger/src/Logger.cpp +++ b/libs/logger/src/Logger.cpp @@ -81,31 +81,29 @@ void LogInterface::Log(const char* logMessage, const LogType logType) std::cout << GetLogColor(logType) << logMessage << COLOR_RESET << "\n"; } - if (logType != LogType::Debug) { - try { - switch (logType) { - case LogType::Fatal: - syslog(LOG_DAEMON | LOG_ERR, "%s", logMessage); - break; - case LogType::Error: - syslog(LOG_DAEMON | LOG_ERR, "%s", logMessage); - break; - case LogType::Warning: - syslog(LOG_DAEMON | LOG_WARNING, "%s", logMessage); - break; - case LogType::Info: - syslog(LOG_DAEMON | LOG_INFO, "%s", logMessage); - break; - case LogType::Debug: - syslog(LOG_DAEMON | LOG_DEBUG, "%s", logMessage); - break; - default: - break; - } - } catch (const std::exception& e) { - std::cerr << GetLogColor(LogType::Fatal) << "Error using syslog: " << e.what() - << COLOR_RESET "\n"; + try { + switch (logType) { + case LogType::Fatal: + syslog(LOG_DAEMON | LOG_ERR, "%s", logMessage); + break; + case LogType::Error: + syslog(LOG_DAEMON | LOG_ERR, "%s", logMessage); + break; + case LogType::Warning: + syslog(LOG_DAEMON | LOG_WARNING, "%s", logMessage); + break; + case LogType::Info: + syslog(LOG_DAEMON | LOG_INFO, "%s", logMessage); + break; + case LogType::Debug: + syslog(LOG_DAEMON | LOG_DEBUG, "%s", logMessage); + break; + default: + break; } + } catch (const std::exception& e) { + std::cerr << GetLogColor(LogType::Error) << "Error using syslog: " << e.what() + << COLOR_RESET "\n"; } } From 881ba1268e9773fc974b5f0f381c9c1fadf83cb8 Mon Sep 17 00:00:00 2001 From: rvan-mee Date: Thu, 25 Sep 2025 19:41:10 +0200 Subject: [PATCH 5/7] Cleanup(cmake) Removes the print for the c-flags --- taskmasterd/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/taskmasterd/CMakeLists.txt b/taskmasterd/CMakeLists.txt index 0d5d31f..5c52755 100644 --- a/taskmasterd/CMakeLists.txt +++ b/taskmasterd/CMakeLists.txt @@ -17,9 +17,6 @@ target_compile_options(${EXECUTABLE_NAME} PRIVATE ${COMPILE_OPTIONS}) # Enable fsanitize: # target_link_options(${EXECUTABLE_NAME} PRIVATE -fsanitize=address) -message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") - - # Link to the needed libs target_link_libraries(${EXECUTABLE_NAME} PRIVATE logger) From b43e9aaeccd57b04ac78fa4f43b2607acce5f304 Mon Sep 17 00:00:00 2001 From: rvan-mee Date: Thu, 25 Sep 2025 19:55:26 +0200 Subject: [PATCH 6/7] Chore(main) Adds all different log levels for testing --- taskmasterd/src/main.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/taskmasterd/src/main.cpp b/taskmasterd/src/main.cpp index b69d30e..adb29e0 100644 --- a/taskmasterd/src/main.cpp +++ b/taskmasterd/src/main.cpp @@ -3,15 +3,14 @@ int main(int argc, char** argv) { + (void) argc; Logger::LogInterface::Initialize(argv[0], Logger::LogLevel::Debug, true); - testFunc(); + LOG_DEBUG("Debug log") + LOG_ERROR("Error log") + LOG_FATAL("Fatal log") + LOG_WARNING("Warning log") + LOG_INFO("Info log") - if (argc > 2) { - LOG_DEBUG("argc > 2") - return 1; - } - - LOG_DEBUG("argc <= 2") return 0; } From 1dea6968708439c49e44dfd7c801245e1b0c46d5 Mon Sep 17 00:00:00 2001 From: rvan-mee Date: Tue, 7 Oct 2025 17:33:14 +0200 Subject: [PATCH 7/7] chore(program name) Allow the setting of the program name that is printed inside the log message through the use of the PROGRAM_NAME define. Default value is taskmasterd --- taskmasterd/CMakeLists.txt | 2 +- taskmasterd/src/main.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/taskmasterd/CMakeLists.txt b/taskmasterd/CMakeLists.txt index 5c52755..911f6f4 100644 --- a/taskmasterd/CMakeLists.txt +++ b/taskmasterd/CMakeLists.txt @@ -11,7 +11,7 @@ add_executable(${EXECUTABLE_NAME}) file(GLOB_RECURSE SOURCES "src/*.cpp") # Add compile options -set(COMPILE_OPTIONS -Wall -Wextra -Werror -pedantic -O3 -march=native -g) +set(COMPILE_OPTIONS -Wall -Wextra -Werror -pedantic -O3 -march=native -g -DPROGRAM_NAME="${EXECUTABLE_NAME}") target_compile_options(${EXECUTABLE_NAME} PRIVATE ${COMPILE_OPTIONS}) # Enable fsanitize: diff --git a/taskmasterd/src/main.cpp b/taskmasterd/src/main.cpp index adb29e0..16029ce 100644 --- a/taskmasterd/src/main.cpp +++ b/taskmasterd/src/main.cpp @@ -1,10 +1,16 @@ #include #include +#include + +#ifndef PROGRAM_NAME +#define PROGRAM_NAME "taskmasterd" +#endif int main(int argc, char** argv) { (void) argc; - Logger::LogInterface::Initialize(argv[0], Logger::LogLevel::Debug, true); + (void) argv; + Logger::LogInterface::Initialize(PROGRAM_NAME, Logger::LogLevel::Debug, true); LOG_DEBUG("Debug log") LOG_ERROR("Error log")