From f5fdeee92cc4f1e3735ca9d183df87274f36aa89 Mon Sep 17 00:00:00 2001 From: Felipe Muniz Date: Sat, 30 Nov 2024 03:44:18 -0300 Subject: [PATCH 1/3] feat: add support to graylog --- src/canary_server.cpp | 12 ++++ src/config/config_enums.hpp | 7 +- src/config/configmanager.cpp | 6 ++ src/lib/logging/gray_log_sink.hpp | 82 +++++++++++++++++++++++ src/lib/logging/gray_log_sink_options.hpp | 18 +++++ src/lib/logging/log_with_spd_log.cpp | 21 ++++++ src/lib/logging/log_with_spd_log.hpp | 2 + src/lib/logging/logger.hpp | 2 + vcproj/canary.vcxproj | 3 + 9 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 src/lib/logging/gray_log_sink.hpp create mode 100644 src/lib/logging/gray_log_sink_options.hpp diff --git a/src/canary_server.cpp b/src/canary_server.cpp index 8dfbcfc954c..492dce2b5f8 100644 --- a/src/canary_server.cpp +++ b/src/canary_server.cpp @@ -33,6 +33,7 @@ #include "server/network/protocol/protocolstatus.hpp" #include "server/network/webhook/webhook.hpp" #include "creatures/players/vocations/vocation.hpp" +#include CanaryServer::CanaryServer( Logger &logger, @@ -137,6 +138,17 @@ int CanaryServer::run() { logger.info("{} {}", g_configManager().getString(SERVER_NAME), "server online!"); g_logger().setLevel(g_configManager().getString(LOGLEVEL)); + if (g_configManager().getBoolean(GRAYLOG_ENABLED)) { + GrayLogSinkOptions options { + g_configManager().getString(GRAYLOG_HOSTNAME_OR_ADDRESS), + g_configManager().getString(GRAYLOG_SOURCE), + g_configManager().getString(GRAYLOG_LEVEL), + g_configManager().getNumber(GRAYLOG_PORT) + }; + + g_logger().enableGraylogSink(options); + } + serviceManager.run(); shutdown(); diff --git a/src/config/config_enums.hpp b/src/config/config_enums.hpp index 559045fdb9b..37fd2120489 100644 --- a/src/config/config_enums.hpp +++ b/src/config/config_enums.hpp @@ -325,5 +325,10 @@ enum ConfigKey_t : uint16_t { WHEEL_POINTS_PER_LEVEL, WHITE_SKULL_TIME, WORLD_TYPE, - XP_DISPLAY_MODE + XP_DISPLAY_MODE, + GRAYLOG_ENABLED, + GRAYLOG_HOSTNAME_OR_ADDRESS, + GRAYLOG_SOURCE, + GRAYLOG_PORT, + GRAYLOG_LEVEL }; diff --git a/src/config/configmanager.cpp b/src/config/configmanager.cpp index 1c00df76c2f..9bede0dab49 100644 --- a/src/config/configmanager.cpp +++ b/src/config/configmanager.cpp @@ -363,6 +363,12 @@ bool ConfigManager::load() { loadStringConfig(L, WORLD_TYPE, "worldType", "pvp"); loadStringConfig(L, LOGLEVEL, "logLevel", "info"); + loadBoolConfig(L, GRAYLOG_ENABLED, "graylogEnabled", false); + loadStringConfig(L, GRAYLOG_HOSTNAME_OR_ADDRESS, "graylogHostNameOrAddress", "127.0.0.1"); + loadStringConfig(L, GRAYLOG_SOURCE, "graylogSource", "Canary"); + loadStringConfig(L, GRAYLOG_LEVEL, "graylogLevel", "info"); + loadIntConfig(L, GRAYLOG_PORT, "graylogPort", 12201); + loaded = true; lua_close(L); return true; diff --git a/src/lib/logging/gray_log_sink.hpp b/src/lib/logging/gray_log_sink.hpp new file mode 100644 index 00000000000..7717d30a230 --- /dev/null +++ b/src/lib/logging/gray_log_sink.hpp @@ -0,0 +1,82 @@ +/** + * 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 +#include +#include +#include +#include +#include "gray_log_sink_options.hpp" + +class GrayLogSink : public spdlog::sinks::base_sink { +public: + GrayLogSink(const GrayLogSinkOptions &options) : + _io_context(), + _socket(_io_context, asio::ip::udp::v4()), + _endpoint(asio::ip::make_address(options.hostNameOrAddress), options.port), + _options(options) { } + +protected: + void sink_it_(const spdlog::details::log_msg &msg) override { + try { + + if (spdlog::level::from_str(_options.level) > msg.level) { + return; + } + + nlohmann::json gelf_message; + gelf_message["version"] = "1.0"; + gelf_message["host"] = _options.source; + gelf_message["short_message"] = std::string(msg.payload.begin(), msg.payload.end()); + + auto now = std::chrono::system_clock::now(); + auto duration = now.time_since_epoch(); + double timestamp = std::chrono::duration_cast(duration).count() + (std::chrono::duration_cast(duration).count() % 1000000) / 1e6; + + gelf_message["timestamp"] = timestamp; + gelf_message["level"] = mapLogLevel(msg.level); + + std::string serialized_message = gelf_message.dump(); + + _socket.send_to(asio::buffer(serialized_message), _endpoint); + } catch (const std::exception &ex) { + std::cerr << "Graylog sink send message error: " << ex.what() << std::endl; + } + } + + void flush_() override { + } + +private: + asio::io_context _io_context; + asio::ip::udp::socket _socket; + asio::ip::udp::endpoint _endpoint; + GrayLogSinkOptions _options; + + int mapLogLevel(spdlog::level::level_enum level) { + switch (level) { + case spdlog::level::trace: + return 7; // Debug + case spdlog::level::debug: + return 7; // Debug + case spdlog::level::info: + return 6; // Informational + case spdlog::level::warn: + return 4; // Warning + case spdlog::level::err: + return 3; // Error + case spdlog::level::critical: + return 2; // Critical + default: + return 1; // Alert + } + } +}; diff --git a/src/lib/logging/gray_log_sink_options.hpp b/src/lib/logging/gray_log_sink_options.hpp new file mode 100644 index 00000000000..cead24dde2e --- /dev/null +++ b/src/lib/logging/gray_log_sink_options.hpp @@ -0,0 +1,18 @@ +/** + * 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 + +struct GrayLogSinkOptions { + const std::string hostNameOrAddress; + const std::string source; + const std::string level; + short port; +}; diff --git a/src/lib/logging/log_with_spd_log.cpp b/src/lib/logging/log_with_spd_log.cpp index 6e6f8a298ca..fbb05796eb6 100644 --- a/src/lib/logging/log_with_spd_log.cpp +++ b/src/lib/logging/log_with_spd_log.cpp @@ -9,6 +9,9 @@ #include #include "lib/di/container.hpp" +#include +#include "gray_log_sink_options.hpp" +#include "gray_log_sink.hpp" LogWithSpdLog::LogWithSpdLog() { setLevel("info"); @@ -50,6 +53,24 @@ void LogWithSpdLog::critical(const std::string &msg) const { SPDLOG_CRITICAL(msg); } +void LogWithSpdLog::enableGraylogSink(const GrayLogSinkOptions options) const { + + // Criação do sink do console (já existente no logger padrão) + auto console_sink = std::make_shared(); + + // Criação do sink Graylog + auto graylog_sink = std::make_shared(options); + + // Combinar os dois sinks em um logger + auto combined_logger = std::make_shared( + "", + spdlog::sinks_init_list { console_sink, graylog_sink } + ); + + // Registrar o logger combinado como o logger padrão + spdlog::set_default_logger(combined_logger); +} + #if defined(DEBUG_LOG) void LogWithSpdLog::debug(const std::string &msg) const { SPDLOG_DEBUG(msg); diff --git a/src/lib/logging/log_with_spd_log.hpp b/src/lib/logging/log_with_spd_log.hpp index 84dc09a1ea3..648bd75fd2b 100644 --- a/src/lib/logging/log_with_spd_log.hpp +++ b/src/lib/logging/log_with_spd_log.hpp @@ -25,6 +25,8 @@ class LogWithSpdLog final : public Logger { void error(const std::string &msg) const override; void critical(const std::string &msg) const override; + void enableGraylogSink(const GrayLogSinkOptions options) const override; + #if defined(DEBUG_LOG) void debug(const std::string &msg) const override; void trace(const std::string &msg) const override; diff --git a/src/lib/logging/logger.hpp b/src/lib/logging/logger.hpp index 05c4ba751e5..eb70c2fc974 100644 --- a/src/lib/logging/logger.hpp +++ b/src/lib/logging/logger.hpp @@ -9,6 +9,7 @@ #pragma once #include "utils/transparent_string_hash.hpp" +#include "gray_log_sink_options.hpp" namespace spdlog { class logger; @@ -25,6 +26,7 @@ class Logger { virtual void setLevel(const std::string &name) const = 0; virtual std::string getLevel() const = 0; + virtual void enableGraylogSink(const GrayLogSinkOptions options) const = 0; /** * @brief Logs the execution time of a given operation to a profile log file. diff --git a/vcproj/canary.vcxproj b/vcproj/canary.vcxproj index 6436dd704a9..6888dae9b67 100644 --- a/vcproj/canary.vcxproj +++ b/vcproj/canary.vcxproj @@ -112,6 +112,8 @@ + + @@ -315,6 +317,7 @@ + From ef623ce424ae8ba747a561ec7384e231ad5e25a1 Mon Sep 17 00:00:00 2001 From: Felipe Muniz Date: Sat, 30 Nov 2024 03:45:06 -0300 Subject: [PATCH 2/3] fix: add missing variables on config.lua --- config.lua.dist | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/config.lua.dist b/config.lua.dist index 7d0360d9360..27d33c82d3c 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -588,3 +588,11 @@ metricsPrometheusAddress = "0.0.0.0:9464" --- OStream metricsEnableOstream = false metricsOstreamInterval = 1000 + +-- Graylog +-- NOTE set graylogLevel: trace, debug, info, warning, error, critical, off (default: info). +graylogEnabled = true +graylogHostNameOrAddress = "10.94.50.11" +graylogSource = "Canary Localhost" +graylogPort = 12201 +graylogLevel = "trace" \ No newline at end of file From a809760a6d32efbaf48cfb317062ffb110115bc9 Mon Sep 17 00:00:00 2001 From: Felipe Muniz Date: Sat, 30 Nov 2024 03:56:54 -0300 Subject: [PATCH 3/3] fix: adjustments on default values --- config.lua.dist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.lua.dist b/config.lua.dist index 27d33c82d3c..20b4806940e 100644 --- a/config.lua.dist +++ b/config.lua.dist @@ -592,7 +592,7 @@ metricsOstreamInterval = 1000 -- Graylog -- NOTE set graylogLevel: trace, debug, info, warning, error, critical, off (default: info). graylogEnabled = true -graylogHostNameOrAddress = "10.94.50.11" -graylogSource = "Canary Localhost" +graylogHostNameOrAddress = "127.0.0.1" +graylogSource = "Canary" graylogPort = 12201 graylogLevel = "trace" \ No newline at end of file