#pragma once #include #include // hard dependency #include // log impl is heavily influenced & based on the yuzu logger namespace utl { enum class logLevel : uint8_t { Trace, //< very detailed and extensive debugging information Debug, //< less detailed debug information Info, //< status information Warning, //< minor or potential problems Error, //< major problems that block further execution of a task Critical, //< major problems that block continued execution of the entire //application Count //< total number of log levels }; struct logEntry { std::chrono::microseconds timestamp; logLevel log_level; unsigned int line_num; std::string function; std::string message; bool final_entry = false; logEntry() = default; logEntry(logEntry &&o) = default; logEntry &operator=(logEntry &&o) = default; logEntry &operator=(const logEntry &o) = default; }; class logBase { public: virtual ~logBase() = default; virtual const char *getName() { return "Unknown"; } virtual void write(const logEntry &) = 0; }; std::string formatLogEntry(const logEntry &entry); logBase *addLogSink(std::unique_ptr sink); logBase *getLogSink(std::string_view name); void formatLogMsg(logLevel lvl, uint32_t line, const char *func, const char *fmt, const fmt::format_args &args); void createLogger(bool withConsole = false); template inline void fmtLogMsg(logLevel lvl, uint32_t line, const char *func, const char *fmt, const Args &... args) { formatLogMsg(lvl, line, func, fmt, fmt::make_format_args(args...)); } template inline void fmtLogMsg(logLevel lvl, uint32_t line, const char *func, const std::string &text) { formatLogMsg(lvl, line, func, text.c_str(), {}); } } #ifdef _DEBUG #define LOG_TRACE(...) \ ::utl::fmtLogMsg(::utl::logLevel::Trace, __LINE__, __func__, __VA_ARGS__) #else #define LOG_TRACE(fmt, ...) (void(0)) #endif #define LOG_DEBUG(...) \ ::utl::fmtLogMsg(::utl::logLevel::Debug, __LINE__, __func__, __VA_ARGS__) #define LOG_INFO(...) \ ::utl::fmtLogMsg(::utl::logLevel::Info, __LINE__, __func__, __VA_ARGS__) #define LOG_WARNING(...) \ ::utl::fmtLogMsg(::utl::logLevel::Warning, __LINE__, __func__, __VA_ARGS__) #define LOG_ERROR(...) \ ::utl::fmtLogMsg(::utl::logLevel::Error, __LINE__, __func__, __VA_ARGS__) #define LOG_CRITICAL(...) \ ::utl::fmtLogMsg(::utl::logLevel::Critical, __LINE__, __func__, __VA_ARGS__) #define LOG_ASSERT(expression) \ do { \ if (!(expression)) { \ ::utl::fmtLogMsg(::utl::logLevel::Error, __LINE__, __func__, \ "assertion failed at " #expression); \ __debugbreak(); \ } \ \ } while (0) #define LOG_UNIMPLEMENTED \ ::utl::fmtLogMsg(::utl::logLevel::Error, __LINE__, __func__, \ "Unimplemented function")