project-aster/aster/include/aster/util/logger.h

211 lines
12 KiB
C++

// =============================================
// Aster: logger.h
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#pragma once
#include "aster/core/constants.h"
#include <debugbreak.h>
#include <fmt/core.h>
struct Logger
{
enum class LogType : u32
{
eError,
eWarning,
eInfo,
eDebug,
eVerbose,
};
u32 m_MinimumLoggingLevel{static_cast<u32>(LogType::eDebug)};
void
SetMinimumLoggingLevel(LogType logType)
{
m_MinimumLoggingLevel = static_cast<u32>(logType);
}
template <LogType TLogLevel>
constexpr static char const *
ToCstr()
{
if constexpr (TLogLevel == LogType::eError)
return "[ERROR]:";
if constexpr (TLogLevel == LogType::eWarning)
return "[WARN]: ";
if constexpr (TLogLevel == LogType::eInfo)
return "[INFO]: ";
if constexpr (TLogLevel == LogType::eDebug)
return "[DEBUG]:";
if constexpr (TLogLevel == LogType::eVerbose)
return "[VERB]: ";
}
template <LogType TLogLevel>
constexpr static char const *
ToColorCstr()
{
if constexpr (TLogLevel == LogType::eError)
return ansi_color::Red;
if constexpr (TLogLevel == LogType::eWarning)
return ansi_color::Yellow;
if constexpr (TLogLevel == LogType::eInfo)
return ansi_color::Green;
if constexpr (TLogLevel == LogType::eDebug)
return ansi_color::White;
if constexpr (TLogLevel == LogType::eVerbose)
return ansi_color::Blue;
}
template <LogType TLogLevel>
void
Log(std::string_view const &message, char const *loc, u32 line) const
{
if (static_cast<u32>(TLogLevel) <= m_MinimumLoggingLevel)
{
fmt::println("{}{} {} {} at {}:{}{}", ToColorCstr<TLogLevel>(), ToCstr<TLogLevel>(), message.data(),
ansi_color::Black, loc, line, ansi_color::Reset);
}
#if !defined(ASTER_NDEBUG) && !defined(ASTER_NO_BREAK)
if constexpr (TLogLevel == LogType::eError)
{
debug_break();
}
#endif
}
template <LogType TLogLevel>
void
LogCond(char const *exprStr, std::string_view const &message, char const *loc, u32 line) const
{
if (static_cast<u32>(TLogLevel) <= m_MinimumLoggingLevel)
{
fmt::println("{}{} ({}) {} {} at {}:{}{}", ToColorCstr<TLogLevel>(), ToCstr<TLogLevel>(), exprStr,
message.data(), ansi_color::Black, loc, line, ansi_color::Reset);
}
#if !defined(ASTER_NDEBUG) && !defined(ASTER_NO_BREAK)
if constexpr (TLogLevel == LogType::eError)
{
debug_break();
}
#endif
}
};
extern Logger g_Logger;
#define MIN_LOG_LEVEL(LOG_LVL) g_Logger.SetMinimumLoggingLevel(LOG_LVL)
#define ERROR(...) g_Logger.Log<Logger::LogType::eError>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define WARN(...) g_Logger.Log<Logger::LogType::eWarning>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define INFO(...) g_Logger.Log<Logger::LogType::eInfo>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ERROR_IF(expr, ...) \
if (static_cast<bool>(expr)) [[unlikely]] \
g_Logger.LogCond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define WARN_IF(expr, ...) \
if (static_cast<bool>(expr)) [[unlikely]] \
g_Logger.LogCond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define INFO_IF(expr, ...) \
if (static_cast<bool>(expr)) \
g_Logger.LogCond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_IF_ERROR(expr, ...) \
; \
else if (static_cast<bool>(expr)) \
[[unlikely]] g_Logger.LogCond<Logger::LogType::eError>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_IF_WARN(expr, ...) \
; \
else if (static_cast<bool>(expr)) \
[[unlikely]] g_Logger.LogCond<Logger::LogType::eWarning>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_IF_INFO(expr, ...) \
; \
else if (static_cast<bool>(expr)) \
g_Logger.LogCond<Logger::LogType::eInfo>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_ERROR(...) \
; \
else [[unlikely]] g_Logger.Log<Logger::LogType::eError>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_WARN(...) \
; \
else [[unlikely]] g_Logger.Log<Logger::LogType::eWarning>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_INFO(...) \
; \
else g_Logger.Log<Logger::LogType::eInfo>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#if !defined(DEBUG_LOG_DISABLED) && !defined(ASTER_NDEBUG)
#define DEBUG(...) g_Logger.Log<Logger::LogType::eDebug>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define DEBUG_IF(expr, ...) \
if (static_cast<bool>(expr)) \
g_Logger.LogCond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_IF_DEBUG(expr, ...) \
; \
else if (static_cast<bool>(expr)) \
g_Logger.LogCond<Logger::LogType::eDebug>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_DEBUG(...) \
; \
else g_Logger.Log<Logger::LogType::eDebug>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#else // !defined(DEBUG_LOG_DISABLED)
#define DEBUG(...) \
{ \
}
#define DEBUG_IF(expr, ...) \
if (false) \
{ \
}
#define ELSE_IF_DEBUG(expr, ...) \
; \
if (false) \
{ \
}
#define ELSE_DEBUG(...) \
; \
{ \
}
#endif // !defined(DEBUG_LOG_DISABLED)
#if !defined(VERBOSE_LOG_DISABLED) && !defined(ASTER_NDEBUG)
#define VERBOSE(...) g_Logger.Log<Logger::LogType::eVerbose>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define VERBOSE_IF(expr, ...) \
if (static_cast<bool>(expr)) \
g_Logger.LogCond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_IF_VERBOSE(expr, ...) \
; \
else if (static_cast<bool>(expr)) \
g_Logger.LogCond<Logger::LogType::eVerbose>(#expr, fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#define ELSE_VERBOSE(...) \
; \
else g_Logger.Log<Logger::LogType::eVerbose>(fmt::format(__VA_ARGS__), __FILE__, __LINE__)
#else // !defined(DEBUG_LOG_DISABLED)
#define VERBOSE(...) \
{ \
}
#define VERBOSE_IF(expr, ...) \
if (false) \
{ \
} \
}
#define ELSE_IF_VERBOSE(expr, ...) \
; \
if (false) \
{ \
}
#define ELSE_VERBOSE(...) \
; \
{ \
}
#endif // !defined(VERBOSE_LOG_DISABLED)
#define DO(code) , code
#define ABORT(code) exit(static_cast<i32>(code))
#define THEN_ABORT(code) , ABORT(code)