diff --git a/engine/pch.hpp b/engine/pch.hpp index a64a22e..7a4822a 100644 --- a/engine/pch.hpp +++ b/engine/pch.hpp @@ -9,5 +9,6 @@ #include #include #include +#include #include #include diff --git a/engine/src/core/Logger.hpp b/engine/src/core/Logger.hpp index 150ead6..132f524 100644 --- a/engine/src/core/Logger.hpp +++ b/engine/src/core/Logger.hpp @@ -17,42 +17,65 @@ namespace ICEngine { FATAL }; - class Logger { - private: - Logger(const char *name, std::ostream *stream) : name(name) { - if (stream) { - streams.push_back(std::unique_ptr(stream)); + class LogSink { + public: + virtual ~LogSink() = default; + + virtual void Log(const std::string &message) = 0; + }; + + class ConsoleSink : public LogSink { + public: + void Log(const std::string &message) override { + std::cout << message << std::endl; + } + }; + + class FileSink : public LogSink { + public: + explicit FileSink(const std::string &filename) { + fileStream.open(filename); + } + + void Log(const std::string &message) override { + if (fileStream.is_open()) { + fileStream << message << std::endl; } } - friend class Log; + private: + std::ofstream fileStream; + }; + class Logger { public: + explicit Logger(const char *name) : name(name) { + } + void SetLevel(LogLevel level) { this->level = level; } - void AddStream(std::unique_ptr stream) { - this->streams.push_back(std::move(stream)); + void AddSink(std::shared_ptr sink) { + sinks.push_back(std::move(sink)); } template void Log(LogLevel level, const char *file, int line, const char *func, const std::string &formatStr, Args &&... args) { - // TODO: Create a crash handler and manage fatal messages separately (creates crashdump) - // TODO: Allow user to create their own class that inherits Fatal Handler so they can implement it themselves if (level < this->level) return; - std::string formattedMessage = format(formatStr, std::forward(args)...); - std::string logMessage = formatMessage(level, file, line, func, formattedMessage); - for (const auto &stream: streams) { - (*stream) << logMessage << std::endl; + std::string logMessage = formatMessage(level, file, line, func, + format(formatStr, std::forward(args)...)); + + for (const auto &sink: sinks) { + sink->Log(logMessage); } } private: const char *name; - std::vector > streams; + std::vector > sinks; LogLevel level = DEBUG; static const char *levelToString(LogLevel level) { @@ -108,7 +131,7 @@ namespace ICEngine { } std::string formatMessage(LogLevel level, const char *file, int line, const char *func, - const std::string &message) { + const std::string &message) { std::ostringstream oss; oss << getCurrentTime() << " "; oss << truncateFilePath(file) << ":" << line << ":" << func << " "; @@ -130,17 +153,16 @@ namespace ICEngine { } GetCoreLogger(); GetAppLogger(); - isInitialized = true; } static std::shared_ptr &GetCoreLogger() { - static std::shared_ptr CoreLogger(new Logger("CORE", &std::cout)); + static std::shared_ptr CoreLogger(new Logger("CORE")); return CoreLogger; } static std::shared_ptr &GetAppLogger() { - static std::shared_ptr AppLogger(new Logger("APP", &std::cout)); + static std::shared_ptr AppLogger(new Logger("APP")); return AppLogger; } diff --git a/examples/client/client.cpp b/examples/client/client.cpp index 8d65fbf..224e3bd 100644 --- a/examples/client/client.cpp +++ b/examples/client/client.cpp @@ -8,11 +8,20 @@ void ShowLogger(); int main() { - ShowLogger(); - ICEngine::StartApplication(); + try { + ShowLogger(); + ICEngine::StartApplication(); + } catch (const std::exception& e) { + CORE_LOG_FATAL("Unhandled exception: {}", e.what()); + return -1; + } catch (...) { + CORE_LOG_FATAL("Unknown fatal error occurred."); + return -1; + } return 0; } + void ShowLogger() { // The logger needs to be initialized before you can use it. // This will be done by the engine, NEVER the user. @@ -39,11 +48,8 @@ void ShowLogger() { // You need to create a unique pointer, because the logger will // take ownership of the streams and clean them up when the app // is complete - auto coreFileStream = std::make_unique("core_logs.txt"); - auto appFileStream = std::make_unique("app_logs.txt"); - - ICEngine::Log::GetCoreLogger()->AddStream(std::move(coreFileStream)); - ICEngine::Log::GetAppLogger()->AddStream(std::move(appFileStream)); + ICEngine::Log::GetCoreLogger()->AddSink(std::make_shared("core_logs.txt")); + ICEngine::Log::GetAppLogger()->AddSink(std::make_shared("app_logs.txt")); // You can log multiple different types with formatting int age = 30; diff --git a/examples/server/server.cpp b/examples/server/server.cpp index d15e6b8..650f00c 100644 --- a/examples/server/server.cpp +++ b/examples/server/server.cpp @@ -5,7 +5,5 @@ #include int main() { - Logger logger; - logger.logVersion(); - return 0; + } \ No newline at end of file