diff --git a/src/ECS/CMakeLists.txt b/src/ECS/CMakeLists.txt index 148889f0..fe67fea1 100644 --- a/src/ECS/CMakeLists.txt +++ b/src/ECS/CMakeLists.txt @@ -13,4 +13,5 @@ target_sources( PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/Registry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Clock.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Logger.cpp ) diff --git a/src/ECS/Logger.cpp b/src/ECS/Logger.cpp new file mode 100644 index 00000000..39521adf --- /dev/null +++ b/src/ECS/Logger.cpp @@ -0,0 +1,189 @@ +/* +** EPITECH PROJECT, 2023 +** Raytracer +** File description: +** Logger.cpp +*/ + +#include "Logger.hpp" +#include +#include +#include +#include +#include "Registry.hpp" + +namespace Logger { + void fatal(const std::string &message) + { + Registry::getInstance().getLogger().fatal(message); + } + void error(const std::string &message) + { + Registry::getInstance().getLogger().error(message); + } + void warn(const std::string &message) + { + Registry::getInstance().getLogger().warn(message); + } + void info(const std::string &message) + { + Registry::getInstance().getLogger().info(message); + } + void debug(const std::string &message) + { + Registry::getInstance().getLogger().debug(message); + } + void trace(const std::string &message) + { + Registry::getInstance().getLogger().trace(message); + } + + Logger::Logger(LogLevel logLevel) : _logLevel(logLevel) + { + } + + void Logger::fatal(const std::string &message) + { + if (_logLevel < LogLevel::Fatal) { + return; + } + Logger::print(LogLevel::Fatal, "FATAL", message); + } + + void Logger::error(const std::string &message) + { + if (_logLevel < LogLevel::Error) { + return; + } + Logger::print(LogLevel::Error, "ERROR", message); + } + + void Logger::warn(const std::string &message) + { + if (_logLevel < LogLevel::Warn) { + return; + } + Logger::print(LogLevel::Warn, "WARN", message); + } + + void Logger::info(const std::string &message) + { + if (_logLevel < LogLevel::Info) { + return; + } + Logger::print(LogLevel::Info, "INFO", message); + } + + void Logger::debug(const std::string &message) + { +#ifdef NDEBUG + return; +#else + if (_logLevel < LogLevel::Debug) { + return; + } + Logger::print(LogLevel::Debug, "DEBUG", message); +#endif + } + + void Logger::trace(const std::string &message) + { +#ifdef NDEBUG + return; +#else + if (_logLevel < LogLevel::Trace) { + return; + } + Logger::print(LogLevel::Trace, "TRACE", message); +#endif + } + + void Logger::print( + LogLevel levelT, + const std::string &level, + const std::string &message) + { +#ifdef __linux__ + static std::map colors = { + {LogLevel::Fatal, "\033[31m"}, + {LogLevel::Error, "\033[33m"}, + {LogLevel::Warn, "\033[34m"}, + {LogLevel::Info, "\033[32m"}, + {LogLevel::Debug, "\033[38m"}, + {LogLevel::Trace, "\033[30m"}, + {LogLevel::MAXLOGLEVEL, "\033[0m" }, + }; +#elif __APPLE__ + static std::map colors = { + {LogLevel::Fatal, "\033[31m"}, + {LogLevel::Error, "\033[33m"}, + {LogLevel::Warn, "\033[34m"}, + {LogLevel::Info, "\033[32m"}, + {LogLevel::Debug, "\033[38m"}, + {LogLevel::Trace, "\033[30m"}, + {LogLevel::MAXLOGLEVEL, "\033[0m" }, + }; +#else + static std::map colors = { + {LogLevel::Fatal, ""}, + {LogLevel::Error, ""}, + {LogLevel::Warn,""}, + {LogLevel::Info, ""}, + {LogLevel::Debug, ""}, + {LogLevel::Trace, ""}, + {LogLevel::MAXLOG ""}, + }; +#endif + + auto const now = std::chrono::current_zone()->to_local( + std::chrono::system_clock::now()); + std::string mes; + auto it = _callbacks.find(levelT); + + mes = std::format("{:%Y-%m-%d %H:%M:%S}", now) + " [" + level + "] " + + message; + std::cerr << colors[levelT] << mes << colors[LogLevel::MAXLOGLEVEL] + << std::endl; + if (it != _callbacks.end()) { + for (auto &it1 : it->second) { + it1.second(mes); + } + } + } + + void Logger::subscribeCallback( + LogLevel type, + const std::string &name, + std::function callback) + { + if (_callbacks.find(type) == _callbacks.end()) { + _callbacks.emplace( + type, + std::map< + std::string, + std::function>()); + } + _callbacks[type].emplace(name, callback); + } + + void Logger::unsubscribeCallback(LogLevel type, const std::string &name) + { + if (_callbacks.find(type) == _callbacks.end()) { + return; + } + if (_callbacks[type].find(name) == _callbacks[type].end()) { + return; + } + _callbacks[type].erase(name); + } + + void Logger::setLogLevel(LogLevel logLevel) + { + _logLevel = logLevel; + } + + LogLevel Logger::getLogLevel() const + { + return _logLevel; + } +} // namespace Logger diff --git a/src/ECS/Logger.hpp b/src/ECS/Logger.hpp new file mode 100644 index 00000000..ba56849a --- /dev/null +++ b/src/ECS/Logger.hpp @@ -0,0 +1,154 @@ +/* +** EPITECH PROJECT, 2023 +** Raytracer +** File description: +** Logger.hpp +*/ + +#pragma once + +#include +#include +#include + +namespace Logger { + enum class LogLevel : int { + NOLOG = -1, + Fatal = 0, + Error = 1, + Warn = 2, + Info = 3, + Debug = 4, + Trace = 5, + MAXLOGLEVEL = 6, + }; + + void fatal(const std::string &message); + void error(const std::string &message); + void warn(const std::string &message); + void info(const std::string &message); + void debug(const std::string &message); + void trace(const std::string &message); + + /** + * @brief Logger + * + * LogLevel: + * LogLevel::NOLOG - no messages + * LogLevel::Fatal - only `fatal` are displayed + * LogLevel::Error - `error` and `fatal` are displayed + * LogLevel::Warn - `warn`, `error` and `fatal` are displayed + * LogLevel::Info - `info`, `warn`, `error` and `fatal` are displayed + * LogLevel::Debug - `debug`, `info`, `warn`, `error` and `fatal` are + * displayed LogLevel::Trace - `trace`, `debug`, `info`, `warn`, `error` and + * `fatal` are displayed + * + * Attention: + * `debug` and `trace` will only do something in debug mode compilation. + * (`set(CMAKE_BUILD_TYPE Debug)` in `CMakeLists.txt`) + */ + class Logger { + public: + Logger(LogLevel logLevel = LogLevel::Info); + /** + * @brief Logger fata + * + * Means that something critical is broken, and the application + * cannot continue to do any more useful work without the + * intervention of an engineer. + * + * @param message the message + */ + void fatal(const std::string &message); + /** + * @brief Logger error + * + * The ERROR log level is used to represent error conditions in + * an application that prevent a specific operation from running, + * but the application itself can continue working even if it is + * at a reduced level of functionality or performance. + * + * @param message the message + */ + void error(const std::string &message); + /** + * @brief Logger warn + * + * Messages logged at the WARN level typically indicate that + * something unexpected happened, but the application can recover + * and continue to function normally. + * + * @param message the message + */ + void warn(const std::string &message); + /** + * @brief Logger info + * + * INFO-level messages indicate events in the system that are + * significant to the business purpose of the application. Such + * events are logged to show that the system is operating normally. + * + * @param message the message + */ + void info(const std::string &message); + /** + * @brief Logger debug + * + * The DEBUG level is used for logging messages that help + * developers find out what went wrong during a debugging session. + * + * @param message the message + */ + void debug(const std::string &message); + /** + * @brief Logger trace + * + * The TRACE level is used for tracing the path of code execution + * in a program. + * + * @param message the message + */ + void trace(const std::string &message); + /** + * @brief Logger subscribe + * + * @param type the type to subscribe for + * @param name the name + * @param callback the callback + */ + void subscribeCallback( + LogLevel type, + const std::string &name, + std::function callback); + /** + * @brief Logger remove + * + * @param type the type + * @param name the name + */ + void unsubscribeCallback(LogLevel type, const std::string &name); + /** + * @brief set log level + * + * @param logLevel the log level + */ + void setLogLevel(LogLevel logLevel); + /** + * @brief get log level + * + * @return the log level + */ + [[nodiscard]] LogLevel getLogLevel() const; + + private: + void print( + LogLevel levelT, + const std::string &level, + const std::string &message); + std::map< + LogLevel, + std::map>> + _callbacks; + LogLevel _logLevel; + }; +} // namespace Logger diff --git a/src/ECS/Registry.cpp b/src/ECS/Registry.cpp index 5bf38040..e1183339 100644 --- a/src/ECS/Registry.cpp +++ b/src/ECS/Registry.cpp @@ -152,3 +152,8 @@ Clock &Registry::getClock() { return _clock; } + +Logger::Logger &Registry::getLogger() +{ + return _logger; +} diff --git a/src/ECS/Registry.hpp b/src/ECS/Registry.hpp index e2114355..6577316e 100644 --- a/src/ECS/Registry.hpp +++ b/src/ECS/Registry.hpp @@ -17,6 +17,7 @@ #include #include #include "Clock.hpp" +#include "Logger.hpp" #include "SceneManager.hpp" #include "SparseArray.hpp" @@ -76,10 +77,13 @@ class Registry { Clock &getClock(); + Logger::Logger &getLogger(); + private: Registry(); Clock _clock; + Logger::Logger _logger; void initLayers(bool back); diff --git a/src/main_client.cpp b/src/main_client.cpp index 161985de..2f633bf8 100644 --- a/src/main_client.cpp +++ b/src/main_client.cpp @@ -5,12 +5,14 @@ ** main */ +#include "Logger.hpp" #include "SceneManager.hpp" int main() { SceneManager &sceneManager = SceneManager::getInstance(); + Logger::info("Starting Game..."); int res = sceneManager.run(); return res;