From 6a257566bd50b02e6b8d975d6105637673e35f61 Mon Sep 17 00:00:00 2001 From: light7734 Date: Sat, 1 Nov 2025 02:36:05 +0330 Subject: [PATCH] refactor(logger): colors & source location! --- modules/logger/CMakeLists.txt | 3 +- modules/logger/private/logger.cpp | 1 - modules/logger/private/logger.test.cpp | 25 ++++ modules/logger/public/logger.hpp | 180 +++++++++++++++++++------ 4 files changed, 165 insertions(+), 44 deletions(-) delete mode 100644 modules/logger/private/logger.cpp create mode 100644 modules/logger/private/logger.test.cpp diff --git a/modules/logger/CMakeLists.txt b/modules/logger/CMakeLists.txt index 73c7eaa..5ef9b1e 100644 --- a/modules/logger/CMakeLists.txt +++ b/modules/logger/CMakeLists.txt @@ -1 +1,2 @@ -add_library_module(logger logger.cpp) +add_library_module(logger) +add_test_module(logger logger.test.cpp) diff --git a/modules/logger/private/logger.cpp b/modules/logger/private/logger.cpp deleted file mode 100644 index 8910b00..0000000 --- a/modules/logger/private/logger.cpp +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/modules/logger/private/logger.test.cpp b/modules/logger/private/logger.test.cpp new file mode 100644 index 0000000..3fda6aa --- /dev/null +++ b/modules/logger/private/logger.test.cpp @@ -0,0 +1,25 @@ +#include +#include + +using ::lt::test::Case; +using ::lt::test::Suite; + +Suite suite = [] { + Case { "no format" } = [] { + lt::log::trace("trace"); + lt::log::debug("debug"); + lt::log::info("info"); + lt::log::warn("warn"); + lt::log::error("error"); + lt::log::critical("critical"); + }; + + Case { "formatted" } = [] { + lt::log::trace("trace {}", 69); + lt::log::debug("debug {}", 69); + lt::log::info("info {}", 69); + lt::log::warn("warn {}", 69); + lt::log::error("error {}", 69); + lt::log::critical("critical {}", 69); + }; +}; diff --git a/modules/logger/public/logger.hpp b/modules/logger/public/logger.hpp index 8625f19..223334b 100644 --- a/modules/logger/public/logger.hpp +++ b/modules/logger/public/logger.hpp @@ -1,10 +1,17 @@ #pragma once -#include -#include +#include +#include +#include +#include +#include +#include +#include + +namespace lt::log { /** Severity of a log message. */ -enum class LogLvl : uint8_t +enum class Level : uint8_t { /** Lowest and most vebose log level, for tracing execution paths and events */ trace = 0, @@ -28,62 +35,151 @@ enum class LogLvl : uint8_t off = 6, }; -/** Simple console logger */ -class Logger +namespace details { + +inline auto thread_hash_id() noexcept -> std::uint64_t { -public: - void static show_imgui_window(); + return static_cast(std::hash {}(std::this_thread::get_id())); +} - template - void static log(LogLvl lvl, std::format_string fmt, Args &&...args) noexcept +} // namespace details + +template +struct [[maybe_unused]] print +{ + [[maybe_unused]] print( + Level level, + const std::source_location &location, + std::format_string format, + Args &&...arguments + ) noexcept { - std::ignore = lvl; - std::println(fmt, std::forward(args)...); + constexpr auto to_string = [](Level level, auto location) { + // clang-format off + switch (level) + { + using enum Level; + case trace : return "\033[1;37m| trc |\033[0m"; + case debug : return "\033[1;36m| dbg |\033[0m"; + case info : return "\033[1;32m| inf |\033[0m"; + case warn : return "\033[1;33m| wrn |\033[0m"; + case error : return "\033[1;31m| err |\033[0m"; + case critical: return "\033[1;41m| crt |\033[0m"; + case off: return "off"; + } + // clang-format on + + std::unreachable(); + }; + + const auto path = std::filesystem::path { location.file_name() }; + + std::println( + "{} {} ==> {}", + to_string(level, location), + std::format("{}:{}", path.filename().c_str(), location.line()), + std::format(format, std::forward(arguments)...) + ); } - - void static log(LogLvl lvl, const char *message) noexcept - { - std::ignore = lvl; - std::println("{}", message); - } - - -private: - Logger() = default; }; template -void log_trc(std::format_string fmt, Args &&...args) noexcept -{ - Logger::log(LogLvl::trace, fmt, std::forward(args)...); -} +print(Level level, std::format_string, Args &&...) noexcept -> print; template -void log_dbg(std::format_string fmt, Args &&...args) noexcept +struct [[maybe_unused]] trace { - Logger::log(LogLvl::debug, fmt, std::forward(args)...); -} + [[maybe_unused]] trace( + std::format_string format, + Args &&...arguments, + const std::source_location &location = std::source_location::current() + ) noexcept + { + print(Level::trace, location, format, std::forward(arguments)...); + } +}; template -void log_inf(std::format_string fmt, Args &&...args) noexcept -{ - Logger::log(LogLvl::info, fmt, std::forward(args)...); -} +trace(std::format_string, Args &&...) noexcept -> trace; template -void log_wrn(std::format_string fmt, Args &&...args) noexcept +struct [[maybe_unused]] debug { - Logger::log(LogLvl::warn, fmt, std::forward(args)...); -} + [[maybe_unused]] debug( + std::format_string format, + Args &&...arguments, + const std::source_location &location = std::source_location::current() + ) noexcept + { + print(Level::debug, location, format, std::forward(arguments)...); + } +}; template -void log_err(std::format_string fmt, Args &&...args) noexcept -{ - Logger::log(LogLvl::error, fmt, std::forward(args)...); -} +debug(std::format_string, Args &&...) noexcept -> debug; template -void log_crt(std::format_string fmt, Args &&...args) noexcept +struct [[maybe_unused]] info { - Logger::log(LogLvl::critical, fmt, std::forward(args)...); -} + [[maybe_unused]] info( + std::format_string format, + Args &&...arguments, + const std::source_location &location = std::source_location::current() + ) noexcept + { + print(Level::info, location, format, std::forward(arguments)...); + } +}; + +template +info(std::format_string, Args &&...) noexcept -> info; + +template +struct [[maybe_unused]] warn +{ + [[maybe_unused]] warn( + std::format_string format, + Args &&...arguments, + const std::source_location &location = std::source_location::current() + ) noexcept + { + print(Level::warn, location, format, std::forward(arguments)...); + } +}; + +template +warn(std::format_string, Args &&...) noexcept -> warn; + +template +struct [[maybe_unused]] error +{ + [[maybe_unused]] error( + std::format_string format, + Args &&...arguments, + const std::source_location &location = std::source_location::current() + ) noexcept + { + print(Level::error, location, format, std::forward(arguments)...); + } +}; + +template +error(std::format_string, Args &&...) noexcept -> error; + +template +struct [[maybe_unused]] critical +{ + [[maybe_unused]] critical( + std::format_string format, + Args &&...arguments, + const std::source_location &location = std::source_location::current() + ) noexcept + { + print(Level::critical, location, format, std::forward(arguments)...); + } +}; + +template +critical(std::format_string, Args &&...) noexcept -> critical; + +} // namespace lt::log