From 6d9ff7e404a22ed1cc7e529cfa77ef7d593d9547 Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Tue, 6 May 2025 16:50:57 +0200 Subject: add sentry for zen command (#373) * refactor sentry integration and add to zen command line tool * move add_ldflags("-framework Security") --- src/zenserver/sentryintegration.cpp | 324 ------------------------------------ 1 file changed, 324 deletions(-) delete mode 100644 src/zenserver/sentryintegration.cpp (limited to 'src/zenserver/sentryintegration.cpp') diff --git a/src/zenserver/sentryintegration.cpp b/src/zenserver/sentryintegration.cpp deleted file mode 100644 index 7996f25bb..000000000 --- a/src/zenserver/sentryintegration.cpp +++ /dev/null @@ -1,324 +0,0 @@ -// Copyright Epic Games, Inc. All Rights Reserved. - -#include "sentryintegration.h" - -#include -#include -#include -#include - -#include -#include - -#if ZEN_PLATFORM_LINUX -# include -#endif - -#if ZEN_PLATFORM_MAC -# include -#endif - -ZEN_THIRD_PARTY_INCLUDES_START -#include -ZEN_THIRD_PARTY_INCLUDES_END - -#if ZEN_USE_SENTRY -# define SENTRY_BUILD_STATIC 1 -ZEN_THIRD_PARTY_INCLUDES_START -# include -# include -ZEN_THIRD_PARTY_INCLUDES_END - -namespace sentry { - -struct SentryAssertImpl : zen::AssertImpl -{ - virtual void ZEN_FORCENOINLINE ZEN_DEBUG_SECTION - OnAssert(const char* Filename, int LineNumber, const char* FunctionName, const char* Msg, zen::CallstackFrames* Callstack) override; -}; - -class sentry_sink final : public spdlog::sinks::base_sink -{ -public: - sentry_sink(); - ~sentry_sink(); - -protected: - void sink_it_(const spdlog::details::log_msg& msg) override; - void flush_() override; -}; - -////////////////////////////////////////////////////////////////////////// - -static constexpr sentry_level_t MapToSentryLevel[spdlog::level::level_enum::n_levels] = {SENTRY_LEVEL_DEBUG, - SENTRY_LEVEL_DEBUG, - SENTRY_LEVEL_INFO, - SENTRY_LEVEL_WARNING, - SENTRY_LEVEL_ERROR, - SENTRY_LEVEL_FATAL, - SENTRY_LEVEL_DEBUG}; - -sentry_sink::sentry_sink() -{ -} -sentry_sink::~sentry_sink() -{ -} - -void -sentry_sink::sink_it_(const spdlog::details::log_msg& msg) -{ - if (msg.level != spdlog::level::err && msg.level != spdlog::level::critical) - { - return; - } - try - { - std::string Message = fmt::format("{}\n{}({}) [{}]", msg.payload, msg.source.filename, msg.source.line, msg.source.funcname); - sentry_value_t event = sentry_value_new_message_event( - /* level */ MapToSentryLevel[msg.level], - /* logger */ nullptr, - /* message */ Message.c_str()); - sentry_event_value_add_stacktrace(event, NULL, 0); - sentry_capture_event(event); - } - catch (const std::exception&) - { - // If our logging with Message formatting fails we do a non-allocating version and just post the msg.payload raw - char TmpBuffer[256]; - size_t MaxCopy = zen::Min(msg.payload.size(), size_t(255)); - memcpy(TmpBuffer, msg.payload.data(), MaxCopy); - TmpBuffer[MaxCopy] = '\0'; - sentry_value_t event = sentry_value_new_message_event( - /* level */ SENTRY_LEVEL_ERROR, - /* logger */ nullptr, - /* message */ TmpBuffer); - sentry_event_value_add_stacktrace(event, NULL, 0); - sentry_capture_event(event); - } -} -void -sentry_sink::flush_() -{ -} - -void -SentryAssertImpl::OnAssert(const char* Filename, int LineNumber, const char* FunctionName, const char* Msg, zen::CallstackFrames* Callstack) -{ - // Sentry will provide its own callstack - ZEN_UNUSED(Callstack); - try - { - std::string Message = fmt::format("ASSERT {}:({}) [{}]\n\"{}\"", Filename, LineNumber, FunctionName, Msg); - sentry_value_t event = sentry_value_new_message_event( - /* level */ SENTRY_LEVEL_ERROR, - /* logger */ nullptr, - /* message */ Message.c_str()); - sentry_event_value_add_stacktrace(event, NULL, 0); - sentry_capture_event(event); - } - catch (const std::exception&) - { - // If our logging with Message formatting fails we do a non-allocating version and just post the Msg raw - sentry_value_t event = sentry_value_new_message_event( - /* level */ SENTRY_LEVEL_ERROR, - /* logger */ nullptr, - /* message */ Msg); - sentry_event_value_add_stacktrace(event, NULL, 0); - sentry_capture_event(event); - } -} - -} // namespace sentry - -namespace zen { - -# if ZEN_USE_SENTRY -static void -SentryLogFunction(sentry_level_t Level, const char* Message, va_list Args, [[maybe_unused]] void* Userdata) -{ - char LogMessageBuffer[160]; - std::string LogMessage; - const char* MessagePtr = LogMessageBuffer; - - int n = vsnprintf(LogMessageBuffer, sizeof LogMessageBuffer, Message, Args); - - if (n >= int(sizeof LogMessageBuffer)) - { - LogMessage.resize(n + 1); - - n = vsnprintf(LogMessage.data(), LogMessage.size(), Message, Args); - - MessagePtr = LogMessage.c_str(); - } - - switch (Level) - { - case SENTRY_LEVEL_DEBUG: - ZEN_CONSOLE_DEBUG("sentry: {}", MessagePtr); - break; - - case SENTRY_LEVEL_INFO: - ZEN_CONSOLE_INFO("sentry: {}", MessagePtr); - break; - - case SENTRY_LEVEL_WARNING: - ZEN_CONSOLE_WARN("sentry: {}", MessagePtr); - break; - - case SENTRY_LEVEL_ERROR: - ZEN_CONSOLE_ERROR("sentry: {}", MessagePtr); - break; - - case SENTRY_LEVEL_FATAL: - ZEN_CONSOLE_CRITICAL("sentry: {}", MessagePtr); - break; - } -} -# endif - -SentryIntegration::SentryIntegration() -{ -} - -SentryIntegration::~SentryIntegration() -{ - if (m_IsInitialized && m_SentryErrorCode == 0) - { - logging::SetErrorLog(""); - m_SentryAssert.reset(); - sentry_close(); - } -} - -void -SentryIntegration::Initialize(std::string SentryDatabasePath, - std::string SentryAttachmentsPath, - bool AllowPII, - const std::string& CommandLine) -{ - m_AllowPII = AllowPII; - - if (SentryDatabasePath.starts_with("\\\\?\\")) - { - SentryDatabasePath = SentryDatabasePath.substr(4); - } - sentry_options_t* SentryOptions = sentry_options_new(); - sentry_options_set_dsn(SentryOptions, "https://8ba3441bebc941c1ae24b8cd2fd25d55@o10593.ingest.sentry.io/5919284"); - sentry_options_set_database_path(SentryOptions, SentryDatabasePath.c_str()); - sentry_options_set_logger(SentryOptions, SentryLogFunction, this); - if (SentryAttachmentsPath.starts_with("\\\\?\\")) - { - SentryAttachmentsPath = SentryAttachmentsPath.substr(4); - } - sentry_options_add_attachment(SentryOptions, SentryAttachmentsPath.c_str()); - sentry_options_set_release(SentryOptions, ZEN_CFG_VERSION); - - // sentry_options_set_debug(SentryOptions, 1); - - m_SentryErrorCode = sentry_init(SentryOptions); - - if (m_SentryErrorCode == 0) - { - sentry_value_t SentryUserObject = sentry_value_new_object(); - - if (m_AllowPII) - { -# if ZEN_PLATFORM_WINDOWS - CHAR Buffer[511 + 1]; - DWORD BufferLength = sizeof(Buffer) / sizeof(CHAR); - BOOL OK = GetUserNameA(Buffer, &BufferLength); - if (OK && BufferLength) - { - m_SentryUserName = std::string(Buffer, BufferLength - 1); - } - BufferLength = sizeof(Buffer) / sizeof(CHAR); - OK = GetComputerNameA(Buffer, &BufferLength); - if (OK && BufferLength) - { - m_SentryHostName = std::string(Buffer, BufferLength); - } - else - { - m_SentryHostName = "unknown"; - } -# endif // ZEN_PLATFORM_WINDOWS - -# if (ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC) - uid_t uid = geteuid(); - struct passwd* pw = getpwuid(uid); - if (pw) - { - m_SentryUserName = std::string(pw->pw_name); - } - else - { - m_SentryUserName = "unknown"; - } - char HostNameBuffer[1023 + 1]; - int err = gethostname(HostNameBuffer, sizeof(HostNameBuffer)); - if (err == 0) - { - m_SentryHostName = std::string(HostNameBuffer); - } - else - { - m_SentryHostName = "unknown"; - } -# endif - m_SentryId = fmt::format("{}@{}", m_SentryUserName, m_SentryHostName); - sentry_value_set_by_key(SentryUserObject, "id", sentry_value_new_string(m_SentryId.c_str())); - sentry_value_set_by_key(SentryUserObject, "username", sentry_value_new_string(m_SentryUserName.c_str())); - sentry_value_set_by_key(SentryUserObject, "ip_address", sentry_value_new_string("{{auto}}")); - } - - sentry_value_set_by_key(SentryUserObject, "cmd", sentry_value_new_string(CommandLine.c_str())); - - const std::string SessionId(GetSessionIdString()); - sentry_value_set_by_key(SentryUserObject, "session", sentry_value_new_string(SessionId.c_str())); - - sentry_set_user(SentryUserObject); - - m_SentryLogger = spdlog::create("sentry"); - logging::SetErrorLog("sentry"); - - m_SentryAssert = std::make_unique(); - } - - m_IsInitialized = true; -} - -void -SentryIntegration::LogStartupInformation() -{ - if (m_IsInitialized) - { - if (m_SentryErrorCode == 0) - { - if (m_AllowPII) - { - ZEN_INFO("sentry initialized, username: '{}', hostname: '{}', id: '{}'", m_SentryUserName, m_SentryHostName, m_SentryId); - } - else - { - ZEN_INFO("sentry initialized with anonymous reports"); - } - } - else - { - ZEN_WARN( - "sentry_init returned failure! (error code: {}) note that sentry expects crashpad_handler to exist alongside the running " - "executable", - m_SentryErrorCode); - } - } -} - -void -SentryIntegration::ClearCaches() -{ - sentry_clear_modulecache(); -} - -} // namespace zen -#endif -- cgit v1.2.3