diff --git a/src/application.cpp b/src/application.cpp index 0d9e2ff..640d966 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -107,18 +107,8 @@ application::application(int argc, char** argv): { // Format log messages logger.set_warning_prefix("Warning: "); - logger.set_error_prefix("Error: "); + logger.set_error_prefix(std::string()); logger.set_success_prefix(std::string()); - #if defined(DEBUG) - #if !defined(_WIN32) - logger.set_warning_prefix(std::string(ansi::bold) + std::string(ansi::yellow) + std::string("Warning: ") + std::string(ansi::reset) + std::string(ansi::yellow)); - logger.set_warning_postfix(ansi::reset); - logger.set_error_prefix(std::string(ansi::bold) + std::string(ansi::red) + std::string("Error: ") + std::string(ansi::reset) + std::string(ansi::red)); - logger.set_error_postfix(ansi::reset); - logger.set_success_prefix(ansi::green); - logger.set_success_postfix(ansi::reset); - #endif - #endif // Redirect logger output #if defined(DEBUG) @@ -153,14 +143,14 @@ application::application(int argc, char** argv): { if (!path_exists(path)) { - int create_path_task = logger.open_task("Creating directory \"" + path + "\""); + logger.push_task("Creating directory \"" + path + "\""); if (create_directory(path)) { - logger.close_task(create_path_task, EXIT_SUCCESS); + logger.pop_task(EXIT_SUCCESS); } else { - logger.close_task(create_path_task, EXIT_FAILURE); + logger.pop_task(EXIT_FAILURE); } } } @@ -194,26 +184,26 @@ application::application(int argc, char** argv): logger.log("Linking against SDL " + sdl_linked_version_string + "\n"); // Init SDL - int sdl_init_task = logger.open_task("Initializing SDL"); + logger.push_task("Initializing SDL"); if (SDL_Init(SDL_INIT_VIDEO) != 0) { - logger.close_task(sdl_init_task, EXIT_FAILURE); + logger.pop_task(EXIT_FAILURE); throw std::runtime_error("Failed to initialize SDL"); } else { - logger.close_task(sdl_init_task, EXIT_SUCCESS); + logger.pop_task(EXIT_SUCCESS); } // Load default OpenGL library - int load_gl_task = logger.open_task("Loading OpenGL library"); + logger.push_task("Loading OpenGL library"); if (SDL_GL_LoadLibrary(nullptr) != 0) { - logger.close_task(load_gl_task, EXIT_FAILURE); + logger.pop_task(EXIT_FAILURE); } else { - logger.close_task(load_gl_task, EXIT_SUCCESS); + logger.pop_task(EXIT_SUCCESS); } // Set window creation hints @@ -250,7 +240,7 @@ application::application(int argc, char** argv): } // Create window - int window_creation_task = logger.open_task("Creating " + std::to_string(window_width) + "x" + std::to_string(window_height) + " window"); + logger.push_task("Creating " + std::to_string(window_width) + "x" + std::to_string(window_height) + " window"); window = SDL_CreateWindow ( "Antkeeper", @@ -260,48 +250,48 @@ application::application(int argc, char** argv): ); if (!window) { - logger.close_task(window_creation_task, EXIT_FAILURE); + logger.pop_task(EXIT_FAILURE); throw std::runtime_error("Failed to create SDL window"); } else { - logger.close_task(window_creation_task, EXIT_SUCCESS); + logger.pop_task(EXIT_SUCCESS); } // Create OpenGL context - int create_gl_context_task = logger.open_task("Creating OpenGL 3.3 context"); + logger.push_task("Creating OpenGL 3.3 context"); context = SDL_GL_CreateContext(window); if (!context) { - logger.close_task(create_gl_context_task, EXIT_FAILURE); + logger.pop_task(EXIT_FAILURE); throw std::runtime_error("Failed to create OpenGL context"); } else { - logger.close_task(create_gl_context_task, EXIT_SUCCESS); + logger.pop_task(EXIT_SUCCESS); } // Load OpenGL functions via GLAD - int load_gl_functions_task = logger.open_task("Loading OpenGL functions"); + logger.push_task("Loading OpenGL functions"); if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { - logger.close_task(load_gl_functions_task, EXIT_FAILURE); + logger.pop_task(EXIT_FAILURE); } else { - logger.close_task(load_gl_functions_task, EXIT_SUCCESS); + logger.pop_task(EXIT_SUCCESS); } // Set v-sync mode int swap_interval = 1; - int set_vsync_task = logger.open_task((swap_interval) ? "Enabling v-sync" : "Disabling v-sync"); + logger.push_task((swap_interval) ? "Enabling v-sync" : "Disabling v-sync"); if (SDL_GL_SetSwapInterval(swap_interval) != 0) { - logger.close_task(set_vsync_task, EXIT_FAILURE); + logger.pop_task(EXIT_FAILURE); } else { - logger.close_task(set_vsync_task, EXIT_SUCCESS); + logger.pop_task(EXIT_SUCCESS); } // Setup rasterizer @@ -319,27 +309,27 @@ application::application(int argc, char** argv): SDL_ShowCursor(SDL_DISABLE); // Init SDL joystick and game controller subsystems - int init_sdl_subsystems_task = logger.open_task("Initializing SDL Joystick and Game Controller subsystems"); + logger.push_task("Initializing SDL Joystick and Game Controller subsystems"); if (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) != 0) { - logger.close_task(init_sdl_subsystems_task, EXIT_FAILURE); + logger.pop_task(EXIT_FAILURE); throw std::runtime_error("Failed to initialize SDL Joystick or Game Controller subsystems"); } else { - logger.close_task(init_sdl_subsystems_task, EXIT_SUCCESS); + logger.pop_task(EXIT_SUCCESS); } // Load SDL game controller mappings - int load_controller_db_task = logger.open_task("Loading SDL game controller mappings from database"); + logger.push_task("Loading SDL game controller mappings from database"); std::string gamecontrollerdb_path = data_path + "controls/gamecontrollerdb.txt"; if (SDL_GameControllerAddMappingsFromFile(gamecontrollerdb_path.c_str()) == -1) { - logger.close_task(load_controller_db_task, EXIT_FAILURE); + logger.pop_task(EXIT_FAILURE); } else { - logger.close_task(load_controller_db_task, EXIT_SUCCESS); + logger.pop_task(EXIT_SUCCESS); } // Setup billboard VAO diff --git a/src/debug/logger.cpp b/src/debug/logger.cpp index 8db6867..07c2892 100644 --- a/src/debug/logger.cpp +++ b/src/debug/logger.cpp @@ -18,19 +18,21 @@ */ #include "logger.hpp" +#include "timestamp.hpp" #include logger::logger(): os(&std::cout), log_prefix(std::string()), log_postfix(std::string()), - warning_prefix(std::string("Warning: ")), + warning_prefix(std::string()), warning_postfix(std::string()), - error_prefix(std::string("Error: ")), + error_prefix(std::string()), error_postfix(std::string()), - success_prefix(std::string("Success: ")), + success_prefix(std::string()), success_postfix(std::string()), - next_task_id(0) + indent("| "), + timestamp_enabled(true) {} logger::~logger() @@ -45,6 +47,14 @@ void logger::log(const std::string& text) { if (os) { + if (timestamp_enabled) + { + (*os) << timestamp() << ": "; + } + + for (std::size_t i = 0; i < tasks.size(); ++i) + (*os) << indent; + for (const std::string& prefix: prefix_stack) { (*os) << prefix; @@ -121,43 +131,45 @@ void logger::pop_prefix() prefix_stack.pop_back(); } -int logger::open_task(const std::string& text) +void logger::push_task(const std::string& description) { - tasks[next_task_id] = text; + std::string message = description + "...\n"; - std::string indent; - for (std::size_t i = 0; i < tasks.size() - 1; ++i) - indent += " "; + log(message); - log(indent + text + "...\n"); - - return next_task_id++; + tasks.push(description); } -bool logger::close_task(int id, int status) +void logger::pop_task(int status) { - auto it = tasks.find(id); - if (it == tasks.end()) - return false; - - std::string message = it->second + "... "; + if (tasks.empty()) + { + return; + } + std::string message = tasks.top() + "... "; - std::string indent; - for (std::size_t i = 0; i < tasks.size() - 1; ++i) - indent += " "; + tasks.pop(); if (status == EXIT_SUCCESS) { message += "success\n"; - log(indent + message); + log(message); } else { message += "failed (" + std::to_string(status) + ")\n"; - log(indent + message); + error(message); } - - tasks.erase(it); +} + +void logger::set_indent(const std::string& indent) +{ + this->indent = indent; +} + +void logger::set_timestamp(bool enabled) +{ + timestamp_enabled = enabled; } diff --git a/src/debug/logger.hpp b/src/debug/logger.hpp index 97c2a42..2d83f75 100644 --- a/src/debug/logger.hpp +++ b/src/debug/logger.hpp @@ -22,8 +22,8 @@ #include #include +#include #include -#include class logger { @@ -59,20 +59,32 @@ public: void pop_prefix(); /** - * Opens a task and outputs it to the log. + * Pushes a task onto the stack and outputs it to the log. * - * @return Task ID used to close the task later. + * @param description Task description. */ - int open_task(const std::string& text); + void push_task(const std::string& description); /** - * Closes a task and outputs its status to the log. + * Pops a task off the stack and outputs its status to the log. * - * @param id ID of the task to close. * @param status Exit status of the task. A value of `0` or `EXIT_SUCCESS` indicates the task exited successfully. A non-zero exit status indicates the task failed. - * @return `true` if the task was closed, `false` if no task with the specified ID was found. */ - bool close_task(int id, int status); + void pop_task(int status); + + /** + * Sets the indent string which prefixes subtasks. This string will be repeated according to the level of indentation. + * + * @param indent Indent string. + */ + void set_indent(const std::string& indent); + + /** + * Enables or disables prefixing log messages with a timestamp. + * + * @param enabled `true` if timestamps should be enabled, `false` otherwise. + */ + void set_timestamp(bool enabled); private: std::ostream* os; @@ -85,9 +97,10 @@ private: std::string success_prefix; std::string success_postfix; std::list prefix_stack; - int next_task_id; - std::unordered_map tasks; + std::stack tasks; + std::string indent; + bool timestamp_enabled; }; #endif // ANTKEEPER_LOGGER_HPP diff --git a/src/resources/resource-manager.hpp b/src/resources/resource-manager.hpp index 4246214..755db7d 100644 --- a/src/resources/resource-manager.hpp +++ b/src/resources/resource-manager.hpp @@ -108,10 +108,9 @@ T* resource_manager::load(const std::string& path) return resource->data; } - int task_id; if (logger) { - task_id = logger->open_task("Loading resource \"" + path + "\""); + logger->push_task("Loading resource \"" + path + "\""); } // Resource not found, load resource data @@ -150,7 +149,7 @@ T* resource_manager::load(const std::string& path) { if (logger) { - logger->close_task(task_id, EXIT_FAILURE); + logger->pop_task(EXIT_FAILURE); } throw std::runtime_error("resource_manager::load(): Unable to open file \"" + path + "\""); @@ -160,7 +159,7 @@ T* resource_manager::load(const std::string& path) { if (logger) { - logger->close_task(task_id, EXIT_FAILURE); + logger->pop_task(EXIT_FAILURE); } std::string error = std::string("resource_manager::load(): Failed to load resource \"") + path + std::string("\": \"") + e.what() + std::string("\""); @@ -177,7 +176,7 @@ T* resource_manager::load(const std::string& path) if (logger) { - logger->close_task(task_id, EXIT_SUCCESS); + logger->pop_task(EXIT_SUCCESS); } return resource->data; diff --git a/src/state/loading-state.cpp b/src/state/loading-state.cpp index b6e2e18..f1353d7 100644 --- a/src/state/loading-state.cpp +++ b/src/state/loading-state.cpp @@ -24,9 +24,9 @@ void enter_loading_state(application* app) { logger* logger = app->get_logger(); - int task_id = logger->open_task("Entering loading state"); + logger->push_task("Entering loading state"); - logger->close_task(task_id, EXIT_SUCCESS); + logger->pop_task(EXIT_SUCCESS); app->get_state_machine()->change_state(app->get_title_state()); } @@ -34,8 +34,8 @@ void enter_loading_state(application* app) void exit_loading_state(application* app) { logger* logger = app->get_logger(); - int task_id = logger->open_task("Exiting loading state"); + logger->push_task("Exiting loading state"); - logger->close_task(task_id, EXIT_SUCCESS); + logger->pop_task(EXIT_SUCCESS); } diff --git a/src/state/play-state.cpp b/src/state/play-state.cpp index d0015c7..db844be 100644 --- a/src/state/play-state.cpp +++ b/src/state/play-state.cpp @@ -44,7 +44,7 @@ using namespace vmq::operators; void enter_play_state(application* app) { logger* logger = app->get_logger(); - int enter_state_task = logger->open_task("Entering play state"); + logger->push_task("Entering play state"); resource_manager* resource_manager = app->get_resource_manager(); @@ -227,16 +227,14 @@ void enter_play_state(application* app) control_system->set_nest(nest); orbit_cam->update(0.0f); - logger->close_task(enter_state_task, EXIT_SUCCESS); + logger->pop_task(EXIT_SUCCESS); } void exit_play_state(application* app) { logger* logger = app->get_logger(); - logger->log("Exiting play state...\n"); + logger->push_task("Exiting play state"); - int exit_state_task = logger->open_task("Exiting play state"); - - logger->close_task(exit_state_task, EXIT_SUCCESS); + logger->pop_task(EXIT_SUCCESS); } diff --git a/src/state/splash-state.cpp b/src/state/splash-state.cpp index 76e6c5f..4f51ec3 100644 --- a/src/state/splash-state.cpp +++ b/src/state/splash-state.cpp @@ -26,7 +26,7 @@ void enter_splash_state(application* app) { logger* logger = app->get_logger(); - int task_id = logger->open_task("Entering splash state"); + logger->push_task("Entering splash state"); auto fade_in = [logger]() { @@ -58,13 +58,13 @@ void enter_splash_state(application* app) // Add splash sequence to timeline timeline->add_sequence(splash_sequence); - logger->close_task(task_id, EXIT_SUCCESS); + logger->pop_task(EXIT_SUCCESS); } void exit_splash_state(application* app) { logger* logger = app->get_logger(); - int task_id = logger->open_task("Exiting splash state"); + logger->push_task("Exiting splash state"); - logger->close_task(task_id, EXIT_SUCCESS); + logger->pop_task(EXIT_SUCCESS); } diff --git a/src/state/title-state.cpp b/src/state/title-state.cpp index 3834fa9..bac03e3 100644 --- a/src/state/title-state.cpp +++ b/src/state/title-state.cpp @@ -23,7 +23,7 @@ void enter_title_state(application* app) { logger* logger = app->get_logger(); - int task_id = logger->open_task("Entering title state"); + logger->push_task("Entering title state"); // Get timeline timeline* timeline = app->get_timeline(); @@ -41,14 +41,14 @@ void enter_title_state(application* app) // Add title sequence to timeline timeline->add_sequence(title_sequence); - logger->close_task(task_id, EXIT_SUCCESS); + logger->pop_task(EXIT_SUCCESS); } void exit_title_state(application* app) { logger* logger = app->get_logger(); - int task_id = logger->open_task("Exiting title state"); + logger->push_task("Exiting title state"); - logger->close_task(task_id, EXIT_SUCCESS); + logger->pop_task(EXIT_SUCCESS); }