Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

### Fixes

- Fixed input handling in samples to work with old and new input system ([#2319](https://github.com/getsentry/sentry-unity/pull/2319))
- The SDK now captures exceptions on WebGL through the logging integration instead of the incompatible log handler, providing better stack trace support . ([#2322](https://github.com/getsentry/sentry-unity/pull/2322))
- Fixed input handling in samples to work with old and new input system. ([#2319](https://github.com/getsentry/sentry-unity/pull/2319))

### Dependencies

Expand Down
10 changes: 8 additions & 2 deletions src/Sentry.Unity.Editor/WebGL/BuildPreProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,21 @@ public void OnPreprocessBuild(BuildReport report)
return;
}

var (options, _) = SentryScriptableObject.ConfiguredBuildTimeOptions();
if (options?.Enabled is not true)
{
return;
}

if (PlayerSettings.WebGL.exceptionSupport == WebGLExceptionSupport.None)
{
throw new BuildFailedException("WebGL exception support is set to None. The Sentry SDK requires exception " +
"support to function properly. Please change the WebGL exception support setting in Player Settings " +
"or disable the Sentry SDK.");
}
else if (PlayerSettings.WebGL.exceptionSupport != WebGLExceptionSupport.FullWithStacktrace)

if (PlayerSettings.WebGL.exceptionSupport != WebGLExceptionSupport.FullWithStacktrace)
{
var (options, _) = SentryScriptableObject.ConfiguredBuildTimeOptions();
var logger = options?.DiagnosticLogger ?? new UnityLogger(options ?? new SentryUnityOptions());

logger.LogWarning("The SDK requires the Exception Support to be set " +
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
using Sentry.Extensibility;
using Sentry.Integrations;
using Sentry.Protocol;
using UnityEngine;

namespace Sentry.Unity.Integrations;

internal class UnityApplicationLoggingIntegration : ISdkIntegration
{
private readonly IApplication _application;
private readonly bool _captureExceptions;
private ErrorTimeDebounce? _errorTimeDebounce;
private LogTimeDebounce? _logTimeDebounce;
private WarningTimeDebounce? _warningTimeDebounce;

private IHub? _hub;
private SentryUnityOptions? _options;

internal UnityApplicationLoggingIntegration(IApplication? application = null)
internal UnityApplicationLoggingIntegration(bool captureExceptions = false, IApplication? application = null)
{
_captureExceptions = captureExceptions;
_application = application ?? ApplicationAdapter.Instance;
}

Expand Down Expand Up @@ -49,7 +53,8 @@ internal void OnLogMessageReceived(string message, string stacktrace, LogType lo
}

// LogType.Exception are getting handled by the UnityLogHandlerIntegration
if (logType is LogType.Exception)
// Unless we're configured to handle them - i.e. WebGL
if (logType is LogType.Exception && !_captureExceptions)
{
return;
}
Expand All @@ -58,6 +63,7 @@ internal void OnLogMessageReceived(string message, string stacktrace, LogType lo
{
var debounced = logType switch
{
LogType.Exception => _errorTimeDebounce?.Debounced(),
LogType.Error or LogType.Assert => _errorTimeDebounce?.Debounced(),
LogType.Log => _logTimeDebounce?.Debounced(),
LogType.Warning => _warningTimeDebounce?.Debounced(),
Expand All @@ -70,14 +76,19 @@ internal void OnLogMessageReceived(string message, string stacktrace, LogType lo
}
}

if (logType is LogType.Error && _options?.CaptureLogErrorEvents is true)
if (logType is LogType.Exception)
{
var ule = new UnityErrorLogException(message, stacktrace, _options);
_hub.CaptureException(ule);
}
else if (logType is LogType.Error && _options?.CaptureLogErrorEvents is true)
{
if (_options?.AttachStacktrace is true && !string.IsNullOrEmpty(stacktrace))
{
var ule = new UnityErrorLogException(message, stacktrace, _options);
var evt = new SentryEvent(ule) { Level = SentryLevel.Error };
var sentryEvent = new SentryEvent(ule) { Level = SentryLevel.Error };

_hub.CaptureEvent(evt);
_hub.CaptureEvent(sentryEvent);
}
else
{
Expand Down
9 changes: 7 additions & 2 deletions src/Sentry.Unity/SentryUnityOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,13 @@ internal SentryUnityOptions(IApplication? application = null,
AddTransactionProcessor(processor);
AddExceptionProcessor(new UnityExceptionProcessor());

AddIntegration(new UnityLogHandlerIntegration(this));
AddIntegration(new UnityApplicationLoggingIntegration());
// UnityLogHandlerIntegration is not compatible with WebGL, so it's added conditionally
if (application.Platform != RuntimePlatform.WebGLPlayer)
{
AddIntegration(new UnityLogHandlerIntegration(this));
AddIntegration(new UnityApplicationLoggingIntegration());
}

AddIntegration(new StartupTracingIntegration());
AddIntegration(new AnrIntegration(behaviour));
AddIntegration(new UnityScopeIntegration(application, unityInfo));
Expand Down
13 changes: 11 additions & 2 deletions src/Sentry.Unity/SentryUnitySdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,17 @@ public SentrySdk.CrashedLastRun CrashedLastRun()
{
if (_options.CrashedLastRun is null)
{
_options.DiagnosticLogger?.LogDebug("The SDK does not have a 'CrashedLastRun' set. " +
"This might be due to a missing or disabled native integration.");
if (ApplicationAdapter.Instance.Platform == RuntimePlatform.WebGLPlayer)
{
_options.DiagnosticLogger?.LogDebug("Currently, the Sentry SDK for Unity provides no native support for WebGL." +
"LastRunState is `Unknown`.");
}
else
{
_options.DiagnosticLogger?.LogDebug("The SDK does not have a 'CrashedLastRun' set. " +
"This might be due to a missing or disabled native integration.");
}

return SentrySdk.CrashedLastRun.Unknown;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: WebGL Crash Detection Override

The new WebGL platform check in CrashedLastRun() always returns Unknown, overriding the options.CrashedLastRun delegate that's explicitly configured for WebGL to return DidNotCrash. This causes the configured WebGL crash detection to be ignored. Also, the debug log message for WebGL is missing a space.

Fix in Cursor Fix in Web


Expand Down
17 changes: 14 additions & 3 deletions src/Sentry.Unity/WebGL/SentryWebGL.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Sentry.Extensibility;
using Sentry.Unity.Integrations;
using UnityEngine.Analytics;

namespace Sentry.Unity.WebGL;
Expand All @@ -16,6 +17,9 @@ public static void Configure(SentryUnityOptions options)
{
options.DiagnosticLogger?.LogDebug("Updating configuration for Unity WebGL.");

// Due to special exception handling on WebGL we capture these through `LogMessageReceived` too
options.AddIntegration(new UnityApplicationLoggingIntegration(captureExceptions: true));

// Note: we need to use a custom background worker which actually doesn't work in the background
// because Unity doesn't support async (multithreading) yet. This may change in the future so let's watch
// https://docs.unity3d.com/2019.4/Documentation/ScriptReference/PlayerSettings.WebGL-threadsSupport.html
Expand All @@ -26,16 +30,23 @@ public static void Configure(SentryUnityOptions options)
// "An abnormal situation has occurred: the PlayerLoop internal function has been called recursively.
// Please contact Customer Support with a sample project so that we can reproduce the problem and troubleshoot it."
// Maybe we could write a file when this error occurs and recognize it on the next start. Like unity-native.
options.CrashedLastRun = () => false;
options.CrashedLastRun = null;

// Disable async when accessing files (e.g. FileStream(useAsync: true)) because it throws on WebGL.
options.UseAsyncFileIO = false;

if (options.AttachScreenshot)
{
options.AttachScreenshot = false;
options.DiagnosticLogger?.LogWarning("Attaching screenshots on WebGL is disabled - " +
"it currently produces blank screenshots mid-frame.");
options.DiagnosticLogger?.LogWarning("Attaching screenshots is unsupported on WebGL - disabling. " +
"Currently, it produces blank screenshots mid-frame.");
}

// On WebGL, the IL2CPP backend does not provide the API required to make the IL2CPP Event Processor work
if (options.Il2CppLineNumberSupportEnabled)
{
options.Il2CppLineNumberSupportEnabled = false;
options.DiagnosticLogger?.LogWarning("IL2CPP line number support is unsupported on WebGL - disabling.");
}

// Use AnalyticsSessionInfo.userId as the default UserID
Expand Down
6 changes: 6 additions & 0 deletions test/Scripts.Integration.Test/Scripts/SmokeTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,13 @@ private IEnumerator SmokeTestCoroutine()

#if !UNITY_EDITOR
var crashed = CrashedLastRun();

#if UNITY_WEBGL
// On WebGL CrashedLastRun returns `Unknown`
t.Expect($"options.CrashedLastRun ({crashed}) == unknown (-2)", crashed == -2);
#else
t.Expect($"options.CrashedLastRun ({crashed}) == false (0)", crashed == 0);
#endif
#endif
var currentMessage = 0;
t.ExpectMessage(currentMessage, "'type':'session'");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ private class Fixture
public TestHub Hub { get; set; } = null!;
public SentryUnityOptions SentryOptions { get; set; } = null!;

public bool CaptureExceptions { get; set; } = false;

public UnityApplicationLoggingIntegration GetSut()
{
var application = new TestApplication();
var integration = new UnityApplicationLoggingIntegration(application);
var integration = new UnityApplicationLoggingIntegration(CaptureExceptions, application);
integration.Register(Hub, SentryOptions);
return integration;
}
Expand Down Expand Up @@ -161,5 +163,17 @@ public void OnLogMessageReceived_AddAsBreadcrumbDisabled_NotAddedAsBreadcrumb(Lo

Assert.IsFalse(_fixture.Hub.ConfigureScopeCalls.Count > 0);
}

[Test]
public void OnLogMessageReceived_LogTypeException_CaptureExceptionsEnabled_EventCaptured()
{
_fixture.CaptureExceptions = true;
var sut = _fixture.GetSut();
var message = TestContext.CurrentContext.Test.Name;

sut.OnLogMessageReceived(message, "stacktrace", LogType.Exception);

Assert.AreEqual(1, _fixture.Hub.CapturedEvents.Count);
}
}
}
Loading