Program Listing for File logger.cpp
↰ Return to documentation for file (src\logger.cpp)
#include "logger.h"
namespace prism::logger {
namespace {
Level logLevel = Level::INFO;
std::unique_ptr<std::ofstream> logFileStream;
bool useCustomOutput = false;
// Стандартная функция вывода SDL
static SDL_LogOutputFunction defaultOutputFunction = nullptr;
static void* defaultUserdata = nullptr;
std::optional<Error> 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<Error, std::string> errorMessages = {
{Error::TEST_ERROR, "It is test error"}
};
}
void setLevel(Level level) {
logLevel = level;
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION,
static_cast<SDL_LogPriority>(level));
}
bool setOutputFile(const std::string& filename) {
try {
// Сохраняем стандартный вывод, если ещё не сделали этого
if (!defaultOutputFunction) {
SDL_LogGetOutputFunction(&defaultOutputFunction, &defaultUserdata);
}
logFileStream = std::make_unique<std::ofstream>();
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<int>(level) < static_cast<int>(logLevel)) return;
SDL_LogPriority priority = static_cast<SDL_LogPriority>(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<Error> getLastError()
{
return lastError;
}
bool hasLastError() {
return lastError.has_value();
}
bool checkLastErrorType(Error errorType) {
return lastError.has_value() && lastError == errorType;
}
void clearLastError() {
lastError.reset();
}
}