Skip to content

Commit

Permalink
refactor: upload crash after restarted
Browse files Browse the repository at this point in the history
  • Loading branch information
ShrBox committed Jan 18, 2025
1 parent 961e852 commit 9271ea4
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 46 deletions.
2 changes: 1 addition & 1 deletion src/ll/core/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ struct LeviConfig {
} command{};
struct {
bool enabled = true;
bool useBuiltin = true;
bool useBuiltin = false;
bool uploadToSentry = true;
std::optional<std::string> externalpath;
} crashLogger{};
Expand Down
75 changes: 59 additions & 16 deletions src/ll/core/CrashLogger_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ class CrashLoggerNew {

static std::unique_ptr<CrashLoggerNew> 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)
Expand All @@ -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();

Expand All @@ -78,6 +121,9 @@ void CrashLogger::init() {
}
if (config.modules.crashLogger.useBuiltin) {
cln = std::make_unique<CrashLoggerNew>();
if (config.modules.crashLogger.uploadToSentry) {
submitCrashInfo();
}
return;
}

Expand Down Expand Up @@ -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<CrashLoggerNew>();
if (config.modules.crashLogger.uploadToSentry) {
submitCrashInfo();
}
return;
}

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down
1 change: 0 additions & 1 deletion src/ll/core/LeviLamina.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include "ll/api/io/FileUtils.h"
#include "ll/core/Version.h"


#include "mc/platform/UUID.h"

namespace ll {
Expand Down
31 changes: 3 additions & 28 deletions src/ll/core/SentryUploader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<unsigned char, 16> 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,
Expand Down Expand Up @@ -112,14 +88,13 @@ void SentryUploader::uploadAll() {
std::vector<std::thread> 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},
Expand Down

0 comments on commit 9271ea4

Please sign in to comment.