diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c1beb2b4..40dd39dc1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,18 @@
### Breaking Changes
-- Dropped support for Unity 2019. It reached End of Life in 2022 ([#2231](https://github.com/getsentry/sentry-unity/pull/2231))
+- Removed Unity 2019 support, which reached End of Life in 2022. Minimum supported version now is 2020 ([#2231](https://github.com/getsentry/sentry-unity/pull/2231))
+
+- **Breaking Change**: The Unity SDK's static API has been simplified moved from `Sentry.Unity.SentryUnity` and `Sentry.SentrySdk`
+ to `Sentry.Unity.SentrySdk`.
+ This change enables [manual/programatic SDK initialization](https://docs.sentry.io/platforms/unity/configuration/options/programmatic-configuration/) with full functionality, previously only available through auto-initialization.
+ The underlying .NET SDK's `SentrySdk` class is now internal, and several previously public classes like `SentryInitialization`
+ and `SentryIntegrations` are now internal.
+
+ **Migration**: Update your `using` directives from `using Sentry;` to `using Sentry.Unity;`. IDEs like Rider can automatically
+ import the missing references. In some cases, you may need both `using Sentry.Unity;` (for the static API) and `using Sentry;`
+ (for types like `SentryId`). No changes are required to your actual SDK method calls (e.g., `SentrySdk.CaptureException()`
+ remains the same). ([#2227](https://github.com/getsentry/sentry-unity/pull/2227))
### Features
diff --git a/package-dev/Runtime/SentryInitialization.cs b/package-dev/Runtime/SentryInitialization.cs
index e98ce8318..dc0485125 100644
--- a/package-dev/Runtime/SentryInitialization.cs
+++ b/package-dev/Runtime/SentryInitialization.cs
@@ -15,7 +15,9 @@
#endif
using System;
+using Sentry.Unity;
using Sentry.Extensibility;
+using Sentry.Unity.NativeUtils;
#if UNITY_2020_3_OR_NEWER
using System.Buffers;
using System.Runtime.InteropServices;
@@ -39,61 +41,57 @@
namespace Sentry.Unity
{
- public static class SentryInitialization
+ internal static class SentryInitialization
{
+ ///
+ /// This is intended for internal use only.
+ /// The SDK relies on SetupPlatformServices getting called as the very first thing during the game's
+ /// startup. This ensures that features like line number and native support are set up and configured properly.
+ /// This is also the case when initializing manually from code.
+ ///
#if SENTRY_WEBGL
// On WebGL SubsystemRegistration is too early for the UnityWebRequestTransport and errors with 'URI empty'
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
#else
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
#endif
- public static void Init()
+ private static void Init()
{
- var unityInfo = new SentryUnityInfo();
+ // We're setting up `UnityInfo` and the platform specific configure callbacks as the very first thing.
+ // These are required to be available during initialization.
+ SetupPlatformServices();
+
// Loading the options invokes the ScriptableOption`Configure` callback. Users can disable the SDK via code.
- var options = ScriptableSentryUnityOptions.LoadSentryUnityOptions(unityInfo);
+ var options = ScriptableSentryUnityOptions.LoadSentryUnityOptions();
if (options != null && options.ShouldInitializeSdk())
{
- // Configures scope sync and (by default) initializes the native SDK.
- SetupNativeSdk(options, unityInfo);
- SentryUnity.Init(options);
+ SentrySdk.Init(options);
}
else
{
// If the SDK is not `enabled` we're closing down the native layer as well. This is especially relevant
// in a `built-time-initialization` scenario where the native SDKs self-initialize.
#if SENTRY_NATIVE_COCOA
- SentryNativeCocoa.Close(options, unityInfo);
+ SentryNativeCocoa.Close(options);
#elif SENTRY_NATIVE_ANDROID
- SentryNativeAndroid.Close(options, unityInfo);
+ SentryNativeAndroid.Close(options);
#endif
}
}
- private static void SetupNativeSdk(SentryUnityOptions options, SentryUnityInfo unityInfo)
+ private static void SetupPlatformServices()
{
- try
- {
+ SentryPlatformServices.UnityInfo = new SentryUnityInfo();
+
#if SENTRY_NATIVE_COCOA
- SentryNativeCocoa.Configure(options, unityInfo);
+ SentryPlatformServices.PlatformConfiguration = SentryNativeCocoa.Configure;
#elif SENTRY_NATIVE_ANDROID
- SentryNativeAndroid.Configure(options, unityInfo);
+ SentryPlatformServices.PlatformConfiguration = SentryNativeAndroid.Configure;
#elif SENTRY_NATIVE
- SentryNative.Configure(options, unityInfo);
+ SentryPlatformServices.PlatformConfiguration = SentryNative.Configure;
#elif SENTRY_WEBGL
- SentryWebGL.Configure(options);
+ SentryPlatformServices.PlatformConfiguration = SentryWebGL.Configure;
#endif
- }
- catch (DllNotFoundException e)
- {
- options.DiagnosticLogger?.LogError(e,
- "Sentry native-error capture configuration failed to load a native library. This usually " +
- "means the library is missing from the application bundle or the installation directory.");
- }
- catch (Exception e)
- {
- options.DiagnosticLogger?.LogError(e, "Sentry native error capture configuration failed.");
- }
}
}
diff --git a/package-dev/Runtime/SentryUserFeedback.cs b/package-dev/Runtime/SentryUserFeedback.cs
index 4e01d3a06..b6475b802 100644
--- a/package-dev/Runtime/SentryUserFeedback.cs
+++ b/package-dev/Runtime/SentryUserFeedback.cs
@@ -86,7 +86,7 @@ public void SendFeedback()
else
{
// Since there is no screenshot added we can capture the feedback right away
- SentryUnity.CaptureFeedback(_description.text, _email.text, _name.text, addScreenshot: false);
+ SentrySdk.CaptureFeedback(_description.text, _email.text, _name.text, addScreenshot: false);
}
}
@@ -99,7 +99,7 @@ private IEnumerator HideFormAndCaptureFeedback()
// We're waiting for the EndOfFrame so the FeedbackForm gets updated before capturing the screenshot
yield return new WaitForEndOfFrame();
- SentryUnity.CaptureFeedback(_description.text, _email.text, _name.text, addScreenshot: true);
+ SentrySdk.CaptureFeedback(_description.text, _email.text, _name.text, addScreenshot: true);
ResetUserFeedback();
}
diff --git a/samples/unity-of-bugs/Assets/Scripts/AdditionalButtons.cs b/samples/unity-of-bugs/Assets/Scripts/AdditionalButtons.cs
index 7d8afd0a7..9ab032cac 100644
--- a/samples/unity-of-bugs/Assets/Scripts/AdditionalButtons.cs
+++ b/samples/unity-of-bugs/Assets/Scripts/AdditionalButtons.cs
@@ -1,7 +1,7 @@
using System.Collections;
using System.Threading;
-using System.Threading.Tasks;
using Sentry;
+using Sentry.Unity;
using UnityEngine;
public class AdditionalButtons : MonoBehaviour
diff --git a/samples/unity-of-bugs/Assets/Scripts/BugFarmButtons.cs b/samples/unity-of-bugs/Assets/Scripts/BugFarmButtons.cs
index 674fc54c3..f43152920 100644
--- a/samples/unity-of-bugs/Assets/Scripts/BugFarmButtons.cs
+++ b/samples/unity-of-bugs/Assets/Scripts/BugFarmButtons.cs
@@ -1,7 +1,7 @@
using System;
-using System.Globalization;
using System.Runtime.CompilerServices;
using Sentry;
+using Sentry.Unity;
using UnityEngine;
using UnityEngine.Assertions;
diff --git a/samples/unity-of-bugs/Assets/Scripts/NativeSupport/NativeButtons.cs b/samples/unity-of-bugs/Assets/Scripts/NativeSupport/NativeButtons.cs
index c43ea33da..28ce26844 100644
--- a/samples/unity-of-bugs/Assets/Scripts/NativeSupport/NativeButtons.cs
+++ b/samples/unity-of-bugs/Assets/Scripts/NativeSupport/NativeButtons.cs
@@ -1,7 +1,7 @@
-using Sentry;
-using System;
+using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
+using Sentry.Unity;
using UnityEngine;
using UnityEngine.Diagnostics;
using UnityEngine.UI;
diff --git a/samples/unity-of-bugs/Assets/Scripts/ThreadingSamples.cs b/samples/unity-of-bugs/Assets/Scripts/ThreadingSamples.cs
index 7aac93994..b8cf7e3be 100644
--- a/samples/unity-of-bugs/Assets/Scripts/ThreadingSamples.cs
+++ b/samples/unity-of-bugs/Assets/Scripts/ThreadingSamples.cs
@@ -3,7 +3,7 @@
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
-using Sentry;
+using Sentry.Unity;
using UnityEngine;
using UnityEngine.Assertions;
diff --git a/src/Sentry.Unity.Android/SentryNativeAndroid.cs b/src/Sentry.Unity.Android/SentryNativeAndroid.cs
index 76ee1f7ae..6c3e6daea 100644
--- a/src/Sentry.Unity.Android/SentryNativeAndroid.cs
+++ b/src/Sentry.Unity.Android/SentryNativeAndroid.cs
@@ -1,6 +1,7 @@
using System;
using Sentry.Extensibility;
using Sentry.Unity.Integrations;
+using Sentry.Unity.NativeUtils;
using UnityEngine;
using UnityEngine.Analytics;
@@ -19,7 +20,7 @@ public static class SentryNativeAndroid
/// Configures the native Android support.
///
/// The Sentry Unity options to use.
- public static void Configure(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo)
+ public static void Configure(SentryUnityOptions options)
{
MainThreadData.CollectData();
@@ -105,7 +106,7 @@ public static void Configure(SentryUnityOptions options, ISentryUnityInfo sentry
e, "Failed to reinstall backend. Captured native crashes will miss scope data and tag.");
}
- options.NativeSupportCloseCallback = () => Close(options, sentryUnityInfo);
+ options.NativeSupportCloseCallback = () => Close(options);
options.DiagnosticLogger?.LogDebug("Fetching installation ID");
@@ -136,14 +137,11 @@ public static void Configure(SentryUnityOptions options, ISentryUnityInfo sentry
///
/// Closes the native Android support.
///
- public static void Close(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo) =>
- Close(options, sentryUnityInfo, ApplicationAdapter.Instance.Platform);
-
- internal static void Close(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo, RuntimePlatform platform)
+ public static void Close(SentryUnityOptions options)
{
options.DiagnosticLogger?.LogInfo("Attempting to close the Android SDK");
- if (!sentryUnityInfo.IsNativeSupportEnabled(options, platform))
+ if (!options.UnityInfo.IsNativeSupportEnabled(options, ApplicationAdapter.Instance.Platform))
{
options.DiagnosticLogger?.LogDebug("Android Native Support is not enabled. Skipping closing the Android SDK");
return;
diff --git a/src/Sentry.Unity.Editor/SentryScriptableObject.cs b/src/Sentry.Unity.Editor/SentryScriptableObject.cs
index 7764c119f..844e43f93 100644
--- a/src/Sentry.Unity.Editor/SentryScriptableObject.cs
+++ b/src/Sentry.Unity.Editor/SentryScriptableObject.cs
@@ -36,7 +36,7 @@ internal static (SentryUnityOptions?, SentryCliOptions?) ConfiguredBuildTimeOpti
SentryUnityOptions? options = null;
if (scriptableOptions is not null)
{
- options = scriptableOptions.ToSentryUnityOptions(isBuilding: true, unityInfo: null);
+ options = scriptableOptions.ToSentryUnityOptions(isBuilding: true);
// TODO: Move this into `Load` once we remove Runtime- and BuildTimeConfig
// We're calling `Configure` here and not in `Load` so the new Config does not overwrite the BuildTimeConfig
diff --git a/src/Sentry.Unity.Native/SentryNative.cs b/src/Sentry.Unity.Native/SentryNative.cs
index 6f15a65f8..d4b132d52 100644
--- a/src/Sentry.Unity.Native/SentryNative.cs
+++ b/src/Sentry.Unity.Native/SentryNative.cs
@@ -2,6 +2,7 @@
using Sentry.Extensibility;
using Sentry.Unity.Integrations;
using System.Collections.Generic;
+using Sentry.Unity.NativeUtils;
using UnityEngine;
using UnityEngine.Analytics;
@@ -22,13 +23,13 @@ public static class SentryNative
///
/// The Sentry Unity options to use.
/// Infos about the current Unity environment
- public static void Configure(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo)
+ public static void Configure(SentryUnityOptions options)
{
Logger = options.DiagnosticLogger;
Logger?.LogInfo("Attempting to configure native support via the Native SDK");
- if (!sentryUnityInfo.IsNativeSupportEnabled(options, ApplicationAdapter.Instance.Platform))
+ if (!options.UnityInfo.IsNativeSupportEnabled(options, ApplicationAdapter.Instance.Platform))
{
Logger?.LogDebug("Native support is disabled for '{0}'.", ApplicationAdapter.Instance.Platform);
return;
@@ -36,7 +37,7 @@ public static void Configure(SentryUnityOptions options, ISentryUnityInfo sentry
try
{
- if (!SentryNativeBridge.Init(options, sentryUnityInfo))
+ if (!SentryNativeBridge.Init(options))
{
Logger?.LogWarning("Sentry native initialization failed - native crashes are not captured.");
return;
diff --git a/src/Sentry.Unity.Native/SentryNativeBridge.cs b/src/Sentry.Unity.Native/SentryNativeBridge.cs
index 7d67d3325..bdfab9f00 100644
--- a/src/Sentry.Unity.Native/SentryNativeBridge.cs
+++ b/src/Sentry.Unity.Native/SentryNativeBridge.cs
@@ -12,13 +12,11 @@ namespace Sentry.Unity.Native;
/// P/Invoke to `sentry-native` functions.
///
///
-public static class SentryNativeBridge
+internal static class SentryNativeBridge
{
- public static bool CrashedLastRun;
-
- public static bool Init(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo)
+ public static bool Init(SentryUnityOptions options)
{
- _isLinux = sentryUnityInfo.IsLinux();
+ _isLinux = options.UnityInfo.IsLinux();
var cOptions = sentry_options_new();
diff --git a/src/Sentry.Unity.iOS/SentryNativeCocoa.cs b/src/Sentry.Unity.iOS/SentryNativeCocoa.cs
index 766fe5a55..6da06232d 100644
--- a/src/Sentry.Unity.iOS/SentryNativeCocoa.cs
+++ b/src/Sentry.Unity.iOS/SentryNativeCocoa.cs
@@ -14,15 +14,15 @@ public static class SentryNativeCocoa
/// Configures the native support.
///
/// The Sentry Unity options to use.
- /// Infos about the current Unity environment
- public static void Configure(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo) =>
- Configure(options, sentryUnityInfo, ApplicationAdapter.Instance.Platform);
+ public static void Configure(SentryUnityOptions options) =>
+ Configure(options, ApplicationAdapter.Instance.Platform);
- internal static void Configure(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo, RuntimePlatform platform)
+ // For testing
+ internal static void Configure(SentryUnityOptions options, RuntimePlatform platform)
{
options.DiagnosticLogger?.LogInfo("Attempting to configure native support via the Cocoa SDK");
- if (!sentryUnityInfo.IsNativeSupportEnabled(options, platform))
+ if (!options.UnityInfo.IsNativeSupportEnabled(options, platform))
{
options.DiagnosticLogger?.LogDebug("Native support is disabled for: '{0}'", platform);
return;
@@ -66,8 +66,8 @@ internal static void Configure(SentryUnityOptions options, ISentryUnityInfo sent
return crashedLastRun;
};
- options.NativeSupportCloseCallback += () => Close(options, sentryUnityInfo, platform);
- if (sentryUnityInfo.IL2CPP)
+ options.NativeSupportCloseCallback += () => Close(options);
+ if (options.UnityInfo.IL2CPP)
{
options.DefaultUserId = SentryCocoaBridgeProxy.GetInstallationId();
if (string.IsNullOrEmpty(options.DefaultUserId))
@@ -96,14 +96,11 @@ internal static void Configure(SentryUnityOptions options, ISentryUnityInfo sent
///
/// Closes the native Cocoa support.
///
- public static void Close(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo) =>
- Close(options, sentryUnityInfo, ApplicationAdapter.Instance.Platform);
-
- internal static void Close(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo, RuntimePlatform platform)
+ public static void Close(SentryUnityOptions options)
{
options.DiagnosticLogger?.LogInfo("Attempting to close the Cocoa SDK");
- if (!sentryUnityInfo.IsNativeSupportEnabled(options, platform))
+ if (!options.UnityInfo.IsNativeSupportEnabled(options, ApplicationAdapter.Instance.Platform))
{
options.DiagnosticLogger?.LogDebug("Cocoa Native Support is not enable. Skipping closing the Cocoa SDK");
return;
diff --git a/src/Sentry.Unity/Il2CppEventProcessor.cs b/src/Sentry.Unity/Il2CppEventProcessor.cs
index 612dcbc93..68247ef77 100644
--- a/src/Sentry.Unity/Il2CppEventProcessor.cs
+++ b/src/Sentry.Unity/Il2CppEventProcessor.cs
@@ -17,11 +17,11 @@ internal class UnityIl2CppEventExceptionProcessor : ISentryEventExceptionProcess
private static ISentryUnityInfo UnityInfo = null!; // private static will be initialized in the constructor
private readonly Il2CppMethods _il2CppMethods;
- public UnityIl2CppEventExceptionProcessor(SentryUnityOptions options, ISentryUnityInfo unityInfo)
+ public UnityIl2CppEventExceptionProcessor(SentryUnityOptions options)
{
Options = options;
- UnityInfo = unityInfo;
- _il2CppMethods = unityInfo.Il2CppMethods ?? throw new ArgumentNullException(nameof(unityInfo.Il2CppMethods),
+ UnityInfo = options.UnityInfo;
+ _il2CppMethods = UnityInfo.Il2CppMethods ?? throw new ArgumentNullException(nameof(UnityInfo.Il2CppMethods),
"Unity IL2CPP methods are not available.");
Options.SdkIntegrationNames.Add("IL2CPPLineNumbers");
diff --git a/src/Sentry.Unity/NativeUtils/SentryPlatformServices.cs b/src/Sentry.Unity/NativeUtils/SentryPlatformServices.cs
new file mode 100644
index 000000000..3070de469
--- /dev/null
+++ b/src/Sentry.Unity/NativeUtils/SentryPlatformServices.cs
@@ -0,0 +1,36 @@
+using System;
+
+namespace Sentry.Unity.NativeUtils;
+
+///
+/// These are SDK's services that are only available at runtime and cannot be baked into the SDK. The
+/// SentryInitialization.cs is provided as .cs and gets compiled with the game. It sets IUnityInfo
+/// and the PlatformConfiguration callback during the game's startup so that they are available during initializtion.
+///
+/// Consider this internal.
+public static class SentryPlatformServices
+{
+ private static ISentryUnityInfo? _unityInfo;
+
+ ///
+ /// The UnityInfo holds methods that rely on conditionally compilation, i.e. IL2CPP backend.
+ ///
+ public static ISentryUnityInfo UnityInfo
+ {
+ get => _unityInfo ?? throw new InvalidOperationException("UnityInfo is null.");
+ set
+ {
+ if (_unityInfo != null)
+ {
+ throw new InvalidOperationException("Should not set twice. lol.");
+ }
+
+ _unityInfo = value;
+ }
+ }
+
+ ///
+ /// The PlatformConfiguration callback is responsible for configuring the native SDK and setting up scope sync.
+ ///
+ public static Action? PlatformConfiguration { get; set; }
+}
diff --git a/src/Sentry.Unity/ScriptableSentryUnityOptions.cs b/src/Sentry.Unity/ScriptableSentryUnityOptions.cs
index 3684172fb..3c7ec50c9 100644
--- a/src/Sentry.Unity/ScriptableSentryUnityOptions.cs
+++ b/src/Sentry.Unity/ScriptableSentryUnityOptions.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using Sentry.Extensibility;
using Sentry.Unity.Integrations;
+using Sentry.Unity.NativeUtils;
using UnityEngine;
namespace Sentry.Unity;
@@ -120,22 +121,22 @@ public static string GetConfigPath(string? notDefaultConfigName = null)
///
/// Used for loading the SentryUnityOptions from the ScriptableSentryUnityOptions during runtime.
///
- public static SentryUnityOptions? LoadSentryUnityOptions(ISentryUnityInfo unityInfo)
+ public static SentryUnityOptions? LoadSentryUnityOptions()
{
var scriptableOptions = Resources.Load($"{ConfigRootFolder}/{ConfigName}");
if (scriptableOptions is not null)
{
- return scriptableOptions.ToSentryUnityOptions(false, unityInfo);
+ return scriptableOptions.ToSentryUnityOptions(false);
}
return null;
}
- internal SentryUnityOptions ToSentryUnityOptions(bool isBuilding, ISentryUnityInfo? unityInfo, IApplication? application = null)
+ internal SentryUnityOptions ToSentryUnityOptions(bool isBuilding, IApplication? application = null)
{
application ??= ApplicationAdapter.Instance;
- var options = new SentryUnityOptions(isBuilding, application, unityInfo)
+ var options = new SentryUnityOptions(isBuilding, application)
{
Enabled = Enabled,
Dsn = Dsn,
@@ -235,12 +236,12 @@ internal SentryUnityOptions ToSentryUnityOptions(bool isBuilding, ISentryUnityIn
options.AddEventProcessor(new ScreenshotEventProcessor(options));
}
- if (!application.IsEditor && options.Il2CppLineNumberSupportEnabled && unityInfo is not null)
+ if (!application.IsEditor && options.Il2CppLineNumberSupportEnabled)
{
- options.AddIl2CppExceptionProcessor(unityInfo);
+ options.AddIl2CppExceptionProcessor();
}
- HandlePlatformRestrictedOptions(options, unityInfo, application);
+ HandlePlatformRestrictedOptions(options, application);
HandleExceptionFilter(options);
if (!AnrDetectionEnabled)
@@ -251,9 +252,9 @@ internal SentryUnityOptions ToSentryUnityOptions(bool isBuilding, ISentryUnityIn
return options;
}
- internal void HandlePlatformRestrictedOptions(SentryUnityOptions options, ISentryUnityInfo? unityInfo, IApplication application)
+ internal void HandlePlatformRestrictedOptions(SentryUnityOptions options, IApplication application)
{
- if (unityInfo?.IsKnownPlatform() == false)
+ if (!options.UnityInfo.IsKnownPlatform())
{
options.DisableFileWrite = true;
diff --git a/src/Sentry.Unity/SentrySdk.Dotnet.cs b/src/Sentry.Unity/SentrySdk.Dotnet.cs
new file mode 100644
index 000000000..f9548d83e
--- /dev/null
+++ b/src/Sentry.Unity/SentrySdk.Dotnet.cs
@@ -0,0 +1,543 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using Sentry.Infrastructure;
+using Sentry.Protocol.Envelopes;
+
+namespace Sentry.Unity;
+
+public static partial class SentrySdk
+{
+ ///
+ /// Flushes the queue of captured events until the timeout set in
+ /// is reached.
+ ///
+ ///
+ /// Blocks synchronously. Prefer in async code.
+ ///
+ [DebuggerStepThrough]
+ public static void Flush() => Sentry.SentrySdk.Flush();
+
+ ///
+ /// Flushes the queue of captured events until the timeout is reached.
+ ///
+ /// The amount of time allowed for flushing.
+ ///
+ /// Blocks synchronously. Prefer in async code.
+ ///
+ [DebuggerStepThrough]
+ public static void Flush(TimeSpan timeout) => Sentry.SentrySdk.Flush(timeout);
+
+ ///
+ /// Flushes the queue of captured events until the timeout set in
+ /// is reached.
+ ///
+ /// A task to await for the flush operation.
+ [DebuggerStepThrough]
+ public static Task FlushAsync() => Sentry.SentrySdk.FlushAsync();
+
+ ///
+ /// Flushes the queue of captured events until the timeout is reached.
+ ///
+ /// The amount of time allowed for flushing.
+ /// A task to await for the flush operation.
+ [DebuggerStepThrough]
+ public static Task FlushAsync(TimeSpan timeout) => Sentry.SentrySdk.FlushAsync(timeout);
+
+ ///
+ /// Whether the SDK is enabled or not.
+ ///
+ public static bool IsEnabled { [DebuggerStepThrough] get => Sentry.SentrySdk.IsEnabled; }
+
+ ///
+ /// Creates a new scope that will terminate when disposed.
+ ///
+ ///
+ /// Pushes a new scope while inheriting the current scope's data.
+ ///
+ /// A state object to be added to the scope.
+ /// A disposable that when disposed, ends the created scope.
+ [DebuggerStepThrough]
+ public static IDisposable PushScope(TState state) => Sentry.SentrySdk.PushScope(state);
+
+ ///
+ /// Creates a new scope that will terminate when disposed.
+ ///
+ /// A disposable that when disposed, ends the created scope.
+ [DebuggerStepThrough]
+ public static IDisposable PushScope() => Sentry.SentrySdk.PushScope();
+
+ ///
+ /// Binds the client to the current scope.
+ ///
+ /// The client.
+ [DebuggerStepThrough]
+ public static void BindClient(ISentryClient client) => Sentry.SentrySdk.BindClient(client);
+
+ ///
+ /// Adds a breadcrumb to the current Scope.
+ ///
+ ///
+ /// If a message is provided it’s rendered as text and the whitespace is preserved.
+ /// Very long text might be abbreviated in the UI.
+ ///
+ /// Categories are dotted strings that indicate what the crumb is or where it comes from.
+ /// Typically it’s a module name or a descriptive string.
+ /// For instance ui.click could be used to indicate that a click happened in the UI or flask could be used to indicate that the event originated in the Flask framework.
+ ///
+ ///
+ /// The type of breadcrumb.
+ /// The default type is default which indicates no specific handling.
+ /// Other types are currently http for HTTP requests and navigation for navigation events.
+ ///
+ ///
+ ///
+ /// Data associated with this breadcrumb.
+ /// Contains a sub-object whose contents depend on the breadcrumb type.
+ /// Additional parameters that are unsupported by the type are rendered as a key/value table.
+ ///
+ /// Breadcrumb level.
+ ///
+ [DebuggerStepThrough]
+ public static void AddBreadcrumb(
+ string message,
+ string? category = null,
+ string? type = null,
+ IDictionary? data = null,
+ BreadcrumbLevel level = default)
+ => Sentry.SentrySdk.AddBreadcrumb(message, category, type, data, level);
+
+ ///
+ /// Adds a breadcrumb to the current scope.
+ ///
+ ///
+ /// This overload is intended to be used by integrations only.
+ /// The objective is to allow better testability by allowing control of the timestamp set to the breadcrumb.
+ ///
+ /// An optional .
+ /// The message.
+ /// The category.
+ /// The type.
+ /// The data.
+ /// The level.
+ [DebuggerStepThrough]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static void AddBreadcrumb(
+ ISystemClock? clock,
+ string message,
+ string? category = null,
+ string? type = null,
+ IDictionary? data = null,
+ BreadcrumbLevel level = default)
+ => Sentry.SentrySdk.AddBreadcrumb(clock, message, category, type, data, level);
+
+ ///
+ /// Adds a breadcrumb to the current Scope.
+ ///
+ /// The breadcrumb to be added
+ /// A hint providing additional context that can be used in the BeforeBreadcrumb callback
+ ///
+ [DebuggerStepThrough]
+ public static void AddBreadcrumb(Breadcrumb breadcrumb, SentryHint? hint = null)
+ => Sentry.SentrySdk.AddBreadcrumb(breadcrumb, hint);
+
+ ///
+ /// Configures the scope through the callback.
+ ///
+ /// The configure scope callback.
+ [DebuggerStepThrough]
+ public static void ConfigureScope(Action configureScope)
+ => Sentry.SentrySdk.ConfigureScope(configureScope);
+
+ ///
+ /// Configures the scope through the callback.
+ ///
+ ///
+ /// object someValue = ...;
+ /// SentrySdk.ConfigureScope(static (scope, arg) => scope.SetExtra("key", arg), someValue);
+ ///
+ ///
+ ///
+ /// The configure scope callback.
+ /// The argument to pass to the configure scope callback.
+ public static void ConfigureScope(Action configureScope, TArg arg)
+ => Sentry.SentrySdk.ConfigureScope(configureScope, arg);
+
+ ///
+ /// Configures the scope through the callback asynchronously.
+ ///
+ /// The configure scope callback.
+ /// A task that completes when the callback is done or a completed task if the SDK is disabled.
+ [DebuggerStepThrough]
+ public static Task ConfigureScopeAsync(Func configureScope)
+ => Sentry.SentrySdk.ConfigureScopeAsync(configureScope);
+
+ ///
+ /// Configures the scope through the callback asynchronously.
+ ///
+ ///
+ /// object someValue = ...;
+ /// SentrySdk.ConfigureScopeAsync(static async (scope, arg) =>
+ /// {
+ /// scope.SetExtra("key", arg);
+ /// }, someValue);
+ ///
+ ///
+ ///
+ /// The configure scope callback.
+ /// The argument to pass to the configure scope callback.
+ /// A task that completes when the callback is done or a completed task if the SDK is disabled.
+ [DebuggerStepThrough]
+ public static Task ConfigureScopeAsync(Func configureScope, TArg arg)
+ => Sentry.SentrySdk.ConfigureScopeAsync(configureScope, arg);
+
+ ///
+ /// Sets a tag on the current scope.
+ ///
+ [DebuggerStepThrough]
+ public static void SetTag(string key, string value)
+ => Sentry.SentrySdk.SetTag(key, value);
+
+ ///
+ /// Removes a tag from the current scope.
+ ///
+ [DebuggerStepThrough]
+ public static void UnsetTag(string key)
+ => Sentry.SentrySdk.UnsetTag(key);
+
+ ///
+ [DebuggerStepThrough]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static bool CaptureEnvelope(Envelope envelope)
+ => Sentry.SentrySdk.CaptureEnvelope(envelope);
+
+ ///
+ /// Captures the event, passing a hint, using the specified scope.
+ ///
+ /// The event.
+ /// The scope.
+ /// a hint for the event.
+ /// The Id of the event.
+ [DebuggerStepThrough]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static SentryId CaptureEvent(SentryEvent evt, Scope? scope = null, SentryHint? hint = null)
+ => Sentry.SentrySdk.CaptureEvent(evt, scope, hint);
+
+ ///
+ /// Captures an event with a configurable scope.
+ ///
+ ///
+ /// This allows modifying a scope without affecting other events.
+ ///
+ /// The event.
+ /// The callback to configure the scope.
+ /// The Id of the event.
+ [DebuggerStepThrough]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static SentryId CaptureEvent(SentryEvent evt, Action configureScope)
+ => Sentry.SentrySdk.CaptureEvent(evt, null, configureScope);
+
+ ///
+ /// Captures an event with a configurable scope.
+ ///
+ ///
+ /// This allows modifying a scope without affecting other events.
+ ///
+ /// The event.
+ /// An optional hint to be provided with the event
+ /// The callback to configure the scope.
+ /// The Id of the event.
+ [DebuggerStepThrough]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static SentryId CaptureEvent(SentryEvent evt, SentryHint? hint, Action configureScope)
+ => Sentry.SentrySdk.CaptureEvent(evt, hint, configureScope);
+
+ ///
+ /// Captures the exception.
+ ///
+ /// The exception.
+ /// The Id of the event.
+ [DebuggerStepThrough]
+ public static SentryId CaptureException(Exception exception)
+ => Sentry.SentrySdk.CaptureException(exception);
+
+ ///
+ /// Captures the exception with a configurable scope.
+ ///
+ ///
+ /// This allows modifying a scope without affecting other events.
+ ///
+ /// The exception.
+ /// The callback to configure the scope.
+ /// The Id of the event.
+ [DebuggerStepThrough]
+ public static SentryId CaptureException(Exception exception, Action configureScope)
+ => Sentry.SentrySdk.CaptureException(exception, configureScope);
+
+ ///
+ /// Captures the message.
+ ///
+ /// The message to send.
+ /// The message level.
+ /// The Id of the event.
+ [DebuggerStepThrough]
+ public static SentryId CaptureMessage(string message, SentryLevel level = SentryLevel.Info)
+ => Sentry.SentrySdk.CaptureMessage(message, level);
+
+ ///
+ /// Captures the message with a configurable scope.
+ ///
+ ///
+ /// This allows modifying a scope without affecting other events.
+ ///
+ /// The message to send.
+ /// The callback to configure the scope.
+ /// The message level.
+ /// The Id of the event.
+ [DebuggerStepThrough]
+ public static SentryId CaptureMessage(string message, Action configureScope, SentryLevel level = SentryLevel.Info)
+ => Sentry.SentrySdk.CaptureMessage(message, configureScope, level);
+
+ ///
+ /// Captures feedback from the user.
+ ///
+ [DebuggerStepThrough]
+ public static void CaptureFeedback(SentryFeedback feedback, Action configureScope, SentryHint? hint = null)
+ => Sentry.SentrySdk.CaptureFeedback(feedback, configureScope, hint);
+
+ ///
+ /// Captures feedback from the user.
+ ///
+ [DebuggerStepThrough]
+ public static void CaptureFeedback(SentryFeedback feedback, Scope? scope = null, SentryHint? hint = null)
+ => Sentry.SentrySdk.CaptureFeedback(feedback, scope, hint);
+
+ ///
+ /// Captures feedback from the user.
+ ///
+ [DebuggerStepThrough]
+ public static void CaptureFeedback(string message, string? contactEmail = null, string? name = null,
+ string? replayId = null, string? url = null, SentryId? associatedEventId = null, Scope? scope = null,
+ SentryHint? hint = null)
+ => Sentry.SentrySdk.CaptureFeedback(new SentryFeedback(message, contactEmail, name, replayId, url, associatedEventId),
+ scope, hint);
+
+ ///
+ /// Captures a user feedback.
+ ///
+ /// The user feedback to send to Sentry.
+ [DebuggerStepThrough]
+ [Obsolete("Use CaptureFeedback instead.")]
+ public static void CaptureUserFeedback(UserFeedback userFeedback)
+ => Sentry.SentrySdk.CaptureUserFeedback(userFeedback);
+
+ ///
+ /// Captures a user feedback.
+ ///
+ /// The event Id.
+ /// The user email.
+ /// The user comments.
+ /// The optional username.
+ [DebuggerStepThrough]
+ [Obsolete("Use CaptureFeedback instead.")]
+ public static void CaptureUserFeedback(SentryId eventId, string email, string comments, string? name = null)
+ => Sentry.SentrySdk.CaptureUserFeedback(new UserFeedback(eventId, name, email, comments));
+
+ ///
+ /// Captures a transaction.
+ ///
+ ///
+ /// Note: this method is NOT meant to be called from user code!
+ /// Instead, call on the transaction.
+ ///
+ [DebuggerStepThrough]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static void CaptureTransaction(SentryTransaction transaction)
+ => Sentry.SentrySdk.CaptureTransaction(transaction);
+
+ ///
+ /// Captures a transaction.
+ ///
+ ///
+ /// Note: this method is NOT meant to be called from user code!
+ /// Instead, call on the transaction.
+ ///
+ [DebuggerStepThrough]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static void CaptureTransaction(SentryTransaction transaction, Scope? scope, SentryHint? hint)
+ => Sentry.SentrySdk.CaptureTransaction(transaction, scope, hint);
+
+ ///
+ /// Captures a session update.
+ ///
+ [DebuggerStepThrough]
+ public static void CaptureSession(SessionUpdate sessionUpdate)
+ => Sentry.SentrySdk.CaptureSession(sessionUpdate);
+
+ ///
+ /// Captures a check-in.
+ ///
+ ///
+ /// Capturing a check-in returns an ID. The ID can be used to update the status. I.e. to update a check-in you
+ /// captured from `CheckInStatus.InProgress` to `CheckInStatus.Ok`.
+ ///
+ /// The monitor slug of the check-in.
+ /// The status of the check-in.
+ /// The associated with the check-in.
+ /// The duration of the check-in.
+ /// The scope of the check-in.
+ /// The optional monitor config used to create a Check-In programmatically.
+ /// The ID of the check-in.
+ [DebuggerStepThrough]
+ public static SentryId CaptureCheckIn(string monitorSlug,
+ CheckInStatus status,
+ SentryId? sentryId = null,
+ TimeSpan? duration = null,
+ Scope? scope = null,
+ Action? configureMonitorOptions = null)
+ => Sentry.SentrySdk.CaptureCheckIn(
+ monitorSlug,
+ status,
+ sentryId,
+ duration,
+ scope,
+ configureMonitorOptions);
+
+ ///
+ /// Starts a transaction.
+ ///
+ [DebuggerStepThrough]
+ public static ITransactionTracer StartTransaction(
+ ITransactionContext context,
+ IReadOnlyDictionary customSamplingContext)
+ => Sentry.SentrySdk.StartTransaction(context, customSamplingContext);
+
+ ///
+ /// Starts a transaction.
+ ///
+ [DebuggerStepThrough]
+ internal static ITransactionTracer StartTransaction(
+ ITransactionContext context,
+ IReadOnlyDictionary customSamplingContext,
+ DynamicSamplingContext? dynamicSamplingContext)
+ => Sentry.SentrySdk.StartTransaction(context, customSamplingContext, dynamicSamplingContext);
+
+ ///
+ /// Starts a transaction.
+ ///
+ [DebuggerStepThrough]
+ public static ITransactionTracer StartTransaction(ITransactionContext context)
+ => Sentry.SentrySdk.StartTransaction(context);
+
+ ///
+ /// Starts a transaction.
+ ///
+ [DebuggerStepThrough]
+ public static ITransactionTracer StartTransaction(string name, string operation)
+ => Sentry.SentrySdk.StartTransaction(name, operation);
+
+ ///
+ /// Starts a transaction.
+ ///
+ [DebuggerStepThrough]
+ public static ITransactionTracer StartTransaction(string name, string operation, string? description)
+ => Sentry.SentrySdk.StartTransaction(name, operation, description);
+
+ ///
+ /// Starts a transaction.
+ ///
+ [DebuggerStepThrough]
+ public static ITransactionTracer StartTransaction(string name, string operation, SentryTraceHeader traceHeader)
+ => Sentry.SentrySdk.StartTransaction(name, operation, traceHeader);
+
+ ///
+ /// Binds specified exception the specified span.
+ ///
+ ///
+ /// This method is used internally and is not meant for public use.
+ ///
+ [DebuggerStepThrough]
+ public static void BindException(Exception exception, ISpan span)
+ => Sentry.SentrySdk.BindException(exception, span);
+
+ ///
+ /// Gets the last active span.
+ ///
+ [DebuggerStepThrough]
+ public static ISpan? GetSpan()
+ => Sentry.SentrySdk.GetSpan();
+
+ ///
+ /// Gets the Sentry trace header of the parent that allows tracing across services
+ ///
+ [DebuggerStepThrough]
+ public static SentryTraceHeader? GetTraceHeader()
+ => Sentry.SentrySdk.GetTraceHeader();
+
+ ///
+ /// Gets the Sentry "baggage" header that allows tracing across services
+ ///
+ [DebuggerStepThrough]
+ public static BaggageHeader? GetBaggage()
+ => Sentry.SentrySdk.GetBaggage();
+
+ ///
+ /// Continues a trace based on HTTP header values provided as strings.
+ ///
+ ///
+ /// If no "sentry-trace" header is provided a random trace ID and span ID is created.
+ ///
+ [DebuggerStepThrough]
+ public static TransactionContext ContinueTrace(
+ string? traceHeader,
+ string? baggageHeader,
+ string? name = null,
+ string? operation = null)
+ => Sentry.SentrySdk.ContinueTrace(traceHeader, baggageHeader, name, operation);
+
+ ///
+ /// Continues a trace based on HTTP header values.
+ ///
+ ///
+ /// If no "sentry-trace" header is provided a random trace ID and span ID is created.
+ ///
+ [DebuggerStepThrough]
+ public static TransactionContext ContinueTrace(
+ SentryTraceHeader? traceHeader,
+ BaggageHeader? baggageHeader,
+ string? name = null,
+ string? operation = null)
+ => Sentry.SentrySdk.ContinueTrace(traceHeader, baggageHeader, name, operation);
+
+ ///
+ [DebuggerStepThrough]
+ public static void StartSession()
+ => Sentry.SentrySdk.StartSession();
+
+ ///
+ [DebuggerStepThrough]
+ public static void EndSession(SessionEndStatus status = SessionEndStatus.Exited)
+ => Sentry.SentrySdk.EndSession(status);
+
+ ///
+ [DebuggerStepThrough]
+ public static void PauseSession()
+ => Sentry.SentrySdk.PauseSession();
+
+ ///
+ [DebuggerStepThrough]
+ public static void ResumeSession()
+ => Sentry.SentrySdk.ResumeSession();
+
+ ///
+ /// Deliberately crashes an application, which is useful for testing and demonstration purposes.
+ ///
+ ///
+ /// The method is marked obsolete only to discourage accidental misuse.
+ /// We do not intend to remove it.
+ ///
+ [Obsolete("WARNING: This method deliberately causes a crash, and should not be used in a real application.")]
+ public static void CauseCrash(CrashType crashType) => Sentry.SentrySdk.CauseCrash(crashType);
+}
diff --git a/src/Sentry.Unity/SentryUnity.cs b/src/Sentry.Unity/SentrySdk.cs
similarity index 74%
rename from src/Sentry.Unity/SentryUnity.cs
rename to src/Sentry.Unity/SentrySdk.cs
index c3b69806e..d5034a267 100644
--- a/src/Sentry.Unity/SentryUnity.cs
+++ b/src/Sentry.Unity/SentrySdk.cs
@@ -1,14 +1,14 @@
using System;
using System.ComponentModel;
using Sentry.Extensibility;
-using UnityEngine;
+using Sentry.Unity.NativeUtils;
namespace Sentry.Unity;
///
/// Sentry Unity initialization class.
///
-public static class SentryUnity
+public static partial class SentrySdk
{
private static SentryUnitySdk? UnitySdk;
@@ -33,7 +33,23 @@ public static void Init(SentryUnityOptions options)
{
if (UnitySdk is not null)
{
- options.DiagnosticLogger?.LogWarning("The SDK has already been initialized.");
+ options.LogWarning("The SDK has already been initialized. Skipping initialization.");
+ }
+
+ try
+ {
+ // Since this mutates the options (i.e. adding scope observer) we have to invoke before initializing the SDK
+ options.PlatformConfiguration.Invoke(options);
+ }
+ catch (DllNotFoundException e)
+ {
+ options.LogError(e,
+ "Sentry native-error capture configuration failed to load a native library. This usually " +
+ "means the library is missing from the application bundle or the installation directory.");
+ }
+ catch (Exception e)
+ {
+ options.LogError(e, "Sentry native error capture configuration failed.");
}
UnitySdk = SentryUnitySdk.Init(options);
@@ -50,7 +66,7 @@ public static void Close()
}
///
- /// Represents the crash state of the games's previous run.
+ /// Represents the crash state of the game's previous run.
/// Used to determine if the last execution terminated normally or crashed.
///
public enum CrashedLastRun
diff --git a/src/Sentry.Unity/SentryUnityOptions.cs b/src/Sentry.Unity/SentryUnityOptions.cs
index ed1184db2..94bed43f8 100644
--- a/src/Sentry.Unity/SentryUnityOptions.cs
+++ b/src/Sentry.Unity/SentryUnityOptions.cs
@@ -4,6 +4,7 @@
using System.Text.RegularExpressions;
using Sentry.Unity.Integrations;
using Sentry.Extensibility;
+using Sentry.Unity.NativeUtils;
using UnityEngine;
using CompressionLevel = System.IO.Compression.CompressionLevel;
@@ -294,6 +295,9 @@ internal string? DefaultUserId
internal List SdkIntegrationNames { get; set; } = new();
+ internal ISentryUnityInfo UnityInfo { get; private set; }
+ internal Action PlatformConfiguration { get; private set; }
+
public SentryUnityOptions() : this(false, ApplicationAdapter.Instance) { }
internal SentryUnityOptions(bool isBuilding, IApplication application, ISentryUnityInfo? unityInfo = null) :
@@ -301,8 +305,14 @@ internal SentryUnityOptions(bool isBuilding, IApplication application, ISentryUn
{ }
// For testing
- internal SentryUnityOptions(SentryMonoBehaviour behaviour, IApplication application, bool isBuilding, ISentryUnityInfo? unityInfo = null)
+ private SentryUnityOptions(SentryMonoBehaviour behaviour, IApplication application, bool isBuilding, ISentryUnityInfo? unityInfo)
{
+ // This should never happen. The PlatformServices are set through the RuntimeLoad attribute in 'SentryInitialization.cs'
+ // and required to be present.
+ UnityInfo = unityInfo ?? SentryPlatformServices.UnityInfo;
+ PlatformConfiguration = SentryPlatformServices.PlatformConfiguration
+ ?? throw new ArgumentNullException(nameof(SentryPlatformServices.PlatformConfiguration), "PlatformConfiguration is null.");
+
// IL2CPP doesn't support Process.GetCurrentProcess().StartupTime
DetectStartupTime = StartupTimeDetectionMode.Fast;
diff --git a/src/Sentry.Unity/SentryUnityOptionsExtensions.cs b/src/Sentry.Unity/SentryUnityOptionsExtensions.cs
index 773e45391..ea97618f5 100644
--- a/src/Sentry.Unity/SentryUnityOptionsExtensions.cs
+++ b/src/Sentry.Unity/SentryUnityOptionsExtensions.cs
@@ -63,16 +63,9 @@ internal static void SetupUnityLogging(this SentryUnityOptions options)
}
}
- internal static void AddIl2CppExceptionProcessor(this SentryUnityOptions options, ISentryUnityInfo unityInfo)
+ internal static void AddIl2CppExceptionProcessor(this SentryUnityOptions options)
{
- if (unityInfo.Il2CppMethods is not null)
- {
- options.AddExceptionProcessor(new UnityIl2CppEventExceptionProcessor(options, unityInfo));
- }
- else
- {
- options.DiagnosticLogger?.LogWarning("Failed to find required IL2CPP methods - Skipping line number support");
- }
+ options.AddExceptionProcessor(new UnityIl2CppEventExceptionProcessor(options));
}
///
diff --git a/src/Sentry.Unity/SentryUnitySDK.cs b/src/Sentry.Unity/SentryUnitySdk.cs
similarity index 86%
rename from src/Sentry.Unity/SentryUnitySDK.cs
rename to src/Sentry.Unity/SentryUnitySdk.cs
index 2228ef8db..052139275 100644
--- a/src/Sentry.Unity/SentryUnitySDK.cs
+++ b/src/Sentry.Unity/SentryUnitySdk.cs
@@ -49,7 +49,11 @@ private SentryUnitySdk(SentryUnityOptions options)
}
}
- unitySdk._dotnetSdk = SentrySdk.Init(options);
+ unitySdk._dotnetSdk = Sentry.SentrySdk.Init(options);
+
+ // We can safely call this during initialization. If the SDK self-initialized we're right on time. If the SDK
+ // was initialized manually, the RuntimeOnLoad attributes already triggered, making this call a no-op.
+ StartupTracingIntegration.StartTracing();
// We can safely call this during initialization. If the SDK self-initialized we're right on time. If the SDK
// was initialized manually, the RuntimeOnLoad attributes already triggered, making this call a no-op.
@@ -57,7 +61,7 @@ private SentryUnitySdk(SentryUnityOptions options)
if (options.NativeContextWriter is { } contextWriter)
{
- SentrySdk.ConfigureScope((scope) =>
+ Sentry.SentrySdk.CurrentHub.ConfigureScope((scope) =>
{
var task = Task.Run(() => contextWriter.Write(scope)).ContinueWith(t =>
{
@@ -104,18 +108,18 @@ public void Close()
}
}
- public SentryUnity.CrashedLastRun CrashedLastRun()
+ 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.");
- return SentryUnity.CrashedLastRun.Unknown;
+ return SentrySdk.CrashedLastRun.Unknown;
}
return _options.CrashedLastRun.Invoke()
- ? SentryUnity.CrashedLastRun.Crashed
- : SentryUnity.CrashedLastRun.DidNotCrash;
+ ? SentrySdk.CrashedLastRun.Crashed
+ : SentrySdk.CrashedLastRun.DidNotCrash;
}
public void CaptureFeedback(string message, string? email, string? name, bool addScreenshot)
@@ -135,7 +139,6 @@ public void CaptureFeedback(string message, string? email, string? name, bool ad
"image/jpeg"))
: null;
-
- SentrySdk.CaptureFeedback(message, email, name, hint: hint);
+ Sentry.SentrySdk.CurrentHub.CaptureFeedback(message, email, name, hint: hint);
}
}
diff --git a/src/Sentry.Unity/WebGL/SentryWebGL.cs b/src/Sentry.Unity/WebGL/SentryWebGL.cs
index c46f68888..a863a23b5 100644
--- a/src/Sentry.Unity/WebGL/SentryWebGL.cs
+++ b/src/Sentry.Unity/WebGL/SentryWebGL.cs
@@ -1,4 +1,5 @@
using Sentry.Extensibility;
+using Sentry.Unity.NativeUtils;
using UnityEngine.Analytics;
namespace Sentry.Unity.WebGL;
diff --git a/src/sentry-dotnet b/src/sentry-dotnet
index 997dcae2f..2aa2bb216 160000
--- a/src/sentry-dotnet
+++ b/src/sentry-dotnet
@@ -1 +1 @@
-Subproject commit 997dcae2fc7c52d0c49c1f412cee329aeb1c8d29
+Subproject commit 2aa2bb21648ef7645c13fc263449de2c326fdd1d
diff --git a/test/Scripts.Integration.Test/Scripts/SmokeTester.cs b/test/Scripts.Integration.Test/Scripts/SmokeTester.cs
index edd0a4430..16becdfdf 100644
--- a/test/Scripts.Integration.Test/Scripts/SmokeTester.cs
+++ b/test/Scripts.Integration.Test/Scripts/SmokeTester.cs
@@ -8,6 +8,7 @@
using System.Threading;
using System.Threading.Tasks;
using Sentry;
+using Sentry.Unity;
using UnityEngine;
using Debug = UnityEngine.Debug;
diff --git a/test/Sentry.Unity.Tests/ContextWriterTests.cs b/test/Sentry.Unity.Tests/ContextWriterTests.cs
index ca9d40c11..b432c5ea0 100644
--- a/test/Sentry.Unity.Tests/ContextWriterTests.cs
+++ b/test/Sentry.Unity.Tests/ContextWriterTests.cs
@@ -79,7 +79,7 @@ public void Arguments()
// act
MainThreadData.SentrySystemInfo = sysInfo;
- SentryUnity.Init(options);
+ SentrySdk.Init(options);
Assert.IsTrue(context.SyncFinished.WaitOne(TimeSpan.FromSeconds(10)));
// assert
diff --git a/test/Sentry.Unity.Tests/IntegrationTests.cs b/test/Sentry.Unity.Tests/IntegrationTests.cs
index 10e7e4924..23f9def4f 100644
--- a/test/Sentry.Unity.Tests/IntegrationTests.cs
+++ b/test/Sentry.Unity.Tests/IntegrationTests.cs
@@ -34,7 +34,7 @@ public void TearDown()
{
if (SentrySdk.IsEnabled)
{
- SentryUnity.Close();
+ SentrySdk.Close();
}
}
@@ -338,7 +338,7 @@ internal static IEnumerator SetupSceneCoroutine(string sceneName, [CallerMemberN
internal IDisposable InitSentrySdk(Action? configure = null)
{
- SentryUnity.Init(options =>
+ SentrySdk.Init(options =>
{
options.Dsn = "https://e9ee299dbf554dfd930bc5f3c90d5d4b@o447951.ingest.sentry.io/4504604988538880";
options.CreateHttpMessageHandler = () => _testHttpClientHandler;
diff --git a/test/Sentry.Unity.Tests/ScreenshotEventProcessorTests.cs b/test/Sentry.Unity.Tests/ScreenshotEventProcessorTests.cs
index fcad4a82a..36252b96e 100644
--- a/test/Sentry.Unity.Tests/ScreenshotEventProcessorTests.cs
+++ b/test/Sentry.Unity.Tests/ScreenshotEventProcessorTests.cs
@@ -24,7 +24,7 @@ public void TearDown()
{
if (SentrySdk.IsEnabled)
{
- SentryUnity.Close();
+ SentrySdk.Close();
}
}
diff --git a/test/Sentry.Unity.Tests/SentryPlatformServicesTests.cs b/test/Sentry.Unity.Tests/SentryPlatformServicesTests.cs
new file mode 100644
index 000000000..8957e396c
--- /dev/null
+++ b/test/Sentry.Unity.Tests/SentryPlatformServicesTests.cs
@@ -0,0 +1,20 @@
+using NUnit.Framework;
+using Sentry.Unity.NativeUtils;
+
+namespace Sentry.Unity.Tests;
+
+[SetUpFixture]
+public class SentryPlatformServicesTests
+{
+ [OneTimeSetUp]
+ public void OneTimeSetUp()
+ {
+ SentryPlatformServices.UnityInfo = new TestUnityInfo();
+ }
+
+ [OneTimeTearDown]
+ public void OneTimeTearDown()
+ {
+
+ }
+}
diff --git a/test/Sentry.Unity.Tests/SentryTests.cs b/test/Sentry.Unity.Tests/SentryTests.cs
index d0d8494c1..4761751a3 100644
--- a/test/Sentry.Unity.Tests/SentryTests.cs
+++ b/test/Sentry.Unity.Tests/SentryTests.cs
@@ -6,7 +6,7 @@ public static class SentryTests
{
internal static IDisposable InitSentrySdk(Action? configure = null, TestHttpClientHandler? testHttpClientHandler = null)
{
- SentryUnity.Init(options =>
+ SentrySdk.Init(options =>
{
options.Dsn = "https://e9ee299dbf554dfd930bc5f3c90d5d4b@o447951.ingest.sentry.io/4504604988538880";
if (testHttpClientHandler is not null)
diff --git a/test/Sentry.Unity.Tests/SentryUnityTests.cs b/test/Sentry.Unity.Tests/SentryUnityTests.cs
index 0c1c2f9e9..e3326cad6 100644
--- a/test/Sentry.Unity.Tests/SentryUnityTests.cs
+++ b/test/Sentry.Unity.Tests/SentryUnityTests.cs
@@ -18,7 +18,7 @@ public void TearDown()
{
if (SentrySdk.IsEnabled)
{
- SentryUnity.Close();
+ SentrySdk.Close();
}
}
@@ -72,7 +72,7 @@ public void SentryUnity_OptionsValid_Initializes()
Dsn = TestDsn
};
- SentryUnity.Init(options);
+ SentrySdk.Init(options);
Assert.IsTrue(SentrySdk.IsEnabled);
}
@@ -83,7 +83,7 @@ public void SentryUnity_OptionsInvalid_DoesNotInitialize()
var options = new SentryUnityOptions();
// Even tho the defaults are set the DSN is missing making the options invalid for initialization
- SentryUnity.Init(options);
+ SentrySdk.Init(options);
Assert.IsFalse(SentrySdk.IsEnabled);
}
@@ -99,8 +99,8 @@ public void Init_MultipleTimes_LogsWarning()
DiagnosticLogger = testLogger,
};
- SentryUnity.Init(options);
- SentryUnity.Init(options);
+ SentrySdk.Init(options);
+ SentrySdk.Init(options);
Assert.IsTrue(testLogger.Logs.Any(log =>
log.logLevel == SentryLevel.Warning &&
@@ -111,13 +111,13 @@ public void Init_MultipleTimes_LogsWarning()
public void GetLastRunState_WithoutInit_ReturnsUnknown()
{
// Make sure SDK is closed
- SentryUnity.Close();
+ SentrySdk.Close();
// Act
- var result = SentryUnity.GetLastRunState();
+ var result = SentrySdk.GetLastRunState();
// Assert
- Assert.AreEqual(SentryUnity.CrashedLastRun.Unknown, result);
+ Assert.AreEqual(SentrySdk.CrashedLastRun.Unknown, result);
}
[Test]
@@ -131,11 +131,11 @@ public void GetLastRunState_WhenCrashed_ReturnsCrashed()
};
// Act
- SentryUnity.Init(options);
- var result = SentryUnity.GetLastRunState();
+ SentrySdk.Init(options);
+ var result = SentrySdk.GetLastRunState();
// Assert
- Assert.AreEqual(SentryUnity.CrashedLastRun.Crashed, result);
+ Assert.AreEqual(SentrySdk.CrashedLastRun.Crashed, result);
}
[Test]
@@ -149,11 +149,11 @@ public void GetLastRunState_WhenNotCrashed_ReturnsDidNotCrash()
};
// Act
- SentryUnity.Init(options);
- var result = SentryUnity.GetLastRunState();
+ SentrySdk.Init(options);
+ var result = SentrySdk.GetLastRunState();
// Assert
- Assert.AreEqual(SentryUnity.CrashedLastRun.DidNotCrash, result);
+ Assert.AreEqual(SentrySdk.CrashedLastRun.DidNotCrash, result);
}
[Test]
@@ -167,10 +167,10 @@ public void GetLastRunState_WithNullDelegate_ReturnsUnknown()
};
// Act
- SentryUnity.Init(options);
- var result = SentryUnity.GetLastRunState();
+ SentrySdk.Init(options);
+ var result = SentrySdk.GetLastRunState();
// Assert
- Assert.AreEqual(SentryUnity.CrashedLastRun.Unknown, result);
+ Assert.AreEqual(SentrySdk.CrashedLastRun.Unknown, result);
}
}
diff --git a/test/Sentry.Unity.Tests/SessionIntegrationTests.cs b/test/Sentry.Unity.Tests/SessionIntegrationTests.cs
index 6fb7aee3f..d53f81698 100644
--- a/test/Sentry.Unity.Tests/SessionIntegrationTests.cs
+++ b/test/Sentry.Unity.Tests/SessionIntegrationTests.cs
@@ -27,7 +27,7 @@ public IEnumerator SessionIntegration_Init_SentryMonoBehaviourCreated()
internal IDisposable InitSentrySdk(Action? configure = null)
{
- SentryUnity.Init(options =>
+ SentrySdk.Init(options =>
{
options.Dsn = "https://e9ee299dbf554dfd930bc5f3c90d5d4b@o447951.ingest.sentry.io/4504604988538880";
configure?.Invoke(options);
diff --git a/test/Sentry.Unity.Tests/StartupTracingIntegrationTests.cs b/test/Sentry.Unity.Tests/StartupTracingIntegrationTests.cs
index 403b7d8e9..d72cdeafb 100644
--- a/test/Sentry.Unity.Tests/StartupTracingIntegrationTests.cs
+++ b/test/Sentry.Unity.Tests/StartupTracingIntegrationTests.cs
@@ -173,7 +173,7 @@ public void StartTracing_WhenNotAllowed_DoesNotCreateTransaction()
[Test]
public void StartupSequence_CallsInOrder_CreatesAndFinishesTransactionCorrectly()
{
- SentrySdk.UseHub(_fixture.Hub);
+ Sentry.SentrySdk.UseHub(_fixture.Hub);
_fixture.Application.IsEditor = false;
_fixture.Application.Platform = RuntimePlatform.WindowsPlayer;
StartupTracingIntegration.Application = _fixture.Application;
diff --git a/test/Sentry.Unity.Tests/TraceGenerationIntegrationTests.cs b/test/Sentry.Unity.Tests/TraceGenerationIntegrationTests.cs
index 751c35d5a..91189d44e 100644
--- a/test/Sentry.Unity.Tests/TraceGenerationIntegrationTests.cs
+++ b/test/Sentry.Unity.Tests/TraceGenerationIntegrationTests.cs
@@ -29,7 +29,7 @@ private class Fixture
public void SetUp()
{
_fixture.TestHub = new TestHub();
- SentrySdk.UseHub(_fixture.TestHub);
+ Sentry.SentrySdk.UseHub(_fixture.TestHub);
}
[Test]
diff --git a/test/Sentry.Unity.Tests/UnityBadGatewayExceptionFilterTests.cs b/test/Sentry.Unity.Tests/UnityBadGatewayExceptionFilterTests.cs
index bfab5d235..8ec055f79 100644
--- a/test/Sentry.Unity.Tests/UnityBadGatewayExceptionFilterTests.cs
+++ b/test/Sentry.Unity.Tests/UnityBadGatewayExceptionFilterTests.cs
@@ -26,7 +26,7 @@ public void Filter_FiltersBadGatewayExceptionsOfTypeException() =>
internal IDisposable InitSentrySdk(Action? configure = null)
{
- SentryUnity.Init(options =>
+ SentrySdk.Init(options =>
{
options.Dsn = "https://e9ee299dbf554dfd930bc5f3c90d5d4b@o447951.ingest.sentry.io/4504604988538880";
options.CreateHttpMessageHandler = () => _testHttpClientHandler;
diff --git a/test/Sentry.Unity.Tests/UnityEventScopeTests.cs b/test/Sentry.Unity.Tests/UnityEventScopeTests.cs
index 303bcace5..2085e1682 100644
--- a/test/Sentry.Unity.Tests/UnityEventScopeTests.cs
+++ b/test/Sentry.Unity.Tests/UnityEventScopeTests.cs
@@ -37,7 +37,7 @@ public void TearDown()
if (SentrySdk.IsEnabled)
{
- SentryUnity.Close();
+ SentrySdk.Close();
}
}
@@ -66,7 +66,7 @@ public void SentrySdkCaptureEvent_OnNotUIThread_Succeeds()
Debug = true,
DiagnosticLogger = _testLogger
};
- SentryUnity.Init(options);
+ SentrySdk.Init(options);
var sentryEvent = new SentryEvent
{
@@ -82,7 +82,11 @@ public void SentrySdkCaptureEvent_OnNotUIThread_Succeeds()
SentrySdk.FlushAsync(TimeSpan.FromSeconds(1)).GetAwaiter().GetResult();
// assert
- var logsFound = _testLogger.Logs.Where(log => log.logLevel >= SentryLevel.Warning && log.message != "Cache directory is empty.").ToList();
+ var logsFound = _testLogger.Logs.Where(log =>
+ log.logLevel >= SentryLevel.Warning &&
+ // Ignore expected or harmless warnings
+ log.message != "Cache directory is empty." &&
+ log.message != "The SDK's Platform Services have not been set up. Native support will be limited.").ToList();
Assert.Zero(logsFound.Count, FormatLogs(logsFound));
@@ -123,7 +127,7 @@ public void SentrySdkCaptureEvent(bool captureOnUiThread)
MainThreadData.SentrySystemInfo = systemInfo;
MainThreadData.CollectData();
- SentryUnity.Init(options);
+ SentrySdk.Init(options);
// Act
var @event = new SentryEvent
diff --git a/test/Sentry.Unity.Tests/ViewHierarchyEventProcessorTests.cs b/test/Sentry.Unity.Tests/ViewHierarchyEventProcessorTests.cs
index 85adba0b8..93ec9dfc4 100644
--- a/test/Sentry.Unity.Tests/ViewHierarchyEventProcessorTests.cs
+++ b/test/Sentry.Unity.Tests/ViewHierarchyEventProcessorTests.cs
@@ -26,7 +26,7 @@ public void TearDown()
{
if (SentrySdk.IsEnabled)
{
- SentryUnity.Close();
+ SentrySdk.Close();
}
}
diff --git a/test/Sentry.Unity.iOS.Tests/SentryNativeIosTests.cs b/test/Sentry.Unity.iOS.Tests/SentryNativeIosTests.cs
index 133cef2ab..c79c78753 100644
--- a/test/Sentry.Unity.iOS.Tests/SentryNativeIosTests.cs
+++ b/test/Sentry.Unity.iOS.Tests/SentryNativeIosTests.cs
@@ -1,20 +1,30 @@
using System;
using NUnit.Framework;
+using Sentry.Unity.NativeUtils;
+using Sentry.Unity.Tests.Stubs;
using UnityEngine;
namespace Sentry.Unity.iOS.Tests;
public class SentryNativeCocoaTests
{
+ [TearDown]
+ public void TearDown()
+ {
+ SentryPlatformServices.UnityInfo = null;
+ }
+
[Test]
public void Configure_DefaultConfiguration_iOS()
{
- var unityInfo = new TestUnityInfo { IL2CPP = false };
+ SentryPlatformServices.UnityInfo = new TestUnityInfo { IL2CPP = false };
+ ;
var options = new SentryUnityOptions();
+
// Note: can't test iOS - throws because it tries to call SentryCocoaBridgeProxy.Init()
// but the bridge isn't loaded now...
Assert.Throws(() =>
- SentryNativeCocoa.Configure(options, unityInfo, RuntimePlatform.IPhonePlayer));
+ SentryNativeCocoa.Configure(options, RuntimePlatform.IPhonePlayer));
}
[Test]
@@ -22,7 +32,7 @@ public void Configure_NativeSupportDisabled_iOS()
{
var unityInfo = new TestUnityInfo(true, false, false) { IL2CPP = false };
var options = new SentryUnityOptions { IosNativeSupportEnabled = false };
- SentryNativeCocoa.Configure(options, unityInfo, RuntimePlatform.IPhonePlayer);
+ SentryNativeCocoa.Configure(options, RuntimePlatform.IPhonePlayer);
Assert.Null(options.ScopeObserver);
Assert.Null(options.CrashedLastRun);
Assert.False(options.EnableScopeSync);