#ifndef LOG_HPP #define LOG_HPP // comment out to disable logging in general #define applog(level, fmt, ...) utils::log(level, std::source_location::current(), fmt, ##__VA_ARGS__) // comment out to disable logging to file // #define LOG_FILE_LOCATION "linuxSmartie.log.gz" #ifdef applog #include #include #include #include #include #ifdef LOG_FILE_LOCATION #include inline std::mutex fmtx; // file logging mutex #endif enum class LOG { INF, WRN, ERR, DBG, START }; namespace utils { inline std::mutex cmtx; // console logging mutex constexpr std::string pFname(std::string_view full) { if (const auto pos = full.find(' '); pos != std::string_view::npos) full.remove_prefix(pos + 1); if (const auto pos = full.rfind('('); pos != std::string_view::npos) full.remove_suffix(full.size() - pos); return std::string(full); } template void log(const LOG level, const std::source_location& loc, std::format_string str, Args&&... args) { constexpr std::string_view reset = "\033[0m"; constexpr std::string_view pattern = "[{}{}{}] "; std::string_view color; switch (level) { case LOG::INF: color = "\033[1;32m"; break; // bold; green case LOG::WRN: color = "\033[1;33m"; // bold; yellow break; case LOG::ERR: color = "\033[1;31m"; // bold; red break; case LOG::DBG: break; case LOG::START: color = "\033[1;3;36m"; // bold; blinking; cyan break; } /* log to console */ { std::scoped_lock lock(cmtx); std::print(pattern, color, pFname(loc.function_name()), reset); std::println(str, std::forward(args)...); } #ifdef LOG_FILE_LOCATION /* log to file */ { auto now = std::chrono::system_clock::now(); auto local = std::chrono::current_zone()->to_local(now); std::string msg = std::format("{:%x %H:%M:%S }", floor(local)); // timestamp std::format_to(std::back_inserter(msg), pattern, color, pFname(loc.function_name()), reset); // tag std::format_to(std::back_inserter(msg), str, std::forward(args)...); // actual log message std::scoped_lock lock(fmtx); gzFile file = gzopen(LOG_FILE_LOCATION, "ab"); if (file) { gzprintf(file, "%s\n", msg.c_str()); gzclose(file); } } #endif } } // namespace utils #else #define applog(...) #endif #endif