light/modules/logger/logger.cppm

231 lines
5.6 KiB
Text
Raw Permalink Normal View History

export module logger;
2026-01-20 09:58:35 +03:30
import preliminary;
2025-11-16 14:29:03 +03:30
export namespace lt::log {
2025-11-16 14:29:03 +03:30
2025-07-16 13:56:59 +03:30
/** Severity of a log message. */
2026-01-20 09:58:35 +03:30
enum class Level : u8
2025-07-05 13:28:41 +03:30
{
2025-07-06 16:30:38 +03:30
/** Lowest and most vebose log level, for tracing execution paths and events */
trace = 0,
2025-07-05 13:28:41 +03:30
2025-07-06 16:30:38 +03:30
/** Vebose log level, for enabling temporarily to debug */
debug = 1,
2025-07-06 16:30:38 +03:30
/** General information */
info = 2,
2025-07-06 16:30:38 +03:30
/** Things we should to be aware of and edge cases */
warn = 3,
2025-07-06 16:30:38 +03:30
/** Defects, bugs and undesired behaviour */
error = 4,
2025-07-06 16:30:38 +03:30
/** Unrecoverable errors */
critical = 5,
2025-07-06 16:30:38 +03:30
/**
* Logs from the testing-framework.
* Highest so we still get them while turning off all logs from the code under test.
*
* @note: log::test does NOT include source_location
*/
test = 6,
2025-07-06 16:30:38 +03:30
/** No logging */
off = 7,
2025-07-06 16:30:38 +03:30
};
auto min_severity = Level::trace;
auto set_min_severity(Level severity)
{
min_severity = severity;
}
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
2025-07-05 13:28:41 +03:30
{
if (std::to_underlying(level) < std::to_underlying(min_severity))
{
return;
}
2026-01-09 21:53:37 +03:30
constexpr auto to_string = [](Level level) {
// clang-format off
switch (level)
{
using enum ::lt::log::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(
"{} {} ==> {}",
2026-01-09 21:53:37 +03:30
to_string(level),
std::format("{}:{}", path.filename().string(), location.line()),
std::format(format, std::forward<Args>(arguments)...)
);
2025-07-05 13:28:41 +03:30
}
[[maybe_unused]] print(
Level level,
std::format_string<Args...> format,
Args &&...arguments
) noexcept
{
constexpr auto to_string = [](Level level) {
// clang-format off
switch (level)
{
using enum ::lt::log::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 test : return "\033[1;33m| test |\033[0m";
case off : return "";
}
// clang-format on
std::unreachable();
};
std::println(
"{} {}",
to_string(level),
std::format(format, std::forward<Args>(arguments)...)
);
}
};
template<typename... Args>
print(Level, const std::source_location &, std::format_string<Args...>, Args &&...) noexcept
-> print<Args...>;
2025-07-05 13:28:41 +03:30
template<typename... Args>
struct [[maybe_unused]] trace
{
[[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>
trace(std::format_string<Args...>, Args &&...) noexcept -> trace<Args...>;
template<typename... Args>
struct [[maybe_unused]] debug
{
[[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)...);
}
2025-07-05 13:28:41 +03:30
};
template<typename... Args>
debug(std::format_string<Args...>, Args &&...) noexcept -> debug<Args...>;
2025-07-05 13:28:41 +03:30
template<typename... Args>
struct [[maybe_unused]] info
2025-07-06 16:30:38 +03:30
{
[[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)...);
}
};
2025-07-06 16:30:38 +03:30
template<typename... Args>
info(std::format_string<Args...>, Args &&...) noexcept -> info<Args...>;
2025-07-06 16:30:38 +03:30
template<typename... Args>
struct [[maybe_unused]] warn
2025-07-06 16:30:38 +03:30
{
[[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...>;
2025-07-06 16:30:38 +03:30
template<typename... Args>
struct [[maybe_unused]] error
2025-07-06 16:30:38 +03:30
{
[[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...>;
2025-07-06 16:30:38 +03:30
template<typename... Args>
struct [[maybe_unused]] critical
2025-07-06 16:30:38 +03:30
{
[[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...>;
template<typename... Args>
void test(std::format_string<Args...> format, Args &&...arguments) noexcept
{
print(Level::test, format, std::forward<Args>(arguments)...);
}
} // namespace lt::log