project-aster/aster/logger.h

209 lines
12 KiB
C++

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