Skip to content
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

feat: Dedicated Server support #1468

Merged
merged 15 commits into from
Nov 7, 2023
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

## Feature

- Added the dedicated server platforms to the known platforms to prevent the SDK from interpreting them as restricted platforms (i.e. disabling offline caching, session tracking) ([#1468](https://github.com/getsentry/sentry-unity/pull/1468))

### Dependencies

- Bump CLI from v2.21.1 to v2.21.2 ([#1454](https://github.com/getsentry/sentry-unity/pull/1454))
Expand Down
9 changes: 7 additions & 2 deletions package-dev/Plugins/macOS/SentryNativeBridge.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,15 @@ int SentryNativeBridgeLoadLibrary()
if (loadStatus == -1) {
loadStatus = 0; // init to "error"
do {
// The default path from the executable to the dylib within a .app
void *dylib = dlopen("@executable_path/../PlugIns/Sentry.dylib", RTLD_LAZY);
if (!dylib) {
NSLog(@"Sentry (bridge): Couldn't load Sentry.dylib - dlopen() failed");
break;
// Fallback path for the dedicated server setup
dylib = dlopen("@executable_path/PlugIns/Sentry.dylib", RTLD_LAZY);
if (!dylib) {
NSLog(@"Sentry (bridge): Couldn't load Sentry.dylib - dlopen() failed");
break;
}
}

LOAD_CLASS_OR_BREAK(SentrySDK)
Expand Down
62 changes: 61 additions & 1 deletion package-dev/Runtime/SentryInitialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public static void Init()
#elif SENTRY_NATIVE_ANDROID
SentryNativeAndroid.Configure(options, sentryUnityInfo);
#elif SENTRY_NATIVE
SentryNative.Configure(options);
SentryNative.Configure(options, sentryUnityInfo);
#elif SENTRY_WEBGL
SentryWebGL.Configure(options);
#endif
Expand Down Expand Up @@ -269,5 +269,65 @@ private static void Il2CppNativeStackTraceShim(IntPtr exc, out IntPtr addresses,
#endif
#pragma warning restore 8632
#endif

public bool IsKnownPlatform()
{
var platform = Application.platform;
return
platform == RuntimePlatform.Android ||
platform == RuntimePlatform.IPhonePlayer ||
platform == RuntimePlatform.WindowsEditor ||
platform == RuntimePlatform.WindowsPlayer ||
platform == RuntimePlatform.OSXEditor ||
platform == RuntimePlatform.OSXPlayer ||
platform == RuntimePlatform.LinuxEditor ||
platform == RuntimePlatform.LinuxPlayer ||
platform == RuntimePlatform.WebGLPlayer
#if UNITY_2021_3_OR_NEWER
||
platform == RuntimePlatform.WindowsServer ||
platform == RuntimePlatform.OSXServer ||
platform == RuntimePlatform.LinuxServer
#endif
;
}

public bool IsLinux()
{
var platform = Application.platform;
return
platform == RuntimePlatform.LinuxPlayer
#if UNITY_2021_3_OR_NEWER
|| platform == RuntimePlatform.LinuxServer
#endif
;
}

public bool IsNativeSupportEnabled(SentryUnityOptions options, RuntimePlatform platform)
{
switch (platform)
{
case RuntimePlatform.Android:
return options.AndroidNativeSupportEnabled;
case RuntimePlatform.IPhonePlayer:
return options.IosNativeSupportEnabled;
case RuntimePlatform.WindowsPlayer:
return options.WindowsNativeSupportEnabled;
case RuntimePlatform.OSXPlayer:
return options.MacosNativeSupportEnabled;
case RuntimePlatform.LinuxPlayer:
return options.LinuxNativeSupportEnabled;
#if UNITY_2021_3_OR_NEWER
case RuntimePlatform.WindowsServer:
return options.WindowsNativeSupportEnabled;
case RuntimePlatform.OSXServer:
return options.MacosNativeSupportEnabled;
case RuntimePlatform.LinuxServer:
return options.LinuxNativeSupportEnabled;
#endif
default:
return false;
}
}
}
}
2 changes: 1 addition & 1 deletion src/Sentry.Unity.Editor/SentryScriptableObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ internal static (SentryUnityOptions?, SentryCliOptions?) ConfiguredBuildTimeOpti
SentryUnityOptions? options = null;
if (scriptableOptions is not null)
{
options = scriptableOptions.ToSentryUnityOptions(isBuilding: true);
options = scriptableOptions.ToSentryUnityOptions(isBuilding: true, unityInfo: null);
// Must be non-nullable in the interface otherwise Unity script compilation fails...
cliOptions ??= ScriptableObject.CreateInstance<SentryCliOptions>();
var setupScript = scriptableOptions.BuildTimeOptionsConfiguration;
Expand Down
85 changes: 42 additions & 43 deletions src/Sentry.Unity.Native/SentryNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,59 +17,58 @@ public static class SentryNative
/// Configures the native SDK.
/// </summary>
/// <param name="options">The Sentry Unity options to use.</param>
public static void Configure(SentryUnityOptions options)
/// <param name="sentryUnityInfo">Infos about the current Unity environment</param>
public static void Configure(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo)
{
if (ApplicationAdapter.Instance.Platform switch
if (!sentryUnityInfo.IsNativeSupportEnabled(options, ApplicationAdapter.Instance.Platform))
vaind marked this conversation as resolved.
Show resolved Hide resolved
{
RuntimePlatform.WindowsPlayer => options.WindowsNativeSupportEnabled,
RuntimePlatform.LinuxPlayer => options.LinuxNativeSupportEnabled,
_ => false,
})
options.DiagnosticLogger?.LogDebug("Native support is disabled for '{0}'.", ApplicationAdapter.Instance.Platform);
return;
}

if (!SentryNativeBridge.Init(options, sentryUnityInfo))
{
if (!SentryNativeBridge.Init(options))
{
options.DiagnosticLogger?
.LogWarning("Sentry native initialization failed - native crashes are not captured.");
return;
}
options.DiagnosticLogger?
.LogWarning("Sentry native initialization failed - native crashes are not captured.");
return;
}

ApplicationAdapter.Instance.Quitting += () =>
{
options.DiagnosticLogger?.LogDebug("Closing the sentry-native SDK");
SentryNativeBridge.Close();
};
options.ScopeObserver = new NativeScopeObserver(options);
options.EnableScopeSync = true;
options.NativeContextWriter = new NativeContextWriter();
ApplicationAdapter.Instance.Quitting += () =>
{
options.DiagnosticLogger?.LogDebug("Closing the sentry-native SDK");
SentryNativeBridge.Close();
};
options.ScopeObserver = new NativeScopeObserver(options);
options.EnableScopeSync = true;
options.NativeContextWriter = new NativeContextWriter();

// Use AnalyticsSessionInfo.userId as the default UserID in native & dotnet
options.DefaultUserId = AnalyticsSessionInfo.userId;
if (options.DefaultUserId is not null)
{
options.ScopeObserver.SetUser(new User { Id = options.DefaultUserId });
}
// Use AnalyticsSessionInfo.userId as the default UserID in native & dotnet
options.DefaultUserId = AnalyticsSessionInfo.userId;
if (options.DefaultUserId is not null)
{
options.ScopeObserver.SetUser(new User { Id = options.DefaultUserId });
}

// Note: we must actually call the function now and on every other call use the value we get here.
// Additionally, we cannot call this multiple times for the same directory, because the result changes
// on subsequent runs. Therefore, we cache the value during the whole runtime of the application.
var cacheDirectory = SentryNativeBridge.GetCacheDirectory(options);
var crashedLastRun = false;
// In the event the SDK is re-initialized with a different path on disk, we need to track which ones were already read
// Similarly we need to cache the value of each call since a subsequent call would return a different value
// as the file used on disk to mark it as crashed is deleted after we read it.
lock (PerDirectoryCrashInfo)
// Note: we must actually call the function now and on every other call use the value we get here.
// Additionally, we cannot call this multiple times for the same directory, because the result changes
// on subsequent runs. Therefore, we cache the value during the whole runtime of the application.
var cacheDirectory = SentryNativeBridge.GetCacheDirectory(options);
var crashedLastRun = false;
// In the event the SDK is re-initialized with a different path on disk, we need to track which ones were already read
// Similarly we need to cache the value of each call since a subsequent call would return a different value
// as the file used on disk to mark it as crashed is deleted after we read it.
lock (PerDirectoryCrashInfo)
{
if (!PerDirectoryCrashInfo.TryGetValue(cacheDirectory, out crashedLastRun))
{
if (!PerDirectoryCrashInfo.TryGetValue(cacheDirectory, out crashedLastRun))
{
crashedLastRun = SentryNativeBridge.HandleCrashedLastRun(options);
PerDirectoryCrashInfo.Add(cacheDirectory, crashedLastRun);
crashedLastRun = SentryNativeBridge.HandleCrashedLastRun(options);
PerDirectoryCrashInfo.Add(cacheDirectory, crashedLastRun);

options.DiagnosticLogger?
.LogDebug("Native SDK reported: 'crashedLastRun': '{0}'", crashedLastRun);
}
options.DiagnosticLogger?
.LogDebug("Native SDK reported: 'crashedLastRun': '{0}'", crashedLastRun);
}
options.CrashedLastRun = () => crashedLastRun;
}
options.CrashedLastRun = () => crashedLastRun;
}
}
}
4 changes: 2 additions & 2 deletions src/Sentry.Unity.Native/SentryNativeBridge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ public static class SentryNativeBridge

public static bool CrashedLastRun;

public static bool Init(SentryUnityOptions options)
public static bool Init(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo)
{
_isLinux = ApplicationAdapter.Instance.Platform is RuntimePlatform.LinuxPlayer;
_isLinux = sentryUnityInfo.IsLinux();

var cOptions = sentry_options_new();

Expand Down
42 changes: 19 additions & 23 deletions src/Sentry.Unity.iOS/SentryNativeCocoa.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using Sentry.Extensibility;
using Sentry.PlatformAbstractions;
using Sentry.Unity.Integrations;
using UnityEngine;

Expand All @@ -13,36 +15,30 @@ public static class SentryNativeCocoa
/// Configures the native support.
/// </summary>
/// <param name="options">The Sentry Unity options to use.</param>
/// <param name="sentryUnityInfo">Infos about the current Unity environment</param>
public static void Configure(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo) =>
Configure(options, sentryUnityInfo, ApplicationAdapter.Instance.Platform);

internal static void Configure(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo, RuntimePlatform platform)
{
switch (platform)
if (!sentryUnityInfo.IsNativeSupportEnabled(options, platform))
{
case RuntimePlatform.IPhonePlayer:
if (!options.IosNativeSupportEnabled)
{
return;
}
options.ScopeObserver = new NativeScopeObserver("iOS", options);
break;
case RuntimePlatform.OSXPlayer:
if (!options.MacosNativeSupportEnabled)
{
return;
}
if (!SentryCocoaBridgeProxy.Init(options))
{
options.DiagnosticLogger?.LogWarning("Failed to initialize the native SDK");
return;
}
options.ScopeObserver = new NativeScopeObserver("macOS", options);
break;
default:
options.DiagnosticLogger?
.LogWarning("Cocoa SentryNative.Configure() called for unsupported platform: '{0}'", platform);
options.DiagnosticLogger?.LogDebug("Native support is not enabled for: '{0}'", platform);
return;
}

if (platform == RuntimePlatform.IPhonePlayer)
{
options.ScopeObserver = new NativeScopeObserver("iOS", options);
}
else
{
if (!SentryCocoaBridgeProxy.Init(options))
{
options.DiagnosticLogger?.LogWarning("Failed to initialize the native SDK");
return;
}
options.ScopeObserver = new NativeScopeObserver("macOS", options);
}

options.NativeContextWriter = new NativeContextWriter();
Expand Down
4 changes: 4 additions & 0 deletions src/Sentry.Unity/ISentryUnityInfo.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
using System;
using UnityEngine;

namespace Sentry.Unity
{
public interface ISentryUnityInfo
{
public bool IL2CPP { get; }
public Il2CppMethods? Il2CppMethods { get; }
public bool IsKnownPlatform();
public bool IsLinux();
public bool IsNativeSupportEnabled(SentryUnityOptions options, RuntimePlatform platform);
}

public class Il2CppMethods
Expand Down
Loading
Loading