feat: Added statistics and crash log uploading (#1149)

Co-authored-by: Justus Garbe <gihihoh@gmail.com>
This commit is contained in:
Nik
2023-06-20 11:55:56 +02:00
committed by GitHub
parent 54061c56bf
commit f703b15165
23 changed files with 401 additions and 94 deletions

View File

@@ -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);

View File

@@ -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 },
};
}

View File

@@ -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;

View File

@@ -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);
}
}