library/src/log.cpp

166 lines
4.5 KiB
C++

/**
* @author Julian Hinxlage
* @since 0.1.0
*/
#include "log.hpp"
#include <fstream>
#include <iostream>
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);
}
}
}