mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-02 13:37:42 -05:00
feat: Added statistics and crash log uploading (#1149)
Co-authored-by: Justus Garbe <gihihoh@gmail.com>
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
#include <hex/api/project_file_manager.hpp>
|
||||
#include <hex/api/task.hpp>
|
||||
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/stacktrace.hpp>
|
||||
@@ -6,7 +8,7 @@
|
||||
#include <wolv/io/fs.hpp>
|
||||
#include <wolv/utils/string.hpp>
|
||||
|
||||
#include "window.hpp"
|
||||
#include <window.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
@@ -15,6 +17,10 @@
|
||||
#include <exception>
|
||||
#include <csignal>
|
||||
|
||||
#if defined (OS_MACOS)
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
namespace hex::crash {
|
||||
|
||||
constexpr static auto CrashBackupFileName = "crash_backup.hexproj";
|
||||
@@ -44,20 +50,34 @@ namespace hex::crash {
|
||||
file.writeString(crashData.dump(4));
|
||||
file.close();
|
||||
log::info("Wrote crash.json file to {}", wolv::util::toUTF8String(file.getPath()));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
log::warn("Could not write crash.json file !");
|
||||
}
|
||||
|
||||
static void printStackTrace() {
|
||||
for (const auto &stackFrame : stacktrace::getStackTrace()) {
|
||||
if (stackFrame.line == 0)
|
||||
log::fatal(" {}", stackFrame.function);
|
||||
else
|
||||
log::fatal(" ({}:{}) | {}", stackFrame.file, stackFrame.line, stackFrame.function);
|
||||
}
|
||||
}
|
||||
|
||||
// Custom signal handler to print various information and a stacktrace when the application crashes
|
||||
static void signalHandler(int signalNumber, const std::string &signalName) {
|
||||
// Reset the signal handler to the default handler
|
||||
for(auto signal : Signals) std::signal(signal, SIG_DFL);
|
||||
|
||||
log::fatal("Terminating with signal '{}' ({})", signalName, signalNumber);
|
||||
|
||||
// Trigger the crash callback
|
||||
crashCallback(hex::format("Received signal '{}' ({})", signalName, signalNumber));
|
||||
|
||||
printStackTrace();
|
||||
|
||||
// Trigger an event so that plugins can handle crashes
|
||||
// It may affect things (like the project path),
|
||||
// so we do this after saving the crash file
|
||||
@@ -68,17 +88,6 @@ namespace hex::crash {
|
||||
log::fatal("Uncaught exception thrown!");
|
||||
}
|
||||
|
||||
// Reset the signal handler to the default handler
|
||||
for(auto signal : Signals) std::signal(signal, SIG_DFL);
|
||||
|
||||
// Print stack trace
|
||||
for (const auto &stackFrame : stacktrace::getStackTrace()) {
|
||||
if (stackFrame.line == 0)
|
||||
log::fatal(" {}", stackFrame.function);
|
||||
else
|
||||
log::fatal(" ({}:{}) | {}", stackFrame.file, stackFrame.line, stackFrame.function);
|
||||
}
|
||||
|
||||
// Trigger a breakpoint if we're in a debug build or raise the signal again for the default handler to handle it
|
||||
#if defined(DEBUG)
|
||||
assert(!"Debug build, triggering breakpoint");
|
||||
@@ -116,6 +125,8 @@ namespace hex::crash {
|
||||
// Handle crash callback
|
||||
crashCallback(hex::format("Uncaught exception: {}", exceptionStr));
|
||||
|
||||
printStackTrace();
|
||||
|
||||
// Reset signal handlers prior to calling the original handler, because it may raise a signal
|
||||
for(auto signal : Signals) std::signal(signal, SIG_DFL);
|
||||
|
||||
|
||||
@@ -27,17 +27,17 @@
|
||||
|
||||
#include <wolv/io/fs.hpp>
|
||||
#include <wolv/io/file.hpp>
|
||||
#include <wolv/hash/uuid.hpp>
|
||||
|
||||
namespace hex::init {
|
||||
|
||||
using namespace std::literals::string_literals;
|
||||
|
||||
#if defined(HEX_UPDATE_CHECK)
|
||||
static bool checkForUpdates() {
|
||||
int showCheckForUpdates = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.check_for_updates", 2);
|
||||
int checkForUpdates = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.server_contact", 2);
|
||||
|
||||
// Check if we should check for updates
|
||||
if (showCheckForUpdates == 1){
|
||||
if (checkForUpdates == 1){
|
||||
HttpRequest request("GET", GitHubApiURL + "/releases/latest"s);
|
||||
request.setTimeout(2000);
|
||||
|
||||
@@ -69,10 +69,36 @@ namespace hex::init {
|
||||
if (latestVersion != currVersion)
|
||||
ImHexApi::System::impl::addInitArgument("update-available", latestVersion.data());
|
||||
|
||||
// Check if there is a telemetry uuid
|
||||
std::string uuid = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.uuid", "");
|
||||
if(uuid.empty()) {
|
||||
// Generate a new uuid
|
||||
uuid = wolv::hash::generateUUID();
|
||||
// Save
|
||||
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.uuid", uuid);
|
||||
}
|
||||
|
||||
// Make telemetry request
|
||||
nlohmann::json telemetry = {
|
||||
{"uuid", uuid},
|
||||
{"version", IMHEX_VERSION},
|
||||
{"os", fmt::format("{}/{}/{}", ImHexApi::System::getOSName(), ImHexApi::System::getOSVersion(), ImHexApi::System::getArchitecture()) }
|
||||
};
|
||||
|
||||
HttpRequest telemetryRequest("POST", ImHexApiURL + "/telemetry"s);
|
||||
telemetryRequest.setTimeout(2000);
|
||||
|
||||
telemetryRequest.setBody(telemetry.dump());
|
||||
telemetryRequest.addHeader("Content-Type", "application/json");
|
||||
|
||||
// Execute request
|
||||
response = telemetryRequest.execute().get();
|
||||
if (response.getStatusCode() != 200)
|
||||
return false;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool setupEnvironment() {
|
||||
hex::log::debug("Using romfs: '{}'", romfs::name());
|
||||
@@ -508,9 +534,7 @@ namespace hex::init {
|
||||
#endif
|
||||
{ "Loading settings", loadSettings, false },
|
||||
{ "Loading plugins", loadPlugins, false },
|
||||
#if defined(HEX_UPDATE_CHECK)
|
||||
{ "Checking for updates", checkForUpdates, true },
|
||||
#endif
|
||||
{ "Loading fonts", loadFonts, true },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -39,9 +39,9 @@ int main(int argc, char **argv, char **envp) {
|
||||
{
|
||||
Window::initNative();
|
||||
|
||||
hex::log::info("Welcome to ImHex {}!", IMHEX_VERSION);
|
||||
log::info("Welcome to ImHex {}!", IMHEX_VERSION);
|
||||
#if defined(GIT_BRANCH) && defined(GIT_COMMIT_HASH_SHORT)
|
||||
hex::log::info("Compiled using commit {}@{}", GIT_BRANCH, GIT_COMMIT_HASH_SHORT);
|
||||
log::info("Compiled using commit {}@{}", GIT_BRANCH, GIT_COMMIT_HASH_SHORT);
|
||||
#endif
|
||||
|
||||
init::WindowSplash splashWindow;
|
||||
@@ -56,13 +56,18 @@ int main(int argc, char **argv, char **envp) {
|
||||
ImHexApi::System::getInitArguments().insert({ "tasks-failed", {} });
|
||||
}
|
||||
|
||||
log::info("Running on {} {} ({})", ImHexApi::System::getOSName(), ImHexApi::System::getOSVersion(), ImHexApi::System::getArchitecture());
|
||||
log::info("Using '{}' GPU", ImHexApi::System::getGPUVendor());
|
||||
|
||||
// Clean up everything after the main window is closed
|
||||
ON_SCOPE_EXIT {
|
||||
auto exitHandler = [](auto){
|
||||
for (const auto &[name, task, async] : init::getExitTasks())
|
||||
task();
|
||||
TaskManager::exit();
|
||||
};
|
||||
|
||||
ON_SCOPE_EXIT { exitHandler(0); };
|
||||
|
||||
// Main window
|
||||
{
|
||||
Window window;
|
||||
|
||||
@@ -295,7 +295,6 @@ namespace hex {
|
||||
log::fatal("Exception raised: 0x{:08X}", exception->ExceptionRecord->ExceptionCode);
|
||||
if (exception->ExceptionRecord->ExceptionCode == STATUS_HEAP_CORRUPTION) {
|
||||
log::fatal("Heap corruption detected!");
|
||||
std::raise(SIGABRT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user