-
-
Notifications
You must be signed in to change notification settings - Fork 49
Add screenshot capturing for Mac/iOS #849
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
ebd5db0
Add screen capturing utility for iOS
tustanivsky 7b685c9
Rework screenshot capturing for Apple
tustanivsky 36026ed
Update snapshot
tustanivsky dcf22ab
Merge branch 'main' into feat/ios-screenshot
tustanivsky 0d9deaf
Update snapshot
tustanivsky 86df572
FIx init params
tustanivsky 0d12285
Add screenshot attachment for crashes via envelope
tustanivsky 40eb0bf
Update changelog
tustanivsky a6bf79c
Add screenshot for ensures on Mac
tustanivsky ba2cb4e
Add screenshot backup
tustanivsky 5c2694d
Fix module getter that could cause ensure
tustanivsky 1716702
Add check if screenshot exists
tustanivsky 4f21912
Add custom signal handler to capture screenshots on crash (iOS)
tustanivsky 3d16918
Merge branch 'main' into feat/ios-screenshot
tustanivsky 0d2f4e9
Update logging
tustanivsky 7cb90cd
Remove screenshot backup
tustanivsky 705f551
Update plugin-dev/Source/Sentry/Public/SentrySettings.h
tustanivsky b26a7d8
Minor logging tweaks
tustanivsky 50c8e74
Fix ensure handler for Mac
tustanivsky 6d1a1c7
Rework screenshot uploading
tustanivsky File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
plugin-dev/Source/Sentry/Private/IOS/IOSSentrySubsystem.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#include "IOS/IOSSentrySubsystem.h" | ||
|
||
#include "IOS/IOSAppDelegate.h" | ||
|
||
#include "SentryDefines.h" | ||
#include "SentrySettings.h" | ||
|
||
#include "Misc/CoreDelegates.h" | ||
#include "Misc/FileHelper.h" | ||
#include "Misc/Paths.h" | ||
#include "Utils/SentryScreenshotUtils.h" | ||
|
||
static FIOSSentrySubsystem* GIOSSentrySubsystem = nullptr; | ||
|
||
struct sigaction DefaultSigIllHandler; | ||
struct sigaction DefaultSigEmtHandler; | ||
struct sigaction DefaultSigFpeHandler; | ||
struct sigaction DefaultSigBusHandler; | ||
struct sigaction DefaultSigSegvHandler; | ||
struct sigaction DefaultSigSysHandler; | ||
|
||
void SaveDefaultSignalHandlers() | ||
{ | ||
sigaction(SIGILL, NULL, &DefaultSigIllHandler); | ||
sigaction(SIGEMT, NULL, &DefaultSigEmtHandler); | ||
sigaction(SIGFPE, NULL, &DefaultSigFpeHandler); | ||
sigaction(SIGBUS, NULL, &DefaultSigBusHandler); | ||
sigaction(SIGSEGV, NULL, &DefaultSigSegvHandler); | ||
sigaction(SIGSYS, NULL, &DefaultSigSysHandler); | ||
} | ||
|
||
void RestoreDefaultSignalHandlers() | ||
{ | ||
sigaction(SIGILL, &DefaultSigIllHandler, NULL); | ||
sigaction(SIGEMT, &DefaultSigEmtHandler, NULL); | ||
sigaction(SIGFPE, &DefaultSigFpeHandler, NULL); | ||
sigaction(SIGBUS, &DefaultSigBusHandler, NULL); | ||
sigaction(SIGSEGV, &DefaultSigSegvHandler, NULL); | ||
sigaction(SIGSYS, &DefaultSigSysHandler, NULL); | ||
} | ||
|
||
static void IOSSentrySignalHandler(int Signal, siginfo_t *Info, void *Context) | ||
{ | ||
if (GIOSSentrySubsystem && GIOSSentrySubsystem->IsEnabled()) | ||
{ | ||
GIOSSentrySubsystem->TryCaptureScreenshot(); | ||
} | ||
|
||
RestoreDefaultSignalHandlers(); | ||
|
||
// Re-raise signal to default handler | ||
raise(Signal); | ||
} | ||
|
||
void InstallSentrySignalHandler() | ||
{ | ||
struct sigaction Action; | ||
memset(&Action, 0, sizeof(Action)); | ||
Action.sa_sigaction = IOSSentrySignalHandler; | ||
Action.sa_flags = SA_SIGINFO | SA_ONSTACK; | ||
|
||
sigaction(SIGILL, &Action, NULL); | ||
sigaction(SIGEMT, &Action, NULL); | ||
sigaction(SIGFPE, &Action, NULL); | ||
sigaction(SIGBUS, &Action, NULL); | ||
sigaction(SIGSEGV, &Action, NULL); | ||
sigaction(SIGSYS, &Action, NULL); | ||
} | ||
|
||
void FIOSSentrySubsystem::InitWithSettings(const USentrySettings* Settings, USentryBeforeSendHandler* BeforeSendHandler, USentryBeforeBreadcrumbHandler* BeforeBreadcrumbHandler, | ||
USentryTraceSampler* TraceSampler) | ||
{ | ||
GIOSSentrySubsystem = this; | ||
|
||
SaveDefaultSignalHandlers(); | ||
InstallSentrySignalHandler(); | ||
|
||
FAppleSentrySubsystem::InitWithSettings(Settings, BeforeSendHandler, BeforeBreadcrumbHandler, TraceSampler); | ||
} | ||
|
||
FString FIOSSentrySubsystem::TryCaptureScreenshot() const | ||
{ | ||
FString ScreenshotPath = GetScreenshotPath(); | ||
|
||
dispatch_sync(dispatch_get_main_queue(), ^{ | ||
UIGraphicsBeginImageContextWithOptions([IOSAppDelegate GetDelegate].RootView.bounds.size, NO, 2.0f); | ||
[[IOSAppDelegate GetDelegate].RootView drawViewHierarchyInRect:[IOSAppDelegate GetDelegate].RootView.bounds afterScreenUpdates:YES]; | ||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); | ||
UIGraphicsEndImageContext(); | ||
|
||
NSData *ImageData = UIImagePNGRepresentation(image); | ||
|
||
TArray<uint8> ImageBytes; | ||
uint32 SavedSize = ImageData.length; | ||
ImageBytes.AddUninitialized(SavedSize); | ||
FPlatformMemory::Memcpy(ImageBytes.GetData(), [ImageData bytes], SavedSize); | ||
|
||
if (!FFileHelper::SaveArrayToFile(ImageBytes, *ScreenshotPath)) | ||
{ | ||
UE_LOG(LogSentrySdk, Error, TEXT("Failed to save screenshot to: %s"), *ScreenshotPath); | ||
} | ||
}); | ||
|
||
return ScreenshotPath; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
plugin-dev/Source/Sentry/Private/Mac/MacSentrySubsystem.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
#include "Mac/MacSentrySubsystem.h" | ||
|
||
#include "SentryIdApple.h" | ||
|
||
#include "SentryDefines.h" | ||
#include "SentryModule.h" | ||
#include "SentrySettings.h" | ||
|
||
#include "Misc/CoreDelegates.h" | ||
#include "Misc/FileHelper.h" | ||
#include "Misc/Paths.h" | ||
|
||
void FMacSentrySubsystem::InitWithSettings(const USentrySettings* Settings, USentryBeforeSendHandler* BeforeSendHandler, USentryBeforeBreadcrumbHandler* BeforeBreadcrumbHandler, | ||
USentryTraceSampler* TraceSampler) | ||
{ | ||
FAppleSentrySubsystem::InitWithSettings(Settings, BeforeSendHandler, BeforeBreadcrumbHandler, TraceSampler); | ||
|
||
isScreenshotAttachmentEnabled = Settings->AttachScreenshot; | ||
|
||
if (IsEnabled() && Settings->AttachScreenshot) | ||
{ | ||
FCoreDelegates::OnHandleSystemError.AddLambda([this]() | ||
{ | ||
TryCaptureScreenshot(); | ||
}); | ||
} | ||
} | ||
|
||
TSharedPtr<ISentryId> FMacSentrySubsystem::CaptureEnsure(const FString& type, const FString& message) | ||
{ | ||
TSharedPtr<ISentryId> id = FAppleSentrySubsystem::CaptureEnsure(type, message); | ||
|
||
if (isScreenshotAttachmentEnabled) | ||
{ | ||
const FString& screenshotPath = TryCaptureScreenshot(); | ||
if (!screenshotPath.IsEmpty()) | ||
{ | ||
UploadScreenshotForEvent(id, screenshotPath); | ||
} | ||
} | ||
|
||
return id; | ||
} | ||
|
||
FString FMacSentrySubsystem::TryCaptureScreenshot() const | ||
{ | ||
NSWindow* MainWindow = [NSApp mainWindow]; | ||
if (!MainWindow) | ||
{ | ||
UE_LOG(LogSentrySdk, Error, TEXT("No main window found!")); | ||
return FString(""); | ||
} | ||
|
||
NSRect WindowRect = [MainWindow frame]; | ||
CGWindowID WindowID = (CGWindowID)[MainWindow windowNumber]; | ||
CGImageRef ScreenshotRef = CGWindowListCreateImage(WindowRect, kCGWindowListOptionIncludingWindow, WindowID, kCGWindowImageDefault); | ||
|
||
if (!ScreenshotRef) | ||
{ | ||
UE_LOG(LogSentrySdk, Error, TEXT("Failed to capture screenshot - invalid ScreenshotRef.")); | ||
return FString(""); | ||
} | ||
|
||
NSBitmapImageRep* BitmapRep = [[NSBitmapImageRep alloc] initWithCGImage:ScreenshotRef]; | ||
NSData* ImageData = [BitmapRep representationUsingType:NSBitmapImageFileTypePNG properties:@{}]; | ||
|
||
TArray<uint8> ImageBytes; | ||
uint32 SavedSize = (uint32)[ImageData length]; | ||
ImageBytes.AddUninitialized(SavedSize); | ||
FPlatformMemory::Memcpy(ImageBytes.GetData(), [ImageData bytes], SavedSize); | ||
|
||
CGImageRelease(ScreenshotRef); | ||
|
||
FString ScreenshotPath = GetScreenshotPath(); | ||
|
||
if (!FFileHelper::SaveArrayToFile(ImageBytes, *ScreenshotPath)) | ||
{ | ||
UE_LOG(LogSentrySdk, Error, TEXT("Failed to save screenshot to: %s"), *ScreenshotPath); | ||
return FString(""); | ||
} | ||
|
||
return ScreenshotPath; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.