/** * @author Julian Hinxlage * @since 0.1.0 */ #include "log.hpp" #include #include namespace vkvm { LogLevel logLevel = LogLevel::INFO; LogLevel fileLogLevel = LogLevel::INFO; std::ofstream logToFileStream;//NOLINT //converts the level to a string of the level auto getLevelName(LogLevel level) -> std::string { switch(level){ case LogLevel::DEBUG: return "DEBUG"; case LogLevel::INFO: return "INFO"; case LogLevel::WARNING: return "WARNING"; case LogLevel::ERROR: return "ERROR"; case LogLevel::CRITICAL: return "CRITICAL"; default: return "NON"; } } //converts the level to a ansi color code auto getLevelColor(LogLevel level) -> std::string { switch(level){ case LogLevel::DEBUG: return "0;37"; case LogLevel::INFO: return "0"; case LogLevel::WARNING: return "1;33"; case LogLevel::ERROR: return "1;31"; case LogLevel::CRITICAL: return "1;35"; default: return "0"; } } //log the current time auto logTime() -> std::string { time_t rawtime; time(&rawtime); struct tm *timeinfo; timeinfo = localtime(&rawtime); constexpr int decimalBase = 10; std::stringstream stream; if (timeinfo->tm_hour < decimalBase) { stream << "0"; } stream << timeinfo->tm_hour; stream << ":"; if (timeinfo->tm_min < decimalBase) { stream << "0"; } stream << timeinfo->tm_min; stream << ":"; if (timeinfo->tm_sec < decimalBase) { stream << "0"; } stream << timeinfo->tm_sec; return stream.str(); } //log the message auto log(LogLevel level, const std::string &msg) -> void { if(level >= logLevel || level >= fileLogLevel) { std::string levelName = getLevelName(level); const int maxLevelNameLength = 8; std::stringstream stream; std::stringstream noColorStream; //time std::string time = logTime(); stream << "["; stream << time; stream << "] "; noColorStream << "["; noColorStream << time; noColorStream << "] "; //color and level name stream << "["; stream << "\033[" << getLevelColor(level) << "m" << levelName << "\033[0m"; stream << "] "; for (int i = levelName.size(); i < maxLevelNameLength; i++) { stream << " "; } //no color and level name noColorStream << "["; noColorStream << levelName; noColorStream << "] "; for (int i = levelName.size(); i < maxLevelNameLength; i++) { noColorStream << " "; } //message for(char c : msg){ if(c == '\n'){ //intend newlines so that they align with the start of the message stream << "\n"; noColorStream << "\n"; const int paddingSize = 22; for(int i = 0; i < paddingSize;i++){ stream << " "; noColorStream << " "; } }else{ stream << c; noColorStream << c; } } stream << "\n"; noColorStream << "\n"; if(level >= logLevel){ std::cout << stream.str(); } if(logToFileStream.is_open()){ if(level >= fileLogLevel){ logToFileStream << noColorStream.str(); //TODO(julian): fixme logToFileStream.flush(); } } } } auto setLogLevel(LogLevel level) -> void { logLevel = level; } auto setLogFileLevel(LogLevel level) -> void { fileLogLevel = level; } auto setLogToFile(const std::string &file) -> void { if(logToFileStream.is_open()){ logToFileStream.close(); } if(!file.empty()){ logToFileStream.open(file, std::ofstream::app); } } }