#pragma once #include #include #include namespace clice::log { enum class Level { INFO, WARN, DEBUG, TRACE, FATAL, }; template void log(Level level, std::string_view fmt, Args&&... args) { namespace chrono = std::chrono; auto now = chrono::floor(chrono::system_clock::now()); auto time = chrono::zoned_time(chrono::current_zone(), now); auto tag = [&] { switch(level) { case Level::INFO: return "\033[32mINFO\033[0m"; // Green case Level::WARN: return "\033[33mWARN\033[0m"; // Yellow case Level::DEBUG: return "\033[36mDEBUG\033[0m"; // Cyan case Level::TRACE: return "\033[35mTRACE\033[0m"; // Magenta case Level::FATAL: return "\033[31mFATAL ERROR\033[0m"; // Red } }(); llvm::errs() << std::format("[{0:%Y-%m-%d %H:%M:%S}] [{1}] ", time, tag) << std::vformat(fmt, std::make_format_args(args...)) << "\n"; } template void info(std::format_string fmt, Args&&... args) { log::log(Level::INFO, fmt.get(), std::forward(args)...); } template void warn(std::format_string fmt, Args&&... args) { log::log(Level::WARN, fmt.get(), std::forward(args)...); } template void debug(std::format_string fmt, Args&&... args) { log::log(Level::DEBUG, fmt.get(), std::forward(args)...); } template void trace(std::format_string fmt, Args&&... args) { log::log(Level::TRACE, fmt.get(), std::forward(args)...); } template void fatal [[noreturn]] (std::format_string fmt, Args&&... args) { log::log(Level::FATAL, fmt.get(), std::forward(args)...); std::terminate(); } } // namespace clice::log