-
-
Notifications
You must be signed in to change notification settings - Fork 55
/
Copy pathSentryNativeAndroid.cs
178 lines (147 loc) · 7.27 KB
/
SentryNativeAndroid.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
using System;
using Sentry.Extensibility;
using Sentry.Unity.Integrations;
using UnityEngine;
using UnityEngine.Analytics;
namespace Sentry.Unity.Android;
/// <summary>
/// Access to the Sentry native support on Android.
/// </summary>
public static class SentryNativeAndroid
{
internal static IJniExecutor? JniExecutor;
internal static ISentryJava SentryJava = new SentryJava();
/// <summary>
/// Configures the native Android support.
/// </summary>
/// <param name="options">The Sentry Unity options to use.</param>
public static void Configure(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo)
{
options.DiagnosticLogger?.LogInfo("Attempting to configure native support via the Android SDK");
if (!options.AndroidNativeSupportEnabled)
{
options.DiagnosticLogger?.LogDebug("Native support is disabled for Android");
return;
}
options.DiagnosticLogger?.LogDebug("Checking whether the Android SDK is present.");
if (!SentryJava.IsSentryJavaPresent())
{
options.DiagnosticLogger?.LogError("Android Native Support has been enabled but the " +
"Android SDK is missing. This could have been caused by a mismatching" +
"build time / runtime configuration. Please make sure you have " +
"Android Native Support enabled during build time.");
return;
}
JniExecutor ??= new JniExecutor(options.DiagnosticLogger);
options.DiagnosticLogger?.LogDebug("Checking whether the Android SDK has already been initialized");
if (SentryJava.IsEnabled(JniExecutor, TimeSpan.FromMilliseconds(200)))
{
options.DiagnosticLogger?.LogDebug("The Android SDK is already initialized");
}
else
{
options.DiagnosticLogger?.LogInfo("Initializing the Android SDK");
// Local testing had Init at an average of about 25ms.
SentryJava.Init(JniExecutor, options, TimeSpan.FromMilliseconds(200));
options.DiagnosticLogger?.LogDebug("Validating Android SDK initialization");
if (!SentryJava.IsEnabled(JniExecutor, TimeSpan.FromMilliseconds(200)))
{
options.DiagnosticLogger?.LogError("Failed to initialize Android Native Support");
return;
}
}
options.DiagnosticLogger?.LogDebug("Configuring scope sync");
options.NativeContextWriter = new NativeContextWriter(JniExecutor, SentryJava);
options.ScopeObserver = new AndroidJavaScopeObserver(options, JniExecutor);
options.EnableScopeSync = true;
options.CrashedLastRun = () =>
{
options.DiagnosticLogger?.LogDebug("Checking for `CrashedLastRun`");
var crashedLastRun = SentryJava.CrashedLastRun(JniExecutor);
if (crashedLastRun is null)
{
// Could happen if the Android SDK wasn't initialized before the .NET layer.
options.DiagnosticLogger?
.LogWarning(
"Unclear from the native SDK if the previous run was a crash. Assuming it was not.");
crashedLastRun = false;
}
else
{
options.DiagnosticLogger?
.LogDebug("Native Android SDK reported: 'crashedLastRun': '{0}'", crashedLastRun);
}
return crashedLastRun.Value;
};
try
{
options.DiagnosticLogger?.LogDebug("Reinstalling native backend.");
// At this point Unity has taken the signal handler and will not invoke the original handler (Sentry)
// So we register our backend once more to make sure user-defined data is available in the crash report.
SentryNative.ReinstallBackend();
}
catch (Exception e)
{
options.DiagnosticLogger?.LogError(
e, "Failed to reinstall backend. Captured native crashes will miss scope data and tag.");
}
options.NativeSupportCloseCallback = () => Close(options, sentryUnityInfo);
options.DiagnosticLogger?.LogDebug("Fetching installation ID");
options.DefaultUserId = SentryJava.GetInstallationId(JniExecutor);
if (string.IsNullOrEmpty(options.DefaultUserId))
{
// In case we can't get an installation ID we create one and sync that down to the native layer
options.DiagnosticLogger?.LogDebug(
"Failed to fetch 'Installation ID' from the native SDK. Creating new 'Default User ID'.");
// We fall back to Unity's Analytics Session Info: https://docs.unity3d.com/ScriptReference/Analytics.AnalyticsSessionInfo-userId.html
// It's a randomly generated GUID that gets created immediately after installation helping
// to identify the same instance of the game
options.DefaultUserId = AnalyticsSessionInfo.userId;
if (options.DefaultUserId is not null)
{
options.ScopeObserver.SetUser(new SentryUser { Id = options.DefaultUserId });
}
else
{
options.DiagnosticLogger?.LogDebug("Failed to create new 'Default User ID'.");
}
}
options.DiagnosticLogger?.LogInfo("Successfully configured the Android SDK");
}
public static void SetTraceId(SentryUnityOptions options)
{
options.DiagnosticLogger?.LogInfo("Setting Trace ID");
var traceId = SentrySdk.GetTraceHeader()?.TraceId;
if (traceId is null)
{
options.DiagnosticLogger?.LogInfo("fucking trace id is null");
}
else
{
options.DiagnosticLogger?.LogInfo("Setting the trace ID on the native layer {0}", traceId);
JniExecutor ??= new JniExecutor(options.DiagnosticLogger);
SentryJava.ContinueTrace(JniExecutor, traceId.ToString());
}
}
/// <summary>
/// Closes the native Android support.
/// </summary>
public static void Close(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo) =>
Close(options, sentryUnityInfo, ApplicationAdapter.Instance.Platform);
internal static void Close(SentryUnityOptions options, ISentryUnityInfo sentryUnityInfo, RuntimePlatform platform)
{
options.DiagnosticLogger?.LogInfo("Attempting to close the Android SDK");
if (!sentryUnityInfo.IsNativeSupportEnabled(options, platform) || !SentryJava.IsSentryJavaPresent())
{
options.DiagnosticLogger?.LogDebug("Android Native Support is not enable. Skipping closing the Android SDK");
return;
}
// Sentry Native is initialized and closed by the Java SDK, no need to call into it directly
options.DiagnosticLogger?.LogDebug("Closing the Android SDK");
// This is an edge-case where the Android SDK has been enabled and setup during build-time but is being
// shut down at runtime. In this case Configure() has not been called and there is no JniExecutor yet
JniExecutor ??= new JniExecutor(options.DiagnosticLogger);
SentryJava?.Close(JniExecutor);
JniExecutor.Dispose();
}
}