diff --git a/CHANGELOG.md b/CHANGELOG.md index a7e1d8cab..5a57f5271 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ ### Features +- Added `SetBeforeCaptureScreenshot` and `SetBeforeCaptureViewHierarchy` to the options. Users can now choose whether to capture those as attachment on an individual event basis. ([#2023](https://github.com/getsentry/sentry-unity/pull/2023)) - When capturing events via `Debug.LogError`, the SDK now provides stacktraces. Note, that the SDK is currently not able to provide line numbers for these events. ([#1965](https://github.com/getsentry/sentry-unity/pull/1965)) - Added option to enable/disable automatic capture of `Debug.LogError` as event. ([#2009](https://github.com/getsentry/sentry-unity/pull/2009)) - The `Ignore CLI Errors` checkbox in the Debug Symbols tab now applies to all supported platforms. ([#2008](https://github.com/getsentry/sentry-unity/pull/2008)) diff --git a/src/Sentry.Unity/ScreenshotEventProcessor.cs b/src/Sentry.Unity/ScreenshotEventProcessor.cs index 8d0e0f8d4..46ea04c27 100644 --- a/src/Sentry.Unity/ScreenshotEventProcessor.cs +++ b/src/Sentry.Unity/ScreenshotEventProcessor.cs @@ -24,15 +24,24 @@ public ScreenshotEventProcessor(SentryUnityOptions sentryOptions) return @event; } - if (Screen.width == 0 || Screen.height == 0) + if (_options.BeforeCaptureScreenshotInternal?.Invoke() is not false) { - _options.DiagnosticLogger?.LogWarning("Can't capture screenshots on a screen with a resolution of '{0}x{1}'.", Screen.width, Screen.height); + if (Screen.width == 0 || Screen.height == 0) + { + _options.DiagnosticLogger?.LogWarning("Can't capture screenshots on a screen with a resolution of '{0}x{1}'.", Screen.width, Screen.height); + } + else + { + hint.AddAttachment(CaptureScreenshot(Screen.width, Screen.height), "screenshot.jpg", contentType: "image/jpeg"); + } } else { - hint.AddAttachment(CaptureScreenshot(Screen.width, Screen.height), "screenshot.jpg", contentType: "image/jpeg"); + _options.DiagnosticLogger?.LogInfo("Screenshot attachment skipped by BeforeAttachScreenshot callback."); } + + return @event; } diff --git a/src/Sentry.Unity/SentryUnityOptions.cs b/src/Sentry.Unity/SentryUnityOptions.cs index edc56b7a3..7cc9773f5 100644 --- a/src/Sentry.Unity/SentryUnityOptions.cs +++ b/src/Sentry.Unity/SentryUnityOptions.cs @@ -228,6 +228,38 @@ public sealed class SentryUnityOptions : SentryOptions /// public new StackTraceMode StackTraceMode { get; private set; } + private Func? _beforeCaptureScreenshot; + + internal Func? BeforeCaptureScreenshotInternal => _beforeCaptureScreenshot; + + /// + /// Configures a callback function to be invoked before capturing and attaching a screenshot to an event. + /// + /// + /// This callback will get invoked right before a screenshot gets taken. If the screenshot should not + /// be taken return `false`. + /// + public void SetBeforeCaptureScreenshot(Func beforeAttachScreenshot) + { + _beforeCaptureScreenshot = beforeAttachScreenshot; + } + + private Func? _beforeCaptureViewHierarchy; + + internal Func? BeforeCaptureViewHierarchyInternal => _beforeCaptureViewHierarchy; + + /// + /// Configures a callback function to be invoked before capturing and attaching the view hierarchy to an event. + /// + /// + /// This callback will get invoked right before the view hierarchy gets taken. If the view hierarchy should not + /// be taken return `false`. + /// + public void SetBeforeCaptureViewHierarchy(Func beforeAttachViewHierarchy) + { + _beforeCaptureViewHierarchy = beforeAttachViewHierarchy; + } + // Initialized by native SDK binding code to set the User.ID in .NET (UnityEventProcessor). internal string? _defaultUserId; internal string? DefaultUserId diff --git a/src/Sentry.Unity/ViewHierarchyEventProcessor.cs b/src/Sentry.Unity/ViewHierarchyEventProcessor.cs index 510af60cc..ff372a2e2 100644 --- a/src/Sentry.Unity/ViewHierarchyEventProcessor.cs +++ b/src/Sentry.Unity/ViewHierarchyEventProcessor.cs @@ -26,11 +26,18 @@ public ViewHierarchyEventProcessor(SentryUnityOptions sentryOptions) { if (!MainThreadData.IsMainThread()) { - _options.DiagnosticLogger?.LogDebug("Can't capture screenshots on other than main (UI) thread."); + _options.DiagnosticLogger?.LogDebug("Can't capture view hierarchy on other than main (UI) thread."); return @event; } - hint.AddAttachment(CaptureViewHierarchy(), "view-hierarchy.json", contentType: "application/json"); + if (_options.BeforeCaptureViewHierarchyInternal?.Invoke() is not false) + { + hint.AddAttachment(CaptureViewHierarchy(), "view-hierarchy.json", contentType: "application/json"); + } + else + { + _options.DiagnosticLogger?.LogInfo("View hierarchy attachment skipped by BeforeAttachViewHierarchy callback."); + } return @event; } diff --git a/test/Sentry.Unity.Tests/ScreenshotEventProcessorTests.cs b/test/Sentry.Unity.Tests/ScreenshotEventProcessorTests.cs index 99d4b4e0e..c12101c0d 100644 --- a/test/Sentry.Unity.Tests/ScreenshotEventProcessorTests.cs +++ b/test/Sentry.Unity.Tests/ScreenshotEventProcessorTests.cs @@ -40,7 +40,7 @@ public void GetTargetResolution_ReturnsTargetMaxSize(ScreenshotQuality quality, } [Test] - public void GetStream_IsMainThread_AddsScreenshotToHint() + public void Process_IsMainThread_AddsScreenshotToHint() { var sut = _fixture.GetSut(); var sentryEvent = new SentryEvent(); @@ -52,7 +52,7 @@ public void GetStream_IsMainThread_AddsScreenshotToHint() } [Test] - public void GetStream_IsNonMainThread_DoesNotAddScreenshotToHint() + public void Process_IsNonMainThread_DoesNotAddScreenshotToHint() { var sut = _fixture.GetSut(); var sentryEvent = new SentryEvent(); @@ -67,6 +67,21 @@ public void GetStream_IsNonMainThread_DoesNotAddScreenshotToHint() }).Start(); } + [Test] + [TestCase(true)] + [TestCase(false)] + public void Process_BeforeCaptureScreenshotCallbackProvided_RespectsScreenshotCaptureDecision(bool captureScreenshot) + { + _fixture.Options.SetBeforeCaptureScreenshot(() => captureScreenshot); + var sut = _fixture.GetSut(); + var sentryEvent = new SentryEvent(); + var hint = new SentryHint(); + + sut.Process(sentryEvent, hint); + + Assert.AreEqual(captureScreenshot ? 1 : 0, hint.Attachments.Count); + } + [Test] [TestCase(ScreenshotQuality.High, 1920)] [TestCase(ScreenshotQuality.Medium, 1280)] diff --git a/test/Sentry.Unity.Tests/UnityViewHierarchyEventProcessorTests.cs b/test/Sentry.Unity.Tests/ViewHierarchyEventProcessorTests.cs similarity index 88% rename from test/Sentry.Unity.Tests/UnityViewHierarchyEventProcessorTests.cs rename to test/Sentry.Unity.Tests/ViewHierarchyEventProcessorTests.cs index ae0246285..273768375 100644 --- a/test/Sentry.Unity.Tests/UnityViewHierarchyEventProcessorTests.cs +++ b/test/Sentry.Unity.Tests/ViewHierarchyEventProcessorTests.cs @@ -6,7 +6,7 @@ namespace Sentry.Unity.Tests; -public class UnityViewHierarchyEventProcessorTests +public class ViewHierarchyEventProcessorTests { private class Fixture { @@ -30,7 +30,7 @@ public void TearDown() } [Test] - public void GetStream_IsMainThread_AddsViewHierarchyToHint() + public void Process_IsMainThread_AddsViewHierarchyToHint() { var sut = _fixture.GetSut(); var sentryEvent = new SentryEvent(); @@ -42,7 +42,7 @@ public void GetStream_IsMainThread_AddsViewHierarchyToHint() } [Test] - public void GetStream_IsNonMainThread_DoesNotAddViewHierarchyToHint() + public void Process_IsNonMainThread_DoesNotAddViewHierarchyToHint() { var sut = _fixture.GetSut(); var sentryEvent = new SentryEvent(); @@ -58,6 +58,21 @@ public void GetStream_IsNonMainThread_DoesNotAddViewHierarchyToHint() }).Start(); } + [Test] + [TestCase(true)] + [TestCase(false)] + public void Process_BeforeCaptureViewHierarchyCallbackProvided_RespectViewHierarchyCaptureDecision(bool captureViewHierarchy) + { + _fixture.Options.SetBeforeCaptureViewHierarchy(() => captureViewHierarchy); + var sut = _fixture.GetSut(); + var sentryEvent = new SentryEvent(); + var hint = new SentryHint(); + + sut.Process(sentryEvent, hint); + + Assert.AreEqual(captureViewHierarchy ? 1 : 0, hint.Attachments.Count); + } + [Test] public void CaptureViewHierarchy_ReturnsNonNullOrEmptyByteArray() {