-
-
Notifications
You must be signed in to change notification settings - Fork 56
fix: Moved late option mutation into Init
#2239
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
base: fix/initialization
Are you sure you want to change the base?
Conversation
…tsentry/sentry-unity into fix/new-init-options-creation
if (options.AttachViewHierarchy) | ||
{ | ||
options.AddEventProcessor(new ViewHierarchyEventProcessor(options)); | ||
} | ||
if (options.AttachScreenshot) | ||
{ | ||
options.AddEventProcessor(new ScreenshotEventProcessor(options)); | ||
} | ||
|
||
if (!application.IsEditor && options.Il2CppLineNumberSupportEnabled && unityInfo is not null) | ||
{ | ||
options.AddIl2CppExceptionProcessor(unityInfo); | ||
} | ||
|
||
HandlePlatformRestrictedOptions(options, unityInfo, application); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This got moved into SentryUnitySdk.Init
to keep the SDKs behaviour consistent.
@@ -252,41 +246,6 @@ internal SentryUnityOptions ToSentryUnityOptions(bool isBuilding, ISentryUnityIn | |||
return options; | |||
} | |||
|
|||
internal void HandlePlatformRestrictedOptions(SentryUnityOptions options, ISentryUnityInfo? unityInfo, IApplication application) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above. Even if users call Init
the SDK should make an effort not to crash the game.
internal SentryUnityOptions(bool isBuilding, IApplication application, ISentryUnityInfo? unityInfo = null) : | ||
this(SentryMonoBehaviour.Instance, application, isBuilding, unityInfo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got rid of a redundant internal
constructor.
internal static void AddIl2CppExceptionProcessor(this SentryUnityOptions options, ISentryUnityInfo unityInfo) | ||
{ | ||
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"); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to Init
.
internal static void HandleWindowsPlayer(SentryUnitySdk unitySdk, SentryUnityOptions options) | ||
{ | ||
// On Windows-Standalone, we disable cache dir in case multiple app instances run over the same path. | ||
// Note: we cannot use a named Mutex, because Unity doesn't support it. Instead, we create a file with `FileShare.None`. | ||
// https://forum.unity.com/threads/unsupported-internal-call-for-il2cpp-mutex-createmutex_internal-named-mutexes-are-not-supported.387334/ | ||
if (ApplicationAdapter.Instance.Platform is not RuntimePlatform.WindowsPlayer || | ||
options.CacheDirectoryPath is null) | ||
{ | ||
return; | ||
} | ||
|
||
try | ||
{ | ||
unitySdk._lockFile = new FileStream(Path.Combine(options.CacheDirectoryPath, "sentry-unity.lock"), FileMode.OpenOrCreate, | ||
FileAccess.ReadWrite, FileShare.None); | ||
} | ||
catch (Exception ex) | ||
{ | ||
options.DiagnosticLogger?.LogWarning("An exception was thrown while trying to " + | ||
"acquire a lockfile on the config directory: .NET event cache will be disabled.", ex); | ||
options.CacheDirectoryPath = null; | ||
options.AutoSessionTracking = false; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To keep the Init
more readable.
if (!ApplicationAdapter.Instance.IsEditor && | ||
(SentryPlatformServices.UnityInfo?.IL2CPP ?? false) && | ||
options.Il2CppLineNumberSupportEnabled) | ||
{ | ||
if (SentryPlatformServices.UnityInfo.Il2CppMethods is not null) | ||
{ | ||
options.AddExceptionProcessor(new UnityIl2CppEventExceptionProcessor(options)); | ||
} | ||
else | ||
{ | ||
options.DiagnosticLogger?.LogWarning("Failed to find required IL2CPP methods - Skipping line number support"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The IL2CPP Exception Processor
is critical and "dangerous" as it calls into the IL2CPP backend and requires certain functions to be there. These functions change depending of Unity versions and are provided via IUnityInfo
. As such, this does not get added by default but late during Init with extensive checks.
"kinda" 😅 |
"Unity IL2CPP methods are not available."); | ||
|
||
// We're throwing here but this should never happen. We're validating UnityInfo before adding the processor. | ||
UnityInfo = SentryPlatformServices.UnityInfo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great! this was my only feedback in the other PR, validation that we're at the right state before going ahead
Also note that you copy a reference to use the same/consistent reference. This also means there's no path for a user to change these values after-the-fact.
But I understand that's the goal, and we then should follow this pattern when it makes sense. Instead of accessing the static mutable property in many places try to keep it to a minimum.
internal SentryUnityOptions(bool isBuilding, IApplication application, ISentryUnityInfo? unityInfo = null) : | ||
this(SentryMonoBehaviour.Instance, application, isBuilding, unityInfo) | ||
public SentryUnityOptions() : | ||
this(false, ApplicationAdapter.Instance, SentryPlatformServices.UnityInfo, SentryMonoBehaviour.Instance) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we access SentryPlatformServices.UnityInfo
here but also in other places where they take SentryOptions but also ISentryUnityInfo
. This makes it a lot more confusing.
Can we then only get it from here?
Once you do new Options
we read SentryPlatformServices.UnityInfo
and if it's null, we throw. Or go into the mode where this doesn't exist if that's a thing. But from that point any access to UnityInfo is through options. If you find references of the getter for SentryPlatformServices.UnityInfo
you'd only see tests and this contructor.
// Some integrations are controlled through a flag and opt-in. Adding these integrations late so we have the | ||
// same behaviour whether we're self or manually initializing | ||
HandleLateIntegrations(options); | ||
HandlePlatformRestrictedOptions(options, SentryPlatformServices.UnityInfo); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
example where we take options and also access the static mutable public property
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw, I'm saying "static public mutable property" a lot because it's a thing you should be aware, I didn't read it btw just got the first link:
https://www.reddit.com/r/learnprogramming/comments/7nzlec/why_are_mutable_static_variables_bad/
@@ -137,4 +125,77 @@ public void CaptureFeedback(string message, string? email, string? name, bool ad | |||
|
|||
Sentry.SentrySdk.CurrentHub.CaptureFeedback(message, email, name, hint: hint); | |||
} | |||
|
|||
internal static void HandleWindowsPlayer(SentryUnitySdk unitySdk, SentryUnityOptions options) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this method is called. "Handle"? It seems it's "Setting Up"? or Initializing?
It's being called by Init
so perhaps InitWindowsPlayer
?
} | ||
} | ||
|
||
internal static void HandlePlatformRestrictedOptions(SentryUnityOptions options, ISentryUnityInfo? unityInfo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again method name is off, seems the guard is: IsKnownPlatform
so how about:
InitUnknownPlatform
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit odd to see on the callsite:
InitWindows
InitOtherPlatform
Since you'd expect the guards to be outside the functions as the function names already 'declare' what they are supposed to be for.
But this is all internal code so not worth splitting hairs 🙈 And I don't have a great suggestion on how to improve this other than maybe trying yet other method names "TryInit" or whatever
} | ||
|
||
[Test] | ||
public void HandlePlatformRestrictedOptions_KnownPlatform_SetsRestrictedOptions() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was lost on purpose?
@@ -127,18 +127,6 @@ public void ToSentryUnityOptions_HasOptionsConfiguration_GetsCalled(bool isBuild | |||
Assert.AreEqual(optionsConfiguration.GotCalled, !isBuilding); | |||
} | |||
|
|||
[Test] | |||
public void ToSentryUnityOptions_UnknownPlatforms_DoesNotAccessDisk() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was also deleted on purpsoe?
This is a follow-up on #2227 as this was getting already kinda big.
Goal
This PR moves adding integrations that depend on certain flags into the
Init
call to be added "late" to keep the SDKs behavious consistent between self and manual initialization.Context
There are two ways
SentryUnityOptions
gets created:.asset
and creates new options from the ScriptableObjectIn both cases, changes to the options need to be made at the same time. This leaves either the constructor or right before initialization.
This means that handling those "late" integrations moved out of
ScriptableUnityOptions
- which is not getting called when initializing manually - into the initialization flow.Note
One could point out the inconsistency how integrations get controlled and added, i.e.
AnrIntegration
,ScreenshotProcessor
andViewHierarchyProcessor
. We could make changes to this but we'd require users to update fromto
which is not all that much better.