diff --git a/qtrocket.pro b/qtrocket.pro index 280cfa8..5ede81c 100644 --- a/qtrocket.pro +++ b/qtrocket.pro @@ -25,6 +25,7 @@ SOURCES += \ sim/WindModel.cpp \ utils/BinMap.cpp \ utils/CurlConnection.cpp \ + utils/Logger.cpp \ utils/ThrustCurveAPI.cpp \ utils/math/Quaternion.cpp \ utils/math/Vector3.cpp @@ -47,6 +48,7 @@ HEADERS += \ sim/WindModel.h \ utils/BinMap.h \ utils/CurlConnection.h \ + utils/Logger.h \ utils/ThrustCurveAPI.h \ utils/math/Constants.h \ utils/math/Quaternion.h \ diff --git a/utils/Logger.cpp b/utils/Logger.cpp new file mode 100644 index 0000000..4d8ddff --- /dev/null +++ b/utils/Logger.cpp @@ -0,0 +1,83 @@ +#include "Logger.h" + +#include + +namespace utils +{ +Logger* Logger::instance = nullptr; + +Logger* Logger::getInstance() +{ + if(!instance) + { + instance = new Logger(); + } + return instance; +} + +Logger::Logger() +{ + outFile.open("log.txt"); + /* + error = [this](std::string_view msg) { log(msg, ERROR); }; + warn = [this](std::string_view msg) { log(msg, WARN); }; + info = [this](std::string_view msg) { log(msg, INFO); }; + debug = [this](std::string_view msg) { log(msg, DEBUG); }; + */ +} + +Logger::~Logger() +{ + outFile.close(); +} + +void Logger::log(std::string_view msg, const LogLevel& lvl) +{ + std::lock_guard lck(mtx); + // The fallthrough is intentional. Logging is automatically enabled for + // all levels at or lower than the current level. + switch(currentLevel) + { + case DEBUG: + if(lvl == DEBUG) + { + outFile << "[DEBUG] " << msg << std::endl; + std::cout << "[DEBUG] " << msg << std::endl; + } + [[fallthrough]]; + case INFO: + if(lvl == INFO) + { + outFile << "[INFO] " << msg << std::endl; + std::cout << "[INFO] " << msg << std::endl; + } + [[fallthrough]]; + case WARN: + if(lvl == WARN) + { + outFile << "[WARN] " << msg << std::endl; + std::cout << "[WARN] " << msg << std::endl; + } + [[fallthrough]]; + default: + if(lvl == ERROR) + { + outFile << "[ERROR] " << msg << std::endl; + std::cout << "[ERROR] " << msg << std::endl; + std::cerr << "[ERROR] " << msg << std::endl; + } + } +} + +void Logger::setLogLevel(const LogLevel& lvl) +{ + currentLevel = lvl; +} + +void Logger::log(std::ostream& o, const std::string& msg) +{ + std::lock_guard lck(mtx); + o << msg << std::endl; +} + +} // namespace utils diff --git a/utils/Logger.h b/utils/Logger.h new file mode 100644 index 0000000..95b9d1e --- /dev/null +++ b/utils/Logger.h @@ -0,0 +1,61 @@ +#ifndef UTILS_LOGGER_H +#define UTILS_LOGGER_H + +#include +#include +#include +//#include + +/** + * @todo write docs + */ +namespace utils +{ + +class Logger +{ +public: + enum LogLevel + { + ERROR, + WARN, + INFO, + DEBUG + }; + + static Logger* getInstance(); + + Logger(Logger const&) = delete; + Logger(Logger&&) = delete; + Logger& operator=(Logger const&) = delete; + Logger& operator=(Logger&&) = delete; + + void setLogLevel(const LogLevel& lvl); + + /* + std::function error; + std::function warn; + std::function info; + std::function debug; + */ + inline void error(std::string_view msg) { log(msg, ERROR); } + inline void warn(std::string_view msg) { log(msg, WARN); } + inline void info(std::string_view msg) { log(msg, INFO); } + inline void debug(std::string_view msg) { log(msg, DEBUG); } + + void log(std::ostream& o, const std::string& msg); + +private: + + void log(std::string_view msg, const LogLevel& lvl); + + LogLevel currentLevel; + std::ofstream outFile; + static Logger* instance; + std::mutex mtx; + Logger(); + ~Logger(); +}; + +} // namespace utils +#endif // UTILS_LOGGER_H