-
-
Notifications
You must be signed in to change notification settings - Fork 50
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
Add AttachScreenshot
option
#284
Comments
Gotchas to keep in mind:
|
Strategy on Xamarin changed: https://github.com/getsentry/sentry-xamarin/blob/main/Src/Sentry.Xamarin/Internals/Device/Screenshot/ScreenshotAttachment.cs Would be nice to have a Sample so users can see the usage when they import the package. Unmerged spec PR: getsentry/develop#422 |
Also:
This is my current implementation but most of the time I'd love to have screenshots for native exceptions, they are harder to diagnose.
|
The resizing of the screenshot is a good catch. Thanks for sharing! |
If you allowed attachment streams to be async we could implement screenshots fairly easily ourselves. Or even just give us a callback 1 frame before you actually call GetStream |
How do you attach this to the event? |
If BeforeSend would be async we could also set attachments in the context without problems no? |
To be honest I never expected Sentry would not have a feature like this... Unity Diagnostics doesn't have 1/10 part of the features you own but does have the screenshot... I dont mean to criticize is just a screenshot of the game just when the exception happened is extremely useful and might save you a lot of time finding where a problem is. I hope you guys consider giving some priority to this or a temporary workaround. |
This is a priority to us. We're adding support for screenshots on iOS and Android, and there's a thumbnail in Sentry's issue detail page. |
@pistoleta Here's an updated version that works some of the time. You just add it to your Configure(SentryUnityOptions options) method. public class ScreenshotAttachment : IAttachmentContent, UnityEngine.ILogHandler
{
private ILogHandler handler;
private Texture2D screenshot;
public ScreenshotAttachment()
{
handler = Debug.unityLogger.logHandler;
Debug.unityLogger.logHandler = this;
}
private async Task Capture()
{
Debug.Log("Capturing screenshot");
await new WaitForEndOfFrame();
float ratio = (float)Screen.width / (float)Screen.height;
int targetHeight = Mathf.Min(Screen.height, 360);
int targetWidth = Mathf.RoundToInt((float)targetHeight * ratio);
RenderTexture screenshotRt = RenderTexture.GetTemporary(Screen.width, Screen.height);
ScreenCapture.CaptureScreenshotIntoRenderTexture(screenshotRt);
// Create a render texture to render into
RenderTexture screenshotResize = RenderTexture.GetTemporary(targetWidth, targetHeight, 0);
##if UNITY_IOS || UNITY_EDITOR
Graphics.Blit(screenshotRt, screenshotResize, new Vector2(1, -1), new Vector2(0, 1));
##else
Graphics.Blit(screenshotRt, screenshotResize);
##endif
RenderTexture.ReleaseTemporary(screenshotRt);
RenderTexture previousActiveRT = RenderTexture.active;
RenderTexture.active = screenshotResize;
// Create a texture & read data from the active RenderTexture
screenshot = new Texture2D(targetWidth, targetHeight) { name = "Screenshot" };
screenshot.ReadPixels(new Rect(0, 0, targetWidth, targetHeight), 0, 0);
screenshot.Apply();
}
public Stream GetStream()
{
if (screenshot == null)
{
UnityEngine.Debug.Log("Returning empty stream due to missing screenshot texture2d");
return new MemoryStream();
}
var stream = new MemoryStream(screenshot.EncodeToJPG(80));
screenshot.SafeDestroy();
UnityEngine.Debug.Log("captured screenshot attachment");
return stream;
}
public void LogFormat(LogType logType, UnityEngine.Object context, string format, params object[] args)
{
handler.LogFormat(logType, context, format, args);
}
public async void LogException(Exception exception, UnityEngine.Object context)
{
await Capture();
handler.LogException(exception,context);
}
} edit by @vaind: fix the codeblock |
Hmm, seeing the screenshots don't have a cursor (when in UI), maybe we should also include cursor position in all events? https://docs.unity3d.com/ScriptReference/Input-mousePosition.html It's not the same issue though, just asking here and if it makes sense we can have a follow-up issue for that. |
For backup: an async version would look somewhat like the following code. It wouldn't work with WebGL because of its single-threaded nature it requires a synchronous stream CopyTo() and we can't have that and wait for the end of frame. ScreenshotAttachmentContent.GetStream():
{
if (!_behaviour.MainThreadData.IsMainThread())
{
_options.DiagnosticLogger?.LogDebug("Won't capture screenshot because we're not on the main thread");
return new MemoryStream();
}
else
{
return new ScreenshotCaptureStream(_options, _behaviour);
}
}
// The async version is currently unused because we want the screenshot to be as early as possible after the error
internal class ScreenshotCaptureStream : Stream
{
private readonly SentryOptions _options;
private readonly TaskCompletionSource<byte[]> _tcs;
public ScreenshotCaptureStream(SentryOptions options, SentryMonoBehaviour behaviour)
{
_options = options;
_tcs = new();
behaviour.StartCoroutine(CaptureScreenshot());
}
private IEnumerator CaptureScreenshot()
{
yield return new WaitForEndOfFrame();
_tcs.TrySetResult(ScreenshotAttachmentContent.CaptureScreenshot(_options));
}
public override async Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
{
var bytes = await _tcs.Task.ConfigureAwait(false);
_options.DiagnosticLogger?.LogDebug("Awaiting screenshot finished: {0} bytes", bytes.Length);
var writer = new BinaryWriter(destination);
writer.Write(bytes);
_options.DiagnosticLogger?.LogDebug("Finished writing the screenshot");
}
public override bool CanRead => throw new NotImplementedException();
public override bool CanSeek => throw new NotImplementedException();
public override bool CanWrite => throw new NotImplementedException();
public override long Length => throw new NotImplementedException();
public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public override void Flush() => throw new NotImplementedException();
public override int Read(byte[] buffer, int offset, int count) => throw new NotImplementedException();
public override long Seek(long offset, SeekOrigin origin) => throw new NotImplementedException();
public override void SetLength(long value) => throw new NotImplementedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException();
} |
I understand for this you had to implement a IDiagnosticLogger and assign it to optios.DiagnosticLogger inside the SentryOptionsConfiguration, correct? Also, why all the hassle trying to make the screenCapture async? couldn't you simply use Unity's API with Is it because you don't want the game lag when creating the screenshot? or we must do it like this for some reason? Thanks for your help. |
No that's not the case. You can see the actual implementation in #670 - ScreenShotAttachment.cs |
I still fail to see how the example in GitHub you pointed can be added to the SentryOptionsConfiguration. I tested in editor and yes, it sends a screenshot when I push the button, but I thought we were talking about attaching a screenshot the moment an exception/error triggers... am I missing something? |
This is my configure method, just in case I'm missing something. |
It's not released yet so it wouldn't work for you yet, unless you've made a custom build with that branch (which I strongly assume you haven't, based on your message). I'd suggest waiting for the next package release (v0.14.0) which should include this feature, if everything goes according to the plan (i.e. we don't find any blocking issues) |
Ah ok, thanks for your kindness and understanding, GitHub it's a bit hard to follow but I'll get used to it. |
@vaind I'd watch out for black screenshots when not using
|
I downloaded last release and used the example for sending screenshot but the screenshot seems to be captured upwards.... any hint where the problem might be? I used the exact same code provided in the example. |
Which platform did you target? |
iOS, btw i had to comment: |
Do you mean the example code, not the new functionality implemented by the latest version? That example is old and doesn't do proper mirroring (necessary for most platforms) |
Sorry to see you run into problems. |
If you're updating the Sentry package you also have to update the samples coming with it. |
Also, there's no |
wrong script 🤦 , seems I already had a ScreenShotAttachement that tried to make work some time ago. Apologies |
No worries! Happy to see it worked out for you regardless! |
sorry but I dont see any way to attach screenshot in the 0.15.0 at least nothing new in the examples |
you can enable it in the settings in the Unity UI (Tools->Sentry) |
awesome, sorry I didnt see it in the changelog |
sorry but I dont see any image attachment, neither from iOS reports or if I send one from unity editor... I enabled from the settings In tools->sentry and also I the SentryOptionsCOnfiguration ScriptableObject. |
When the option is set to true, events will include a screenshot of the game.
This feature is being added to Xamarin:
https://github.com/getsentry/sentry-xamarin/search?q=screenshot
https://github.com/getsentry/sentry-xamarin/blob/411be60d616789ad81ec13e2e50c7c2a777b4c67/Src/Sentry.Xamarin/Internals/Device/Screenshot/ScreenshotEventProcessor.droid.ios.cs
The text was updated successfully, but these errors were encountered: