From 547d542e540530a8ac36332303b3dae1f5c8c18e Mon Sep 17 00:00:00 2001 From: Ivan Tustanivskyi Date: Fri, 20 Dec 2024 12:27:39 +0200 Subject: [PATCH] Add GPU crash dump attachments (#712) * Add GPU crash dump attachment for desktop * Fix gpu dump path * Fix tooltip * Update changelog * Fix build errors on Linux --- CHANGELOG.md | 4 +++ .../Desktop/SentrySubsystemDesktop.cpp | 28 +++++++++++++++++++ .../Private/Desktop/SentrySubsystemDesktop.h | 2 ++ .../Source/Sentry/Private/SentrySettings.cpp | 1 + .../Sentry/Private/Utils/SentryFileUtils.cpp | 23 ++++++++++++++- .../Sentry/Private/Utils/SentryFileUtils.h | 1 + .../Source/Sentry/Public/SentrySettings.h | 4 +++ 7 files changed, 62 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4e45b31..81a83fd0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Features + +- Add GPU crash dump attachments ([#712](https://github.com/getsentry/sentry-unreal/pull/712)) + ### Dependencies - Bump Native SDK from v0.7.16 to v0.7.17 ([#717](https://github.com/getsentry/sentry-unreal/pull/717)) diff --git a/plugin-dev/Source/Sentry/Private/Desktop/SentrySubsystemDesktop.cpp b/plugin-dev/Source/Sentry/Private/Desktop/SentrySubsystemDesktop.cpp index 4b45ab7d..6054f9f4 100644 --- a/plugin-dev/Source/Sentry/Private/Desktop/SentrySubsystemDesktop.cpp +++ b/plugin-dev/Source/Sentry/Private/Desktop/SentrySubsystemDesktop.cpp @@ -18,6 +18,7 @@ #include "SentryTraceSampler.h" +#include "Utils/SentryFileUtils.h" #include "Utils/SentryLogUtils.h" #include "Utils/SentryScreenshotUtils.h" @@ -41,8 +42,11 @@ #if PLATFORM_WINDOWS #include "Windows/WindowsPlatformMisc.h" +#include "Windows/WindowsPlatformCrashContext.h" #endif +extern CORE_API bool GIsGPUCrashed; + #if USE_SENTRY_NATIVE void PrintVerboseLog(sentry_level_t level, const char *message, va_list args, void *userdata) @@ -135,6 +139,11 @@ sentry_value_t HandleBeforeCrash(const sentry_ucontext_t *uctx, sentry_value_t e SentrySubsystemDesktop* SentrySubsystem = static_cast(closure); SentrySubsystem->TryCaptureScreenshot(); + if (GIsGPUCrashed) + { + IFileManager::Get().Copy(*SentrySubsystem->GetGpuDumpBackupPath(), *SentryFileUtils::GetGpuDumpPath()); + } + FSentryCrashContext::Get()->Apply(SentrySubsystem->GetCurrentScope()); TSharedPtr eventDesktop = MakeShareable(new SentryEventDesktop(event, true)); @@ -219,6 +228,15 @@ void SentrySubsystemDesktop::InitWithSettings(const USentrySettings* settings, U #endif } + if (settings->AttachGpuDump) + { +#if PLATFORM_WINDOWS + sentry_options_add_attachmentw(options, *GetGpuDumpBackupPath()); +#elif PLATFORM_LINUX + sentry_options_add_attachment(options, TCHAR_TO_UTF8(*GetGpuDumpBackupPath())); +#endif + } + if(settings->UseProxy) { sentry_options_set_http_proxy(options, TCHAR_TO_ANSI(*settings->ProxyUrl)); @@ -562,6 +580,16 @@ void SentrySubsystemDesktop::TryCaptureScreenshot() const SentryScreenshotUtils::CaptureScreenshot(GetScreenshotPath()); } +FString SentrySubsystemDesktop::GetGpuDumpBackupPath() const +{ + static const FString DateTimeString = FDateTime::Now().ToString(); + + const FString GpuDumpPath = FPaths::Combine(GetDatabasePath(), TEXT("gpudumps"), *FString::Printf(TEXT("UEAftermath-%s.nv-gpudmp"), *DateTimeString));; + const FString GpuDumpFullPath = FPaths::ConvertRelativePathToFull(GpuDumpPath); + + return GpuDumpFullPath; +} + TSharedPtr SentrySubsystemDesktop::GetCurrentScope() { if(scopeStack.Num() == 0) diff --git a/plugin-dev/Source/Sentry/Private/Desktop/SentrySubsystemDesktop.h b/plugin-dev/Source/Sentry/Private/Desktop/SentrySubsystemDesktop.h index d2269c99..c41a42a4 100644 --- a/plugin-dev/Source/Sentry/Private/Desktop/SentrySubsystemDesktop.h +++ b/plugin-dev/Source/Sentry/Private/Desktop/SentrySubsystemDesktop.h @@ -49,6 +49,8 @@ class SentrySubsystemDesktop : public ISentrySubsystem void TryCaptureScreenshot() const; + FString GetGpuDumpBackupPath() const; + TSharedPtr GetCurrentScope(); private: diff --git a/plugin-dev/Source/Sentry/Private/SentrySettings.cpp b/plugin-dev/Source/Sentry/Private/SentrySettings.cpp index 10f1a715..26fb1011 100644 --- a/plugin-dev/Source/Sentry/Private/SentrySettings.cpp +++ b/plugin-dev/Source/Sentry/Private/SentrySettings.cpp @@ -20,6 +20,7 @@ USentrySettings::USentrySettings(const FObjectInitializer& ObjectInitializer) , AttachStacktrace(true) , SendDefaultPii(false) , AttachScreenshot(false) + , AttachGpuDump(true) , MaxBreadcrumbs(100) , EnableAutoSessionTracking(true) , SessionTimeout(30000) diff --git a/plugin-dev/Source/Sentry/Private/Utils/SentryFileUtils.cpp b/plugin-dev/Source/Sentry/Private/Utils/SentryFileUtils.cpp index 33e103d7..1782168e 100644 --- a/plugin-dev/Source/Sentry/Private/Utils/SentryFileUtils.cpp +++ b/plugin-dev/Source/Sentry/Private/Utils/SentryFileUtils.cpp @@ -42,4 +42,25 @@ FString SentryFileUtils::GetGameLogBackupPath() GameLogBackupFiles.Sort(FSentrySortFileByDatePredicate()); return GameLogBackupFiles[0]; -} \ No newline at end of file +} + +FString SentryFileUtils::GetGpuDumpPath() +{ + TArray GpuDumpFiles; + IFileManager::Get().FindFiles(GpuDumpFiles, *FString::Printf(TEXT("%s*.nv-gpudmp"), *FPaths::ProjectLogDir()), true, false); + + if (GpuDumpFiles.Num() == 0) + { + UE_LOG(LogSentrySdk, Log, TEXT("There is no GPU dump file available.")); + return FString(""); + } + + if (GpuDumpFiles.Num() > 1) + { + // By default, engine should handle clean up of GPU dumps from the previous runs + UE_LOG(LogSentrySdk, Log, TEXT("There are multiple GPU dump files, can't determine reliably which one to pick.")); + return FString(""); + } + + return IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*(FPaths::ProjectLogDir() / GpuDumpFiles[0])); +} diff --git a/plugin-dev/Source/Sentry/Private/Utils/SentryFileUtils.h b/plugin-dev/Source/Sentry/Private/Utils/SentryFileUtils.h index 9f5d2fe0..142e911a 100644 --- a/plugin-dev/Source/Sentry/Private/Utils/SentryFileUtils.h +++ b/plugin-dev/Source/Sentry/Private/Utils/SentryFileUtils.h @@ -9,4 +9,5 @@ class SentryFileUtils public: static FString GetGameLogPath(); static FString GetGameLogBackupPath(); + static FString GetGpuDumpPath(); }; \ No newline at end of file diff --git a/plugin-dev/Source/Sentry/Public/SentrySettings.h b/plugin-dev/Source/Sentry/Public/SentrySettings.h index 9dc921e3..6c8f502f 100644 --- a/plugin-dev/Source/Sentry/Public/SentrySettings.h +++ b/plugin-dev/Source/Sentry/Public/SentrySettings.h @@ -242,6 +242,10 @@ class SENTRY_API USentrySettings : public UObject Meta = (DisplayName = "Attach screenshots", ToolTip = "Flag indicating whether to attach screenshot of the application when an error occurs. Currently this feature is supported for Windows and Linux only.")) bool AttachScreenshot; + UPROPERTY(Config, EditAnywhere, Category = "General|Attachments", + Meta = (DisplayName = "Attach GPU dump", ToolTip = "Flag indicating whether to attach GPU crash dump when an error occurs. Currently this feature is supported for Nvidia graphics only.")) + bool AttachGpuDump; + UPROPERTY(Config, EditAnywhere, BlueprintReadWrite, Category = "General|Breadcrumbs", Meta = (DisplayName = "Max breadcrumbs", Tooltip = "Total amount of breadcrumbs that should be captured.")) int32 MaxBreadcrumbs;