.. _program_listing_file_PrismEngine_src_logger.cpp: Program Listing for File logger.cpp =================================== |exhale_lsh| :ref:`Return to documentation for file ` (``PrismEngine/src/logger.cpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #include "logger.h" namespace prism::logger { namespace { Level logLevel = Level::INFO; std::unique_ptr logFileStream; bool useCustomOutput = false; // Стандартная функция вывода SDL static SDL_LogOutputFunction defaultOutputFunction = nullptr; static void* defaultUserdata = nullptr; std::optional lastError; // функция вывода void CustomOutputFunction(void* userdata, int category, SDL_LogPriority priority, const char* message) { if (logFileStream && logFileStream->is_open()) { *logFileStream << message << std::endl; } // Всегда выводим в стандартный вывод SDL if (defaultOutputFunction) { defaultOutputFunction(defaultUserdata, category, priority, message); } } const std::unordered_map errorMessages = { {Error::TEST_ERROR, "It is test error"}, {Error::FAILED_TO_CREATE_VK_INSTANCE, "failed to create Vulkan instance!"}, {Error::FAILED_TO_CREATE_WINDOW_SURFACE, "failed to create window surface!"}, {Error::PRISM_ENGINE_NOT_INITIALIZE, "the part of PrismEngine that requires initialization has been called, please call prism::init() at the beginning of your program" }, {Error::WINDOW_INSTANCE_CREATE_ERROR, "Window instance creation failed for unspecified reasons"}, {Error::NOT_CALL_CLEANUP_IN_PGC_CORE, "Cleanup was not called for an instance of the PGC::core::Core class"}, {Error::SDL_VULKAN_EXTENSIONS_COUNT_FAILED, "Failed to get SDL Vulkan instance extensions count"}, {Error::VULKAN_VALIDATION_LAYERS_UNAVAILABLE, "Vulkan validation layers requested, but not available!"}, {Error::VULKAN_DEBUG_MESSENGER_SETUP_FAILED, "Failed to set up debug messenger!"}, {Error::VULKAN_NO_GPU_SUPPORT, "Failed to find GPUs with Vulkan support!"}, {Error::VULKAN_NO_SUITABLE_GPU, "Failed to find a suitable GPU!"}, {Error::VULKAN_LOGICAL_DEVICE_CREATION_FAILED, "Failed to create logical device!"}, {Error::VULKAN_SWAP_CHAIN_FAILED, "Failed to create swap chain!"}, {Error::FAILED_TO_OPEN_FILE, "Failed to open file"}, {Error::FAILED_TO_DETERMINE_FILE_SIZE, "Failed to determine file size"}, {Error::FAILED_TO_READ_FILE, "Failed to read file"} }; } void setLevel(Level level) { logLevel = level; SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, static_cast(level)); } bool setOutputFile(const std::string& filename) { try { // Сохраняем стандартный вывод, если ещё не сделали этого if (!defaultOutputFunction) { SDL_LogGetOutputFunction(&defaultOutputFunction, &defaultUserdata); } logFileStream = std::make_unique(); logFileStream->open(filename, std::ios::app); if (!logFileStream->is_open()) { logFileStream.reset(); return false; } SDL_LogSetOutputFunction(CustomOutputFunction, nullptr); useCustomOutput = true; return true; } catch (...) { logFileStream.reset(); return false; } } void setOutputConsole() { if (logFileStream) { logFileStream->close(); logFileStream.reset(); } if (useCustomOutput && defaultOutputFunction) { SDL_LogSetOutputFunction(defaultOutputFunction, defaultUserdata); } useCustomOutput = false; } void log(Level level, const std::string& message) { if (static_cast(level) < static_cast(logLevel)) return; SDL_LogPriority priority = static_cast(level); SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, priority, "%s", message.c_str()); } void logError(Error err, const std::string& details) { std::string fullMsg = "[ENGINE ERROR] " + errorMessages.at(err); if (!details.empty()) { fullMsg += " | Details: " + details; } // Сохраняем ошибку lastError = err; log(Level::ERROR, fullMsg); } void verbose(const std::string& message) { log(Level::VERBOSE, message); } void debug(const std::string& message) { log(Level::DEBUG, message); } void info(const std::string& message) { log(Level::INFO, message); } void warning(const std::string& message) { log(Level::WARNING, message); } void error(const std::string& message) { log(Level::ERROR, message); } void critical(const std::string& message) { log(Level::CRITICAL, message); } std::optional getLastError() { return lastError; } bool hasLastError() { return lastError.has_value(); } bool checkLastErrorType(Error errorType) { return lastError.has_value() && lastError == errorType; } void clearLastError() { lastError.reset(); } }