From 8baf3250ec81efcc0ad3b978c1d2df97c016dc96 Mon Sep 17 00:00:00 2001 From: beats-dh Date: Thu, 22 Aug 2024 00:46:07 -0300 Subject: [PATCH] improve and fixs --- cmake/modules/BaseConfig.cmake | 1 + config.lua.dist | 3 +- src/account/account.cpp | 1 - src/canary_server.cpp | 2 +- src/config/configmanager.cpp | 2 - src/database/database.hpp | 2 +- src/game/scheduling/task.cpp | 1 - src/lib/CMakeLists.txt | 2 +- src/lib/di/container.hpp | 4 +- src/lib/di/soft_singleton.hpp | 2 +- src/lib/logging/log_with_spd_log.cpp | 93 ----------------- src/lib/logging/log_with_spd_log.hpp | 36 ------- src/lib/logging/logger.cpp | 146 ++++++++++++++++++++++++++ src/lib/logging/logger.hpp | 149 ++++++++++----------------- src/lua/scripts/luascript.hpp | 2 +- src/pch.hpp | 2 +- src/utils/pugicast.cpp | 1 - 17 files changed, 212 insertions(+), 237 deletions(-) create mode 100644 src/lib/logging/logger.cpp diff --git a/cmake/modules/BaseConfig.cmake b/cmake/modules/BaseConfig.cmake index f61ee9e809c..122a955cae7 100644 --- a/cmake/modules/BaseConfig.cmake +++ b/cmake/modules/BaseConfig.cmake @@ -92,6 +92,7 @@ endif(OPTIONS_ENABLE_OPENMP) # 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 89bd3e68fc3..e52fabe70b4 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -10,6 +10,7 @@ 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: 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 2e5f58dd864..942b7b35789 100644 --- a/src/account/account.cpp +++ b/src/account/account.cpp @@ -16,7 +16,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/canary_server.cpp b/src/canary_server.cpp index e49a86d7d9f..e9b718f7e0f 100644 --- a/src/canary_server.cpp +++ b/src/canary_server.cpp @@ -205,7 +205,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 6390d0699b3..4c490ea2397 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -37,9 +37,7 @@ 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) diff --git a/src/database/database.hpp b/src/database/database.hpp index 2a27c30159b..5c0f8f9739a 100644 --- a/src/database/database.hpp +++ b/src/database/database.hpp @@ -10,7 +10,7 @@ #pragma once #include "declarations.hpp" -#include "lib/logging/log_with_spd_log.hpp" +#include "lib/logging/logger.hpp" #ifndef USE_PRECOMPILED_HEADERS #include diff --git a/src/game/scheduling/task.cpp b/src/game/scheduling/task.cpp index 96355968bd1..c7c4c990047 100644 --- a/src/game/scheduling/task.cpp +++ b/src/game/scheduling/task.cpp @@ -11,7 +11,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/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 55709c59ac3..86d49d5e6fb 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -1,6 +1,6 @@ target_sources(${PROJECT_NAME}_lib PRIVATE di/soft_singleton.cpp - logging/log_with_spd_log.cpp + logging/logger.cpp thread/thread_pool.cpp ) diff --git a/src/lib/di/container.hpp b/src/lib/di/container.hpp index 3c15e30b3d9..eb034af34ef 100644 --- a/src/lib/di/container.hpp +++ b/src/lib/di/container.hpp @@ -10,7 +10,7 @@ #include "account/account_repository_db.hpp" #include "lib/di/injector.hpp" -#include "lib/logging/log_with_spd_log.hpp" +#include "lib/logging/logger.hpp" #include "kv/kv_sql.hpp" namespace di = boost::di; @@ -21,7 +21,7 @@ class DI final { const inline static auto defaultContainer = di::make_injector( di::bind().to().in(di::singleton), di::bind().to().in(di::singleton), - di::bind().to().in(di::singleton) + di::bind().to().in(di::singleton) ); public: diff --git a/src/lib/di/soft_singleton.hpp b/src/lib/di/soft_singleton.hpp index 12d90aa3bea..ceb7d31d386 100644 --- a/src/lib/di/soft_singleton.hpp +++ b/src/lib/di/soft_singleton.hpp @@ -9,7 +9,7 @@ #pragma once #include -#include "lib/logging/log_with_spd_log.hpp" +#include "lib/logging/logger.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 f5608733921..e69de29bb2d 100644 --- a/src/lib/logging/log_with_spd_log.cpp +++ b/src/lib/logging/log_with_spd_log.cpp @@ -1,93 +0,0 @@ -/** - * 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 "pch.hpp" -#include "lib/di/container.hpp" - -LogWithSpdLog::LogWithSpdLog() { - setLevel("info"); - -#ifdef DEBUG_LOG - spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [thread %t] [%^%l%$] %v "); -#else - spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v "); -#endif - - const std::tm local_tm = get_local_time(); - - std::ostringstream oss; - oss << std::put_time(&local_tm, "%Y-%m-%d_%H-%M-%S"); - std::string filename = "log/server_log_" + oss.str() + ".txt"; - - try { - auto console_sink = std::make_shared(); - auto file_sink = std::make_shared(filename, true); - - const auto combined_logger = std::make_shared( - "", - spdlog::sinks_init_list { console_sink, file_sink } - ); - - combined_logger->set_level(spdlog::get_level()); - combined_logger->flush_on(spdlog::level::info); - - set_default_logger(combined_logger); - - spdlog::info("Logger initialized and configured for console and file output."); - } catch (const spdlog::spdlog_ex &ex) { - std::cerr << "Log initialization failed: " << ex.what() << std::endl; - } -} - -Logger &LogWithSpdLog::getInstance() { - return inject(); -} - -void LogWithSpdLog::setLevel(const std::string &name) { - debug("Setting log level to: {}.", name); - const auto level = spdlog::level::from_str(name); - spdlog::set_level(level); -} - -std::string LogWithSpdLog::getLevel() const { - 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); -} - -bool LogWithSpdLog::shouldLog(const std::string &lvl) const { - const auto currentLevel = spdlog::get_level(); - const auto messageLevel = spdlog::level::from_str(lvl); - return messageLevel >= currentLevel; -} - -void LogWithSpdLog::logProfile(const std::string &name, double duration_ms) const { - std::string filename = "log/profile_log-" + name + ".txt"; - - const auto it = profile_loggers_.find(filename); - if (it == profile_loggers_.end()) { - try { - auto file_sink = std::make_shared(filename, true); - auto profile_logger = std::make_shared("profile_logger_" + name, file_sink); - profile_loggers_[filename] = profile_logger; - profile_logger->info("Function {} executed in {} ms", name, duration_ms); - } catch (const spdlog::spdlog_ex &ex) { - std::cerr << "Profile log initialization failed: " << ex.what() << std::endl; - } - } else { - it->second->info("Function {} executed in {} ms", name, duration_ms); - } -} diff --git a/src/lib/logging/log_with_spd_log.hpp b/src/lib/logging/log_with_spd_log.hpp index 6d7f102295d..e69de29bb2d 100644 --- a/src/lib/logging/log_with_spd_log.hpp +++ b/src/lib/logging/log_with_spd_log.hpp @@ -1,36 +0,0 @@ -/** - * 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 - -#include "lib/logging/logger.hpp" - -namespace spdlog { - class logger; // Forward declaration -} - -class LogWithSpdLog final : public Logger { -public: - LogWithSpdLog(); - ~LogWithSpdLog() override = default; - - static Logger &getInstance(); - - void setLevel(const std::string &name) override; - std::string getLevel() const override; - bool shouldLog(const std::string &lvl) const override; - void logProfile(const std::string &name, double duration_ms) const override; - void setupLogger() const; - - void log(const std::string &lvl, fmt::basic_string_view msg) const override; - -private: - mutable std::unordered_map> profile_loggers_; -}; - -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..3d3587efa16 --- /dev/null +++ b/src/lib/logging/logger.cpp @@ -0,0 +1,146 @@ +/** + * 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 "pch.hpp" +#include "lib/di/container.hpp" + +Logger::Logger() { + spdlog::set_pattern("[%Y-%d-%m %H:%M:%S.%e] [%^%l%$] %v "); + +#ifdef DEBUG_LOG + spdlog::set_level(spdlog::level::trace); + spdlog::set_pattern("[%Y-%d-%m %H:%M:%S.%e] [thread %t] [%^%l%$] %v "); +#endif + + const std::tm local_tm = get_local_time(); + + std::ostringstream oss; + oss << std::put_time(&local_tm, "%Y-%m-%d_%H-%M-%S"); + std::string filename = "log/server_log_" + oss.str() + ".txt"; + + try { + // Limpar logs antigos + cleanOldLogs("log", 2); + + auto console_sink = std::make_shared(); + auto file_sink = std::make_shared(filename, true); + + const auto combined_logger = std::make_shared( + "", + spdlog::sinks_init_list { console_sink, file_sink } + ); + + combined_logger->set_level(spdlog::get_level()); + + combined_logger->set_pattern("[%Y-%d-%m %H:%M:%S.%e] [%^%l%$] %v "); + +#ifdef DEBUG_LOG + combined_logger->set_pattern("[%Y-%d-%m %H:%M:%S.%e] [thread %t] [%^%l%$] %v "); +#endif + + combined_logger->flush_on(spdlog::level::info); + + set_default_logger(combined_logger); + + info("Logger initialized and configured for console and file output."); + } catch (const spdlog::spdlog_ex &ex) { + std::cerr << "Log initialization failed: " << ex.what() << std::endl; + } +} + +Logger &Logger::getInstance() { + return inject(); +} + +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); + } +} + +// Função para limpar logs antigos +void Logger::cleanOldLogs(const std::string &logDirectory, int days) const { + namespace fs = std::filesystem; + + const auto days_duration = std::chrono::hours(days * 24); + + for (const auto &entry : fs::directory_iterator(logDirectory)) { + if (entry.is_regular_file()) { + auto ftime = fs::last_write_time(entry); + + if (decltype(ftime)::clock::now() - ftime > days_duration) { + try { + fs::remove(entry.path()); + debug("Deleted old log file: {}", entry.path().string()); + } catch (const std::exception &e) { + debug("Failed to delete old log file: {}", entry.path().string()); + } + } + } + } +} + +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_WARN(msg); +} + +void Logger::critical(const std::string &msg) const { + SPDLOG_WARN(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 a29ebe9c995..7eca1ec201e 100644 --- a/src/lib/logging/logger.hpp +++ b/src/lib/logging/logger.hpp @@ -8,46 +8,27 @@ */ #pragma once -#ifndef USE_PRECOMPILED_HEADERS - #include -#endif - -#define LOG_LEVEL_TRACE "trace" -#define LOG_LEVEL_DEBUG "debug" -#define LOG_LEVEL_INFO "info" -#define LOG_LEVEL_WARNING "warning" -#define LOG_LEVEL_ERROR "error" -#define LOG_LEVEL_CRITICAL "critical" +namespace spdlog { + class logger; // Forward declaration da classe logger +} class Logger { public: - Logger() = default; - virtual ~Logger() = default; + Logger(); + ~Logger() = default; - // Ensures that we don't accidentally copy it - Logger(const Logger &) = delete; - virtual Logger &operator=(const Logger &) = delete; + static Logger &getInstance(); - 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; + void setLevel(const std::string &name) const; + std::string getLevel() const; - virtual bool shouldLog(const std::string &lvl) const = 0; - virtual void logProfile(const std::string &name, double duration_ms) const = 0; + void logProfile(const std::string &name, double duration_ms) const; + void cleanOldLogs(const std::string &logDirectory, int days) const; - 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 {}; - -#if defined(_WIN32) || defined(_WIN64) - localtime_s(&local_tm, &now_time); -#else - localtime_r(&now_time, &local_tm); -#endif - - return local_tm; - } + void info(const std::string &msg) const; + void warn(const std::string &msg) const; + void error(const std::string &msg) const; + void critical(const std::string &msg) const; template auto profile(const std::string &name, Func func) -> decltype(func()) { @@ -56,94 +37,74 @@ class Logger { const auto end = std::chrono::high_resolution_clock::now(); const std::chrono::duration duration = end - start; - info("Function {} executed in {} ms", name, duration.count()); - logProfile(name, duration.count()); + info("Function {} executed in {} ms", name, duration.count()); return result; } +#if defined(DEBUG_LOG) + void debug(const std::string &msg) const; + template - void trace(const fmt::format_string &fmt, Args &&... args) { - if (shouldLog(LOG_LEVEL_TRACE)) { - trace(fmt::format(fmt, std::forward(args)...)); - } + void debug(const fmt::format_string &fmt, Args &&... args) const { + debug(fmt::format(fmt, std::forward(args)...)); } + void trace(const std::string &msg) const; + template - void debug(const fmt::format_string &fmt, Args &&... args) { - if (shouldLog(LOG_LEVEL_DEBUG)) { - 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 + void debug(const std::string &) const { } template - void info(fmt::format_string fmt, Args &&... args) { - if (shouldLog(LOG_LEVEL_INFO)) { - info(fmt::format(fmt, std::forward(args)...)); - } - } + void debug(const fmt::format_string &, Args &&...) const { } + + void trace(const std::string &) const { } template - void warn(const fmt::format_string &fmt, Args &&... args) { - if (shouldLog(LOG_LEVEL_WARNING)) { - warn(fmt::format(fmt, std::forward(args)...)); - } - } + void trace(const fmt::format_string &, Args &&...) const { } +#endif template - void error(const fmt::format_string fmt, Args &&... args) { - if (shouldLog(LOG_LEVEL_ERROR)) { - error(fmt::format(fmt, std::forward(args)...)); - } + void info(const fmt::format_string &fmt, Args &&... args) const { + info(fmt::format(fmt, std::forward(args)...)); } template - void critical(const fmt::format_string fmt, Args &&... args) { - if (shouldLog(LOG_LEVEL_CRITICAL)) { - critical(fmt::format(fmt, std::forward(args)...)); - } + void warn(const fmt::format_string &fmt, Args &&... args) const { + warn(fmt::format(fmt, std::forward(args)...)); } - template - void trace(const T &msg) { - if (shouldLog(LOG_LEVEL_TRACE)) { - log(LOG_LEVEL_TRACE, msg); - } + template + void error(const fmt::format_string &fmt, Args &&... args) const { + error(fmt::format(fmt, std::forward(args)...)); } - template - void debug(const T &msg) { - if (shouldLog(LOG_LEVEL_DEBUG)) { - log(LOG_LEVEL_DEBUG, msg); - } + template + void critical(const fmt::format_string &fmt, Args &&... args) const { + critical(fmt::format(fmt, std::forward(args)...)); } - template - void info(const T &msg) { - if (shouldLog(LOG_LEVEL_INFO)) { - log(LOG_LEVEL_INFO, msg); - } - } +private: + mutable std::unordered_map> profile_loggers_; - template - void warn(const T &msg) { - if (shouldLog(LOG_LEVEL_WARNING)) { - log(LOG_LEVEL_WARNING, 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 error(const T &msg) { - if (shouldLog(LOG_LEVEL_ERROR)) { - 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) { - if (shouldLog(LOG_LEVEL_CRITICAL)) { - log(LOG_LEVEL_CRITICAL, msg); - } + return local_tm; } }; + +constexpr auto g_logger = Logger::getInstance; diff --git a/src/lua/scripts/luascript.hpp b/src/lua/scripts/luascript.hpp index 06654c35a21..990ef08efbb 100644 --- a/src/lua/scripts/luascript.hpp +++ b/src/lua/scripts/luascript.hpp @@ -9,7 +9,7 @@ #pragma once -#include "lib/logging/log_with_spd_log.hpp" +#include "lib/logging/logger.hpp" #include "lua/functions/lua_functions_loader.hpp" #include "lua/scripts/script_environment.hpp" diff --git a/src/pch.hpp b/src/pch.hpp index e69c27016a4..598daef673f 100644 --- a/src/pch.hpp +++ b/src/pch.hpp @@ -164,7 +164,7 @@ struct fmt::formatter, char>> : formatter< #include "lib/messaging/message.hpp" #include "lib/messaging/command.hpp" #include "lib/messaging/event.hpp" -#include "lib/logging/log_with_spd_log.hpp" +#include "lib/logging/logger.hpp" #include #include diff --git a/src/utils/pugicast.cpp b/src/utils/pugicast.cpp index 62717c33621..d7365e40590 100644 --- a/src/utils/pugicast.cpp +++ b/src/utils/pugicast.cpp @@ -7,7 +7,6 @@ * Website: https://docs.opentibiabr.com/ */ #include "pch.hpp" -#include "lib/logging/log_with_spd_log.hpp" namespace pugi { void logError(const std::string &str) {