From 9271ea42bc13ef1904acc11bca9cf7a8370d4f80 Mon Sep 17 00:00:00 2001 From: ShrBox Date: Sat, 18 Jan 2025 15:36:59 +0800 Subject: [PATCH] refactor: upload crash after restarted --- src/ll/core/Config.h | 2 +- src/ll/core/CrashLogger_win.cpp | 75 ++++++++++++++++++++++++++------- src/ll/core/LeviLamina.cpp | 1 - src/ll/core/SentryUploader.cpp | 31 ++------------ 4 files changed, 63 insertions(+), 46 deletions(-) diff --git a/src/ll/core/Config.h b/src/ll/core/Config.h index efbde383e5..7562533978 100644 --- a/src/ll/core/Config.h +++ b/src/ll/core/Config.h @@ -32,7 +32,7 @@ struct LeviConfig { } command{}; struct { bool enabled = true; - bool useBuiltin = true; + bool useBuiltin = false; bool uploadToSentry = true; std::optional externalpath; } crashLogger{}; diff --git a/src/ll/core/CrashLogger_win.cpp b/src/ll/core/CrashLogger_win.cpp index 8e5067ae6e..9189a1a438 100644 --- a/src/ll/core/CrashLogger_win.cpp +++ b/src/ll/core/CrashLogger_win.cpp @@ -45,7 +45,6 @@ class CrashLoggerNew { static std::unique_ptr cln; - std::string toString(_CONTEXT const& c) { return fmt::format("RAX: 0x{:016X} RBX: 0x{:016X} RCX: 0x{:016X}\n", c.Rax, c.Rbx, c.Rcx) + fmt::format("RDX: 0x{:016X} RSI: 0x{:016X} RDI: 0x{:016X}\n", c.Rdx, c.Rsi, c.Rdi) @@ -66,6 +65,50 @@ std::string toString(_CONTEXT const& c) { ); } +bool saveCrashInfo( + const std::filesystem::path& logPath, + const std::string& minidumpName, + const std::string& traceName +) { + auto path = logPath / fmt::format("sentry_{:%Y-%m-%d_%H-%M-%S}", fmt::localtime(_time64(nullptr))); + return file_utils::writeFile(path, fmt::format("{}\n{}", minidumpName, traceName)); +} + +// Read log and dump file path from logs/crash/sentry_xxx, then submit them to sentry +void submitCrashInfo() { + auto path = file_utils::u8path(pl::pl_log_path) / u8"crash"; + for (auto& entry : std::filesystem::directory_iterator(path)) { + if (entry.path().filename().string().starts_with("sentry_")) { + auto content = file_utils::readFile(entry.path()); + if (!content) { + continue; + } + auto paths = string_utils::splitByPattern(*content, "\n"); + if (paths.size() != 2) { + continue; + } + auto dmpFilePath = file_utils::u8path(pl::pl_log_path) / u8"crash" / paths[0]; + auto logFilePath = file_utils::u8path(pl::pl_log_path) / u8"crash" / paths[1]; + SentryUploader sentryUploader{ + std::string(getServiceUuid()), + dmpFilePath.filename().string(), + u8str2str(dmpFilePath.u8string()), + logFilePath.filename().string(), + u8str2str(logFilePath.u8string()), + ll::getLoaderVersion().to_string().find('+') != std::string::npos, + ll::getLoaderVersion().to_string() + }; + sentryUploader.addModSentryInfo( + ll::getSelfModIns()->getName(), + "https://43a888504c33385bfd2e570c9ac939aa@o4508652421906432.ingest.us.sentry.io/4508652563398656", + ll::getLoaderVersion().to_string() + ); + sentryUploader.uploadAll(); + std::filesystem::remove(entry.path()); + } + } +} + void CrashLogger::init() { auto& config = getLeviConfig(); @@ -78,6 +121,9 @@ void CrashLogger::init() { } if (config.modules.crashLogger.useBuiltin) { cln = std::make_unique(); + if (config.modules.crashLogger.uploadToSentry) { + submitCrashInfo(); + } return; } @@ -106,6 +152,11 @@ void CrashLogger::init() { if (!CreateProcess(nullptr, cmd.data(), &sa, &sa, true, 0, nullptr, nullptr, &si, &pi)) { crashLoggerPtr->error("Couldn't Create CrashLogger Daemon Process"_tr()); error_utils::printException(error_utils::getLastSystemError(), *crashLoggerPtr); + // If failed to create CrashLogger Daemon Process, use built-in CrashLogger + cln = std::make_unique(); + if (config.modules.crashLogger.uploadToSentry) { + submitCrashInfo(); + } return; } @@ -254,8 +305,13 @@ static LONG unhandledExceptionFilter(_In_ struct _EXCEPTION_POINTERS* e) { crashInfo.date = fmt::format("{:%Y-%m-%d_%H-%M-%S}", fmt::localtime(_time64(nullptr))); crashInfo.settings = ll::getLeviConfig().modules.crashLogger; crashInfo.path = file_utils::u8path(pl::pl_log_path) / u8"crash"; - auto logFilePath = crashInfo.path / ("trace_" + crashInfo.date + ".log"); - auto dumpFilePath = crashInfo.path / string_utils::str2u8str("minidump_" + crashInfo.date + ".dmp"); + auto logFilePath = crashInfo.path / ("trace_" + crashInfo.date + ".log"); + auto dumpFilePath = crashInfo.path / string_utils::str2u8str("minidump_" + crashInfo.date + ".dmp"); + // Save log and dump file path to logs/crash/sentry_xxx for later use + if (getLeviConfig().modules.crashLogger.uploadToSentry) { + saveCrashInfo(crashInfo.path, dumpFilePath.filename().string(), logFilePath.filename().string()); + } + if (!std::filesystem::is_directory(crashInfo.path)) { std::filesystem::create_directory(crashInfo.path); } @@ -331,19 +387,6 @@ static LONG unhandledExceptionFilter(_In_ struct _EXCEPTION_POINTERS* e) { if (!EnumerateLoadedModulesW64(crashInfo.process, dumpModules, nullptr)) { throw error_utils::getLastSystemError(); } - if (getLeviConfig().modules.crashLogger.uploadToSentry) { - SentryUploader sentryUploader{ - std::string(getServiceUuid()), - dumpFilePath.filename().string(), - u8str2str(dumpFilePath.u8string()), - logFilePath.filename().string(), - u8str2str(logFilePath.u8string()), - ll::getLoaderVersion().to_string().find('+') != std::string::npos, - ll::getLoaderVersion().to_string() - }; - sentryUploader.addModSentryInfo(ll::getSelfModIns()->getName(), "https://43a888504c33385bfd2e570c9ac939aa@o4508652421906432.ingest.us.sentry.io/4508652563398656", ll::getLoaderVersion().to_string()); - sentryUploader.uploadAll(); - } } catch (...) { crashInfo.logger.error("!!! Error in CrashLogger !!!"); ll::error_utils::printCurrentException(crashInfo.logger); diff --git a/src/ll/core/LeviLamina.cpp b/src/ll/core/LeviLamina.cpp index 112a1b79d7..96dee39d9b 100644 --- a/src/ll/core/LeviLamina.cpp +++ b/src/ll/core/LeviLamina.cpp @@ -4,7 +4,6 @@ #include "ll/api/io/FileUtils.h" #include "ll/core/Version.h" - #include "mc/platform/UUID.h" namespace ll { diff --git a/src/ll/core/SentryUploader.cpp b/src/ll/core/SentryUploader.cpp index 41d4f361fa..5a72f3b2bf 100644 --- a/src/ll/core/SentryUploader.cpp +++ b/src/ll/core/SentryUploader.cpp @@ -9,11 +9,12 @@ #include "ll/core/SentryUploader.h" #include "ll/api/io/Logger.h" #include "ll/api/io/LoggerRegistry.h" +#include "mc/platform/UUID.h" using json = nlohmann::json; namespace ll { -auto sentryLogger = io::LoggerRegistry::getInstance().getOrCreate("CrashLogger"); +auto sentryLogger = io::LoggerRegistry::getInstance().getOrCreate("SentryUploader"); std::string compressDataGzip(const std::string& data) { std::ostringstream compressedStream; @@ -33,31 +34,6 @@ std::string compressDataGzip(const std::string& data) { return resultStream.str(); } -std::string generateUUID() { - thread_local static std::mt19937_64 rng(std::random_device{}()); - std::array bytes{}; - uint64_t random_part1 = rng(); - uint64_t random_part2 = rng(); - - static_assert(sizeof(uint64_t) == 8, "Unexpected size"); - std::memcpy(bytes.data(), &random_part1, 8); - std::memcpy(bytes.data() + 8, &random_part2, 8); - bytes[6] = (unsigned char)((bytes[6] & 0x0F) | 0x40); - bytes[8] = (unsigned char)((bytes[8] & 0x3F) | 0x80); - static const char* hex = "0123456789abcdef"; - std::string uuid; - uuid.reserve(36); - - for (size_t i = 0; i < 16; ++i) { - uuid.push_back(hex[(bytes[i] >> 4) & 0x0F]); - uuid.push_back(hex[bytes[i] & 0x0F]); - if (i == 3 || i == 5 || i == 7 || i == 9) { - uuid.push_back('-'); - } - } - return uuid; -} - SentryUploader::SentryUploader( const std::string& user, const std::string& minidmpName, @@ -112,14 +88,13 @@ void SentryUploader::uploadAll() { std::vector threads; threads.reserve(mModsSentryConfig.size()); - sentryLogger->info(""); sentryLogger->info("Uploading crash report to Sentry..."); for (const auto& sentryConfig : mModsSentryConfig) { threads.emplace_back([=, this]() { try { std::string url = sentryConfig.dsnInfo.protocol + "://" + sentryConfig.dsnInfo.host + "/api/" + sentryConfig.dsnInfo.projectId + "/envelope/"; - std::string eventId = generateUUID(); + std::string eventId = mce::UUID::random().asString(); json envelopeHeader = { {"event_id", eventId},