#pragma once /*Utility to log to console*/ #include "ansi.h" //Colors #include #include #include enum TLogLevel {logERROR, logWARNING, logINFOBLUE, logINFOGREEN, logINFORED, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4, logDEBUG5}; // Compiler should optimize away anything below this value #ifndef LOG_MAX_REPORTING_LEVEL #define LOG_MAX_REPORTING_LEVEL logINFO #endif #define __AT__ std::string(__FILE__) + std::string("::") + std::string(__func__) + std::string("(): ") #define __SHORT_FORM_OF_FILE__ \ (strrchr(__FILE__,'/') \ ? strrchr(__FILE__,'/')+1 \ : __FILE__ \ ) #define __SHORT_AT__ std::string(__SHORT_FORM_OF_FILE__) + std::string("::") + std::string(__func__) + std::string("(): ") namespace sls { class Logger { std::ostringstream os; TLogLevel level = LOG_MAX_REPORTING_LEVEL; public: Logger() = default; explicit Logger(TLogLevel level) : level(level){}; ~Logger() { // output in the destructor to allow for << syntax os << RESET << '\n'; std::clog << os.str() << std::flush; // Single write } static TLogLevel &ReportingLevel() { // singelton eeh static TLogLevel reportingLevel = logINFO; return reportingLevel; } // Danger this buffer need as many elements as TLogLevel static const char *Color(TLogLevel level) noexcept { static const char *const colors[] = { RED BOLD, YELLOW BOLD, BLUE, GREEN, RED, RESET, RESET, RESET, RESET, RESET, RESET, RESET}; return colors[level]; } // Danger this buffer need as many elements as TLogLevel static std::string ToString(TLogLevel level) { static const char *const buffer[] = { "ERROR", "WARNING", "INFO", "INFO", "INFO", "INFO", "DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4", "DEBUG5"}; return buffer[level]; } std::ostringstream &Get() { os << Color(level) << "- " << Timestamp() << " " << ToString(level) << ": "; return os; } static std::string Timestamp() { constexpr size_t buffer_len = 12; char buffer[buffer_len]; time_t t; ::time(&t); tm r; strftime(buffer, buffer_len, "%X", localtime_r(&t, &r)); buffer[buffer_len - 1] = '\0'; struct timeval tv; gettimeofday(&tv, nullptr); constexpr size_t result_len = 100; char result[result_len]; snprintf(result, result_len, "%s.%03ld", buffer, (long)tv.tv_usec / 1000); result[result_len - 1] = '\0'; return result; } }; #define LOG(level) \ if (level > LOG_MAX_REPORTING_LEVEL) \ ; \ else if (level > sls::Logger::ReportingLevel()) \ ; \ else \ sls::Logger(level).Get() } // namespace sls