refactor(logger): colors & source location!
This commit is contained in:
parent
4534ed11d2
commit
6a257566bd
4 changed files with 165 additions and 44 deletions
|
|
@ -1 +1,2 @@
|
||||||
add_library_module(logger logger.cpp)
|
add_library_module(logger)
|
||||||
|
add_test_module(logger logger.test.cpp)
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#include <logger/logger.hpp>
|
|
||||||
25
modules/logger/private/logger.test.cpp
Normal file
25
modules/logger/private/logger.test.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include <logger/logger.hpp>
|
||||||
|
#include <test/test.hpp>
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -1,10 +1,17 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <format>
|
#include <cstdint>
|
||||||
#include <print>
|
#include <fmt/chrono.h>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <source_location>
|
||||||
|
#include <string_view>
|
||||||
|
#include <thread>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace lt::log {
|
||||||
|
|
||||||
/** Severity of a log message. */
|
/** 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 */
|
/** Lowest and most vebose log level, for tracing execution paths and events */
|
||||||
trace = 0,
|
trace = 0,
|
||||||
|
|
@ -28,62 +35,151 @@ enum class LogLvl : uint8_t
|
||||||
off = 6,
|
off = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Simple console logger */
|
namespace details {
|
||||||
class Logger
|
|
||||||
|
inline auto thread_hash_id() noexcept -> std::uint64_t
|
||||||
{
|
{
|
||||||
public:
|
return static_cast<std::uint64_t>(std::hash<std::thread::id> {}(std::this_thread::get_id()));
|
||||||
void static show_imgui_window();
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
} // namespace details
|
||||||
void static log(LogLvl lvl, std::format_string<Args...> fmt, Args &&...args) noexcept
|
|
||||||
|
template<typename... Args>
|
||||||
|
struct [[maybe_unused]] print
|
||||||
|
{
|
||||||
|
[[maybe_unused]] print(
|
||||||
|
Level level,
|
||||||
|
const std::source_location &location,
|
||||||
|
std::format_string<Args...> format,
|
||||||
|
Args &&...arguments
|
||||||
|
) noexcept
|
||||||
{
|
{
|
||||||
std::ignore = lvl;
|
constexpr auto to_string = [](Level level, auto location) {
|
||||||
std::println(fmt, std::forward<Args>(args)...);
|
// clang-format off
|
||||||
}
|
switch (level)
|
||||||
|
|
||||||
void static log(LogLvl lvl, const char *message) noexcept
|
|
||||||
{
|
{
|
||||||
std::ignore = lvl;
|
using enum Level;
|
||||||
std::println("{}", message);
|
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();
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
const auto path = std::filesystem::path { location.file_name() };
|
||||||
Logger() = default;
|
|
||||||
|
std::println(
|
||||||
|
"{} {} ==> {}",
|
||||||
|
to_string(level, location),
|
||||||
|
std::format("{}:{}", path.filename().c_str(), location.line()),
|
||||||
|
std::format(format, std::forward<Args &&>(arguments)...)
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void log_trc(std::format_string<Args...> fmt, Args &&...args) noexcept
|
print(Level level, std::format_string<Args...>, Args &&...) noexcept -> print<Args...>;
|
||||||
{
|
|
||||||
Logger::log(LogLvl::trace, fmt, std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void log_dbg(std::format_string<Args...> fmt, Args &&...args) noexcept
|
struct [[maybe_unused]] trace
|
||||||
{
|
{
|
||||||
Logger::log(LogLvl::debug, fmt, std::forward<Args>(args)...);
|
[[maybe_unused]] trace(
|
||||||
}
|
std::format_string<Args...> format,
|
||||||
|
Args &&...arguments,
|
||||||
|
const std::source_location &location = std::source_location::current()
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
print(Level::trace, location, format, std::forward<Args &&>(arguments)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void log_inf(std::format_string<Args...> fmt, Args &&...args) noexcept
|
trace(std::format_string<Args...>, Args &&...) noexcept -> trace<Args...>;
|
||||||
{
|
|
||||||
Logger::log(LogLvl::info, fmt, std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void log_wrn(std::format_string<Args...> fmt, Args &&...args) noexcept
|
struct [[maybe_unused]] debug
|
||||||
{
|
{
|
||||||
Logger::log(LogLvl::warn, fmt, std::forward<Args>(args)...);
|
[[maybe_unused]] debug(
|
||||||
}
|
std::format_string<Args...> format,
|
||||||
|
Args &&...arguments,
|
||||||
|
const std::source_location &location = std::source_location::current()
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
print(Level::debug, location, format, std::forward<Args &&>(arguments)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void log_err(std::format_string<Args...> fmt, Args &&...args) noexcept
|
debug(std::format_string<Args...>, Args &&...) noexcept -> debug<Args...>;
|
||||||
{
|
|
||||||
Logger::log(LogLvl::error, fmt, std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void log_crt(std::format_string<Args...> fmt, Args &&...args) noexcept
|
struct [[maybe_unused]] info
|
||||||
{
|
{
|
||||||
Logger::log(LogLvl::critical, fmt, std::forward<Args>(args)...);
|
[[maybe_unused]] info(
|
||||||
}
|
std::format_string<Args...> format,
|
||||||
|
Args &&...arguments,
|
||||||
|
const std::source_location &location = std::source_location::current()
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
print(Level::info, location, format, std::forward<Args &&>(arguments)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
info(std::format_string<Args...>, Args &&...) noexcept -> info<Args...>;
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
struct [[maybe_unused]] warn
|
||||||
|
{
|
||||||
|
[[maybe_unused]] warn(
|
||||||
|
std::format_string<Args...> format,
|
||||||
|
Args &&...arguments,
|
||||||
|
const std::source_location &location = std::source_location::current()
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
print(Level::warn, location, format, std::forward<Args &&>(arguments)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
warn(std::format_string<Args...>, Args &&...) noexcept -> warn<Args...>;
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
struct [[maybe_unused]] error
|
||||||
|
{
|
||||||
|
[[maybe_unused]] error(
|
||||||
|
std::format_string<Args...> format,
|
||||||
|
Args &&...arguments,
|
||||||
|
const std::source_location &location = std::source_location::current()
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
print(Level::error, location, format, std::forward<Args &&>(arguments)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
error(std::format_string<Args...>, Args &&...) noexcept -> error<Args...>;
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
struct [[maybe_unused]] critical
|
||||||
|
{
|
||||||
|
[[maybe_unused]] critical(
|
||||||
|
std::format_string<Args...> format,
|
||||||
|
Args &&...arguments,
|
||||||
|
const std::source_location &location = std::source_location::current()
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
print(Level::critical, location, format, std::forward<Args &&>(arguments)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
critical(std::format_string<Args...>, Args &&...) noexcept -> critical<Args...>;
|
||||||
|
|
||||||
|
} // namespace lt::log
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue