From 65ab5528d0b49e05c8f3a4660b4ccbea8302cfa3 Mon Sep 17 00:00:00 2001 From: Beats Date: Fri, 25 Oct 2024 01:32:31 -0300 Subject: [PATCH] perf: optimized logging with profiling and efficient file management (#7777) (#2832) This improves the performance of the logging system and adds profiling functionality with automatic log generation. Additionally, optimizations have been performed to ensure that logs are written efficiently to text files. --------- Co-authored-by: Eduardo Dantas --- cmake/modules/BaseConfig.cmake | 1 + config.lua.dist | 5 +- src/account/account.cpp | 1 - src/account/account_repository_db.cpp | 1 - src/canary_server.cpp | 4 +- src/config/configmanager.cpp | 5 +- src/database/database.hpp | 1 - src/game/scheduling/task.cpp | 1 - src/kv/kv.hpp | 1 - src/kv/kv_sql.cpp | 1 - src/lib/CMakeLists.txt | 1 + src/lib/di/soft_singleton.hpp | 1 - src/lib/logging/log_with_spd_log.cpp | 34 +++- src/lib/logging/log_with_spd_log.hpp | 31 +++- src/lib/logging/logger.cpp | 74 +++++++++ src/lib/logging/logger.hpp | 157 +++++++++++------- src/lib/thread/thread_pool.hpp | 1 - src/lua/scripts/luascript.hpp | 1 - src/main.cpp | 19 --- src/server/server.hpp | 1 - src/utils/pugicast.cpp | 2 - src/utils/transparent_string_hash.hpp | 24 +++ .../fixture/lib/logging/in_memory_logger.hpp | 30 +++- vcproj/canary.vcxproj | 1 + 24 files changed, 285 insertions(+), 113 deletions(-) create mode 100644 src/lib/logging/logger.cpp create mode 100644 src/utils/transparent_string_hash.hpp diff --git a/cmake/modules/BaseConfig.cmake b/cmake/modules/BaseConfig.cmake index e772f78b3a1..14dc6e22153 100644 --- a/cmake/modules/BaseConfig.cmake +++ b/cmake/modules/BaseConfig.cmake @@ -87,6 +87,7 @@ endif() # cmake -DDEBUG_LOG=ON .. if(DEBUG_LOG) add_definitions(-DDEBUG_LOG=ON) + add_definitions(-DSPDLOG_ACTIVE_LEVEL=SPDLOG_LEVEL_TRACE) log_option_enabled("DEBUG LOG") else() log_option_disabled("DEBUG LOG") diff --git a/config.lua.dist b/config.lua.dist index 07792a0289b..4d28a2033cd 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -9,7 +9,8 @@ coreDirectory = "data" -- Set log level -- It can be trace, debug, info, warning, error, critical, off (default: info). --- NOTE: Will only display logs with level higher or equal the one set. +-- NOTE: It will only be valid after the server starts up and only display logs with level higher or equal the one set. +-- NOTE: Debug and trace logs are only available if compiled in debug mode. logLevel = "info" --- Toggles the server's maintenance mode. @@ -52,7 +53,7 @@ cleanProtectionZones = false -- Connection Config -- NOTE: allowOldProtocol can allow login on 10x protocol. (11.00) -- NOTE: maxPlayers set to 0 means no limit --- NOTE: MaxPacketsPerSeconds if you change you will be subject to bugs by WPE, keep the default value of 25, +-- NOTE: MaxPacketsPerSeconds if you change you will be subject to bugs by WPE, keep the default value of 25, -- It's recommended to use a range like min 50 in this function, otherwise you will be disconnected after equipping two-handed distance weapons. ip = "127.0.0.1" allowOldProtocol = false diff --git a/src/account/account.cpp b/src/account/account.cpp index 8b67c09ebca..2cd411ef3e7 100644 --- a/src/account/account.cpp +++ b/src/account/account.cpp @@ -14,7 +14,6 @@ #include "utils/definitions.hpp" #include "security/argon.hpp" #include "utils/tools.hpp" -#include "lib/logging/log_with_spd_log.hpp" #include "enums/account_type.hpp" #include "enums/account_coins.hpp" diff --git a/src/account/account_repository_db.cpp b/src/account/account_repository_db.cpp index a6d169ef4af..10f3d6f3a41 100644 --- a/src/account/account_repository_db.cpp +++ b/src/account/account_repository_db.cpp @@ -10,7 +10,6 @@ #include "account/account_repository_db.hpp" #include "database/database.hpp" -#include "lib/logging/logger.hpp" #include "utils/definitions.hpp" #include "utils/tools.hpp" #include "enums/account_type.hpp" diff --git a/src/canary_server.cpp b/src/canary_server.cpp index 7606a026362..aaf1de80530 100644 --- a/src/canary_server.cpp +++ b/src/canary_server.cpp @@ -97,7 +97,6 @@ int CanaryServer::run() { #endif g_game().start(&serviceManager); - g_game().setGameState(GAME_STATE_NORMAL); if (g_configManager().getBoolean(TOGGLE_MAINTAIN_MODE)) { g_game().setGameState(GAME_STATE_CLOSED); g_logger().warn("Initialized in maintain mode!"); @@ -133,6 +132,7 @@ int CanaryServer::run() { } logger.info("{} {}", g_configManager().getString(SERVER_NAME), "server online!"); + g_logger().setLevel(g_configManager().getString(LOGLEVEL)); serviceManager.run(); @@ -203,7 +203,7 @@ void CanaryServer::logInfos() { logger.info("{} - Version {}", ProtocolStatus::SERVER_NAME, SERVER_RELEASE_VERSION); #endif - logger.debug("Compiled with {}, on {} {}, for platform {}\n", getCompiler(), __DATE__, __TIME__, getPlatform()); + logger.debug("Compiled with {}, on {} {}, for platform {}", getCompiler(), __DATE__, __TIME__, getPlatform()); #if defined(LUAJIT_VERSION) logger.debug("Linked with {} for Lua support", LUAJIT_VERSION); diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index 2cae928382f..aa028b52284 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -35,10 +35,6 @@ bool ConfigManager::load() { return false; } -#ifndef DEBUG_LOG - g_logger().setLevel(loadStringConfig(L, LOGLEVEL, "logLevel", "info")); -#endif - // Parse config // Info that must be loaded one time (unless we reset the modules involved) if (!loaded) { @@ -363,6 +359,7 @@ bool ConfigManager::load() { loadStringConfig(L, TIBIADROME_CONCOCTION_TICK_TYPE, "tibiadromeConcoctionTickType", "online"); loadStringConfig(L, URL, "url", ""); loadStringConfig(L, WORLD_TYPE, "worldType", "pvp"); + loadStringConfig(L, LOGLEVEL, "logLevel", "info"); loaded = true; lua_close(L); diff --git a/src/database/database.hpp b/src/database/database.hpp index 2a27c30159b..837933f3879 100644 --- a/src/database/database.hpp +++ b/src/database/database.hpp @@ -10,7 +10,6 @@ #pragma once #include "declarations.hpp" -#include "lib/logging/log_with_spd_log.hpp" #ifndef USE_PRECOMPILED_HEADERS #include diff --git a/src/game/scheduling/task.cpp b/src/game/scheduling/task.cpp index 0e1f6489516..8e1b984a905 100644 --- a/src/game/scheduling/task.cpp +++ b/src/game/scheduling/task.cpp @@ -9,7 +9,6 @@ #include "task.hpp" -#include "lib/logging/log_with_spd_log.hpp" #include "lib/metrics/metrics.hpp" std::atomic_uint_fast64_t Task::LAST_EVENT_ID = 0; diff --git a/src/kv/kv.hpp b/src/kv/kv.hpp index fa32461b24b..c00a0fd4204 100644 --- a/src/kv/kv.hpp +++ b/src/kv/kv.hpp @@ -20,7 +20,6 @@ #include #endif -#include "lib/logging/logger.hpp" #include "kv/value_wrapper.hpp" class KV : public std::enable_shared_from_this { diff --git a/src/kv/kv_sql.cpp b/src/kv/kv_sql.cpp index 0391425884c..18f3c7a3205 100644 --- a/src/kv/kv_sql.cpp +++ b/src/kv/kv_sql.cpp @@ -10,7 +10,6 @@ #include "kv/kv_sql.hpp" #include "database/database.hpp" -#include "lib/logging/logger.hpp" #include "kv/value_wrapper_proto.hpp" #include "utils/tools.hpp" diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 55709c59ac3..d24f72347fc 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -1,5 +1,6 @@ target_sources(${PROJECT_NAME}_lib PRIVATE di/soft_singleton.cpp + logging/logger.cpp logging/log_with_spd_log.cpp thread/thread_pool.cpp ) diff --git a/src/lib/di/soft_singleton.hpp b/src/lib/di/soft_singleton.hpp index 12d90aa3bea..b64df1c77b6 100644 --- a/src/lib/di/soft_singleton.hpp +++ b/src/lib/di/soft_singleton.hpp @@ -9,7 +9,6 @@ #pragma once #include -#include "lib/logging/log_with_spd_log.hpp" class SoftSingleton { public: diff --git a/src/lib/logging/log_with_spd_log.cpp b/src/lib/logging/log_with_spd_log.cpp index a1893e3d501..6e6f8a298ca 100644 --- a/src/lib/logging/log_with_spd_log.cpp +++ b/src/lib/logging/log_with_spd_log.cpp @@ -6,8 +6,8 @@ * Contributors: https://github.com/opentibiabr/canary/graphs/contributors * Website: https://docs.opentibiabr.com/ */ -#include +#include #include "lib/di/container.hpp" LogWithSpdLog::LogWithSpdLog() { @@ -23,17 +23,39 @@ Logger &LogWithSpdLog::getInstance() { return inject(); } -void LogWithSpdLog::setLevel(const std::string &name) { +void LogWithSpdLog::setLevel(const std::string &name) const { debug("Setting log level to: {}.", name); - auto level = spdlog::level::from_str(name); + const auto level = spdlog::level::from_str(name); spdlog::set_level(level); } std::string LogWithSpdLog::getLevel() const { - auto level = spdlog::level::to_string_view(spdlog::get_level()); + const auto level = spdlog::level::to_string_view(spdlog::get_level()); return std::string { level.begin(), level.end() }; } -void LogWithSpdLog::log(const std::string &lvl, const fmt::basic_string_view msg) const { - spdlog::log(spdlog::level::from_str(lvl), msg); +void LogWithSpdLog::info(const std::string &msg) const { + SPDLOG_INFO(msg); +} + +void LogWithSpdLog::warn(const std::string &msg) const { + SPDLOG_WARN(msg); } + +void LogWithSpdLog::error(const std::string &msg) const { + SPDLOG_ERROR(msg); +} + +void LogWithSpdLog::critical(const std::string &msg) const { + SPDLOG_CRITICAL(msg); +} + +#if defined(DEBUG_LOG) +void LogWithSpdLog::debug(const std::string &msg) const { + SPDLOG_DEBUG(msg); +} + +void LogWithSpdLog::trace(const std::string &msg) const { + SPDLOG_TRACE(msg); +} +#endif diff --git a/src/lib/logging/log_with_spd_log.hpp b/src/lib/logging/log_with_spd_log.hpp index 983ee716c0d..84dc09a1ea3 100644 --- a/src/lib/logging/log_with_spd_log.hpp +++ b/src/lib/logging/log_with_spd_log.hpp @@ -17,10 +17,37 @@ class LogWithSpdLog final : public Logger { static Logger &getInstance(); - void setLevel(const std::string &name) override; + void setLevel(const std::string &name) const override; std::string getLevel() const override; - void log(const std::string &lvl, fmt::basic_string_view msg) const override; + void info(const std::string &msg) const override; + void warn(const std::string &msg) const override; + void error(const std::string &msg) const override; + void critical(const std::string &msg) const override; + +#if defined(DEBUG_LOG) + void debug(const std::string &msg) const override; + void trace(const std::string &msg) const override; + + template + void debug(const fmt::format_string &fmt, Args &&... args) const { + debug(fmt::format(fmt, std::forward(args)...)); + } + + template + void trace(const fmt::format_string &fmt, Args &&... args) const { + trace(fmt::format(fmt, std::forward(args)...)); + } +#else + void debug(const std::string &) const override { } + void trace(const std::string &) const override { } + + template + void debug(const fmt::format_string &, Args &&...) const { } + + template + void trace(const fmt::format_string &, Args &&...) const { } +#endif }; constexpr auto g_logger = LogWithSpdLog::getInstance; diff --git a/src/lib/logging/logger.cpp b/src/lib/logging/logger.cpp new file mode 100644 index 00000000000..b9a3c889d18 --- /dev/null +++ b/src/lib/logging/logger.cpp @@ -0,0 +1,74 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2024 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#include +#include +#include +#include "lib/di/container.hpp" + +void Logger::setLevel(const std::string &name) const { + debug("Setting log level to: {}.", name); + const auto level = spdlog::level::from_str(name); + spdlog::set_level(level); +} + +std::string Logger::getLevel() const { + const auto level = spdlog::level::to_string_view(spdlog::get_level()); + return std::string { level.begin(), level.end() }; +} + +void Logger::logProfile(const std::string &name, double duration_ms) const { + std::string mutable_name = name; + + std::ranges::replace(mutable_name, ':', '_'); + std::ranges::replace(mutable_name, '\\', '_'); + std::ranges::replace(mutable_name, '/', '_'); + + std::string filename = "log/profile_log-" + mutable_name + ".txt"; + + const auto it = profile_loggers_.find(filename); + if (it == profile_loggers_.end()) { + try { + auto file_sink = std::make_shared(filename, true); + const auto profile_logger = std::make_shared(mutable_name, file_sink); + profile_loggers_[filename] = profile_logger; + profile_logger->info("Function {} executed in {} ms", name, duration_ms); + } catch (const spdlog::spdlog_ex &ex) { + error("Profile log initialization failed: {}", ex.what()); + } + } else { + it->second->info("Function {} executed in {} ms", mutable_name, duration_ms); + } +} + +void Logger::info(const std::string &msg) const { + SPDLOG_INFO(msg); +} + +void Logger::warn(const std::string &msg) const { + SPDLOG_WARN(msg); +} + +void Logger::error(const std::string &msg) const { + SPDLOG_ERROR(msg); +} + +void Logger::critical(const std::string &msg) const { + SPDLOG_CRITICAL(msg); +} + +#if defined(DEBUG_LOG) +void Logger::debug(const std::string &msg) const { + SPDLOG_DEBUG(msg); +} + +void Logger::trace(const std::string &msg) const { + SPDLOG_TRACE(msg); +} +#endif diff --git a/src/lib/logging/logger.hpp b/src/lib/logging/logger.hpp index bc6c455fbde..05c4ba751e5 100644 --- a/src/lib/logging/logger.hpp +++ b/src/lib/logging/logger.hpp @@ -8,34 +8,11 @@ */ #pragma once -#ifndef USE_PRECOMPILED_HEADERS - #include -#endif +#include "utils/transparent_string_hash.hpp" -#define LOG_LEVEL_TRACE \ - std::string { \ - "trace" \ - } -#define LOG_LEVEL_DEBUG \ - std::string { \ - "debug" \ - } -#define LOG_LEVEL_INFO \ - std::string { \ - "info" \ - } -#define LOG_LEVEL_WARNING \ - std::string { \ - "warning" \ - } -#define LOG_LEVEL_ERROR \ - std::string { \ - "error" \ - } -#define LOG_LEVEL_CRITICAL \ - std::string { \ - "critical" \ - } +namespace spdlog { + class logger; +} class Logger { public: @@ -46,67 +23,121 @@ class Logger { Logger(const Logger &) = delete; virtual Logger &operator=(const Logger &) = delete; - virtual void setLevel(const std::string &name) = 0; - [[nodiscard]] virtual std::string getLevel() const = 0; - virtual void log(const std::string &lvl, fmt::basic_string_view msg) const = 0; + virtual void setLevel(const std::string &name) const = 0; + virtual std::string getLevel() const = 0; + + /** + * @brief Logs the execution time of a given operation to a profile log file. + * + * This function records the duration of a named operation in a log file specific + * to that operation. If the log file doesn't exist, it creates a new one. + * The log file name is derived from the provided operation name. + * + * @param name Name of the operation to profile. + * @param duration_ms Execution duration in milliseconds. + * + * Example usage: + * @code + * class ExampleClass { + * public: + * void run() { + * g_logger().profile("quickTask", [this]() { + * quickTask(); + * }); + * } + * + * private: + * void quickTask() { + * std::this_thread::sleep_for(std::chrono::milliseconds(100)); + * } + * }; + * @endcode + */ + void logProfile(const std::string &name, double duration_ms) const; + + virtual void info(const std::string &msg) const; + virtual void warn(const std::string &msg) const; + virtual void error(const std::string &msg) const; + virtual void critical(const std::string &msg) const; + + template + auto profile(const std::string &name, Func func) -> decltype(func()) { + const auto start = std::chrono::high_resolution_clock::now(); + auto result = func(); + const auto end = std::chrono::high_resolution_clock::now(); + + const std::chrono::duration duration = end - start; + logProfile(name, duration.count()); + info("Function {} executed in {} ms", name, duration.count()); + + return result; + } + +#if defined(DEBUG_LOG) + virtual void debug(const std::string &msg) const; template - void trace(const fmt::format_string &fmt, Args &&... args) { - trace(fmt::format(fmt, std::forward(args)...)); + void debug(const fmt::format_string &fmt, Args &&... args) const { + debug(fmt::format(fmt, std::forward(args)...)); } + virtual void trace(const std::string &msg) const; + template - void debug(const fmt::format_string &fmt, Args &&... args) { - debug(fmt::format(fmt, std::forward(args)...)); + void trace(const fmt::format_string &fmt, Args &&... args) const { + trace(fmt::format(fmt, std::forward(args)...)); } +#else + virtual void debug(const std::string &) const { } + + template + void debug(const fmt::format_string &, Args &&...) const { } + + virtual void trace(const std::string &) const { } template - void info(fmt::format_string fmt, Args &&... args) { + void trace(const fmt::format_string &, Args &&...) const { } +#endif + + template + void info(const fmt::format_string &fmt, Args &&... args) const { info(fmt::format(fmt, std::forward(args)...)); } template - void warn(const fmt::format_string &fmt, Args &&... args) { + void warn(const fmt::format_string &fmt, Args &&... args) const { warn(fmt::format(fmt, std::forward(args)...)); } template - void error(const fmt::format_string fmt, Args &&... args) { + void error(const fmt::format_string &fmt, Args &&... args) const { error(fmt::format(fmt, std::forward(args)...)); } template - void critical(const fmt::format_string fmt, Args &&... args) { + void critical(const fmt::format_string &fmt, Args &&... args) const { critical(fmt::format(fmt, std::forward(args)...)); } - template - void trace(const T &msg) { - log(LOG_LEVEL_TRACE, msg); - } +private: + mutable std::unordered_map< + std::string, + std::shared_ptr, + TransparentStringHasher, + std::equal_to<>> + profile_loggers_; - template - void debug(const T &msg) { - log(LOG_LEVEL_DEBUG, msg); - } + std::tm get_local_time() const { + const auto now = std::chrono::system_clock::now(); + std::time_t now_time = std::chrono::system_clock::to_time_t(now); + std::tm local_tm {}; - template - void info(const T &msg) { - log(LOG_LEVEL_INFO, msg); - } - - template - void warn(const T &msg) { - log(LOG_LEVEL_WARNING, msg); - } - - template - void error(const T &msg) { - log(LOG_LEVEL_ERROR, msg); - } +#if defined(_WIN32) || defined(_WIN64) + localtime_s(&local_tm, &now_time); +#else + localtime_r(&now_time, &local_tm); +#endif - template - void critical(const T &msg) { - log(LOG_LEVEL_CRITICAL, msg); + return local_tm; } }; diff --git a/src/lib/thread/thread_pool.hpp b/src/lib/thread/thread_pool.hpp index ea24d3486cb..be5aac0f701 100644 --- a/src/lib/thread/thread_pool.hpp +++ b/src/lib/thread/thread_pool.hpp @@ -8,7 +8,6 @@ */ #pragma once -#include "lib/logging/logger.hpp" #include "BS_thread_pool.hpp" class ThreadPool : public BS::thread_pool { diff --git a/src/lua/scripts/luascript.hpp b/src/lua/scripts/luascript.hpp index 06654c35a21..a376babedde 100644 --- a/src/lua/scripts/luascript.hpp +++ b/src/lua/scripts/luascript.hpp @@ -9,7 +9,6 @@ #pragma once -#include "lib/logging/log_with_spd_log.hpp" #include "lua/functions/lua_functions_loader.hpp" #include "lua/scripts/script_environment.hpp" diff --git a/src/main.cpp b/src/main.cpp index a2a77bd636c..8534bbb6911 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,26 +9,7 @@ #include "canary_server.hpp" #include "lib/di/container.hpp" -// Define um conceito para garantir que a função só aceite contêineres de números -template -concept NumberContainer = requires(T a) { - typename T::value_type; - requires std::integral || std::floating_point; -}; - -// Função que calcula a média de um contêiner de números -auto calculateAverage(const NumberContainer auto &container) { - // Utiliza ranges e std::views para processar o contêiner - return std::accumulate(container.begin(), container.end(), 0.0) / std::ranges::distance(container); -} int main() { - std::vector numbers = { 1, 2, 3, 4, 5 }; - - // Calcula a média usando a função com suporte a C++23 - double average = calculateAverage(numbers); - - std::cout << "Average: " << average << std::endl; - return inject().run(); } diff --git a/src/server/server.hpp b/src/server/server.hpp index 42134f765b0..dfb6aef5cf8 100644 --- a/src/server/server.hpp +++ b/src/server/server.hpp @@ -9,7 +9,6 @@ #pragma once -#include "lib/logging/logger.hpp" #include "lib/metrics/metrics.hpp" #include "server/network/connection/connection.hpp" #include "server/signals.hpp" diff --git a/src/utils/pugicast.cpp b/src/utils/pugicast.cpp index 2269e62b1fb..5791a8383a8 100644 --- a/src/utils/pugicast.cpp +++ b/src/utils/pugicast.cpp @@ -7,8 +7,6 @@ * Website: https://docs.opentibiabr.com/ */ -#include "lib/logging/log_with_spd_log.hpp" - namespace pugi { void logError(const std::string &str) { g_logger().error(str); diff --git a/src/utils/transparent_string_hash.hpp b/src/utils/transparent_string_hash.hpp new file mode 100644 index 00000000000..2092aa2cb98 --- /dev/null +++ b/src/utils/transparent_string_hash.hpp @@ -0,0 +1,24 @@ +/** + * Canary - A free and open-source MMORPG server emulator + * Copyright (©) 2019-2024 OpenTibiaBR + * Repository: https://github.com/opentibiabr/canary + * License: https://github.com/opentibiabr/canary/blob/main/LICENSE + * Contributors: https://github.com/opentibiabr/canary/graphs/contributors + * Website: https://docs.opentibiabr.com/ + */ + +#pragma once + +class TransparentStringHasher { +public: + using is_transparent = void; + size_t operator()(const std::string &key) const noexcept { + return std::hash {}(key); + } + size_t operator()(std::string_view key) const noexcept { + return std::hash {}(key); + } + size_t operator()(const char* key) const noexcept { + return std::hash {}(key); + } +}; diff --git a/tests/fixture/lib/logging/in_memory_logger.hpp b/tests/fixture/lib/logging/in_memory_logger.hpp index 76f0e7307d6..b45af91715e 100644 --- a/tests/fixture/lib/logging/in_memory_logger.hpp +++ b/tests/fixture/lib/logging/in_memory_logger.hpp @@ -51,7 +51,7 @@ class InMemoryLogger : public Logger { return false; } - void setLevel(const std::string &name) override { + void setLevel(const std::string &name) const override { // For the stub, setting a level might not have any behavior. // But you can implement level filtering if you like. } @@ -61,10 +61,34 @@ class InMemoryLogger : public Logger { return "DEBUG"; } - virtual void log(const std::string &lvl, const fmt::basic_string_view msg) const override { - logs.push_back({ lvl, { msg.data(), msg.size() } }); + virtual void info(const std::string &msg) const override { + logs.push_back({ "info", msg }); } + virtual void warn(const std::string &msg) const override { + logs.push_back({ "warning", msg }); + } + + virtual void error(const std::string &msg) const override { + logs.push_back({ "error", msg }); + } + + virtual void critical(const std::string &msg) const override { + logs.push_back({ "critical", msg }); + } + +#if defined(DEBUG_LOG) + virtual void debug(const std::string &msg) const override { + logs.push_back({ "debug", msg }); + } + + virtual void trace(const std::string &msg) const override { + logs.push_back({ "trace", msg }); + } +#else + virtual void debug(const std::string &) const override { } + virtual void trace(const std::string &) const override { } +#endif // Helper methods for testing size_t logCount() const { return logs.size(); diff --git a/vcproj/canary.vcxproj b/vcproj/canary.vcxproj index 135389e491d..7cbdd118ccc 100644 --- a/vcproj/canary.vcxproj +++ b/vcproj/canary.vcxproj @@ -316,6 +316,7 @@ +