From 5418917280c750827e7cd7b6e58014863701cacf Mon Sep 17 00:00:00 2001 From: beats-dh Date: Tue, 20 Aug 2024 01:08:36 -0300 Subject: [PATCH] improve --- src/lib/logging/log_with_spd_log.cpp | 61 ++++++++++++++- src/lib/logging/log_with_spd_log.hpp | 10 +++ src/lib/logging/logger.hpp | 109 ++++++++++++++++++--------- 3 files changed, 140 insertions(+), 40 deletions(-) diff --git a/src/lib/logging/log_with_spd_log.cpp b/src/lib/logging/log_with_spd_log.cpp index f8cfe16946d..f5608733921 100644 --- a/src/lib/logging/log_with_spd_log.cpp +++ b/src/lib/logging/log_with_spd_log.cpp @@ -6,18 +6,47 @@ * 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"); - spdlog::set_pattern("[%Y-%d-%m %H:%M:%S.%e] [%^%l%$] %v "); #ifdef DEBUG_LOG - spdlog::set_pattern("[%Y-%d-%m %H:%M:%S.%e] [thread %t] [%^%l%$] %v "); + 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() { @@ -26,15 +55,39 @@ Logger &LogWithSpdLog::getInstance() { void LogWithSpdLog::setLevel(const std::string &name) { 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); } + +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 983ee716c0d..6d7f102295d 100644 --- a/src/lib/logging/log_with_spd_log.hpp +++ b/src/lib/logging/log_with_spd_log.hpp @@ -10,6 +10,10 @@ #include "lib/logging/logger.hpp" +namespace spdlog { + class logger; // Forward declaration +} + class LogWithSpdLog final : public Logger { public: LogWithSpdLog(); @@ -19,8 +23,14 @@ class LogWithSpdLog final : public Logger { 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.hpp b/src/lib/logging/logger.hpp index bc6c455fbde..a29ebe9c995 100644 --- a/src/lib/logging/logger.hpp +++ b/src/lib/logging/logger.hpp @@ -12,30 +12,12 @@ #include #endif -#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" \ - } +#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" class Logger { public: @@ -50,63 +32,118 @@ class Logger { [[nodiscard]] virtual std::string getLevel() const = 0; virtual void log(const std::string &lvl, fmt::basic_string_view msg) const = 0; + virtual bool shouldLog(const std::string &lvl) const = 0; + virtual void logProfile(const std::string &name, double duration_ms) const = 0; + + 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; + } + + 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; + info("Function {} executed in {} ms", name, duration.count()); + + logProfile(name, duration.count()); + + return result; + } + template void trace(const fmt::format_string &fmt, Args &&... args) { - trace(fmt::format(fmt, std::forward(args)...)); + if (shouldLog(LOG_LEVEL_TRACE)) { + trace(fmt::format(fmt, std::forward(args)...)); + } } template void debug(const fmt::format_string &fmt, Args &&... args) { - debug(fmt::format(fmt, std::forward(args)...)); + if (shouldLog(LOG_LEVEL_DEBUG)) { + debug(fmt::format(fmt, std::forward(args)...)); + } } template void info(fmt::format_string fmt, Args &&... args) { - info(fmt::format(fmt, std::forward(args)...)); + if (shouldLog(LOG_LEVEL_INFO)) { + info(fmt::format(fmt, std::forward(args)...)); + } } template void warn(const fmt::format_string &fmt, Args &&... args) { - warn(fmt::format(fmt, std::forward(args)...)); + if (shouldLog(LOG_LEVEL_WARNING)) { + warn(fmt::format(fmt, std::forward(args)...)); + } } template void error(const fmt::format_string fmt, Args &&... args) { - error(fmt::format(fmt, std::forward(args)...)); + if (shouldLog(LOG_LEVEL_ERROR)) { + error(fmt::format(fmt, std::forward(args)...)); + } } template void critical(const fmt::format_string fmt, Args &&... args) { - critical(fmt::format(fmt, std::forward(args)...)); + if (shouldLog(LOG_LEVEL_CRITICAL)) { + critical(fmt::format(fmt, std::forward(args)...)); + } } template void trace(const T &msg) { - log(LOG_LEVEL_TRACE, msg); + if (shouldLog(LOG_LEVEL_TRACE)) { + log(LOG_LEVEL_TRACE, msg); + } } template void debug(const T &msg) { - log(LOG_LEVEL_DEBUG, msg); + if (shouldLog(LOG_LEVEL_DEBUG)) { + log(LOG_LEVEL_DEBUG, msg); + } } template void info(const T &msg) { - log(LOG_LEVEL_INFO, msg); + if (shouldLog(LOG_LEVEL_INFO)) { + log(LOG_LEVEL_INFO, msg); + } } template void warn(const T &msg) { - log(LOG_LEVEL_WARNING, msg); + if (shouldLog(LOG_LEVEL_WARNING)) { + log(LOG_LEVEL_WARNING, msg); + } } template void error(const T &msg) { - log(LOG_LEVEL_ERROR, msg); + if (shouldLog(LOG_LEVEL_ERROR)) { + log(LOG_LEVEL_ERROR, msg); + } } template void critical(const T &msg) { - log(LOG_LEVEL_CRITICAL, msg); + if (shouldLog(LOG_LEVEL_CRITICAL)) { + log(LOG_LEVEL_CRITICAL, msg); + } } };