Skip to content

Commit 1d4fe53

Browse files
authored
fix: Async Android scope sync (#2107)
1 parent ec7f381 commit 1d4fe53

14 files changed

+465
-499
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
### Features
1010

11+
- Drastically improved performance of scope sync when targeting Android ([#2107](https://github.com/getsentry/sentry-unity/pull/2107))
1112
- When running on Android, Windows or Linux, the SDK now links errors and events originating on different layers (managed, native errors) via `trace ID` ([#1997](https://github.com/getsentry/sentry-unity/pull/1997), [#2089](https://github.com/getsentry/sentry-unity/pull/2089))
1213
- The SDK now reports the game's name as part of the app context ([2083](https://github.com/getsentry/sentry-unity/pull/2083))
1314
- The SDK now reports the active scene's name as part of the `Unity Context` ([2084](https://github.com/getsentry/sentry-unity/pull/2084))

src/Sentry.Unity.Android/AndroidJavaScopeObserver.cs

Lines changed: 17 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -9,96 +9,31 @@ namespace Sentry.Unity.Android;
99
/// <see href="https://github.com/getsentry/sentry-java"/>
1010
internal class AndroidJavaScopeObserver : ScopeObserver
1111
{
12-
private readonly IJniExecutor _jniExecutor;
12+
private ISentryJava _sentryJava;
1313

14-
public AndroidJavaScopeObserver(SentryOptions options, IJniExecutor jniExecutor) : base("Android", options)
14+
public AndroidJavaScopeObserver(SentryOptions options, ISentryJava sentryJava) : base("Android", options)
1515
{
16-
_jniExecutor = jniExecutor;
16+
_sentryJava = sentryJava;
1717
}
1818

19-
private static AndroidJavaObject GetSentryJava() => new AndroidJavaClass("io.sentry.Sentry");
19+
public override void AddBreadcrumbImpl(Breadcrumb breadcrumb) =>
20+
_sentryJava.AddBreadcrumb(breadcrumb);
2021

21-
private static AndroidJavaObject GetInternalSentryJava() => new AndroidJavaClass("io.sentry.android.core.InternalSentrySdk");
22+
public override void SetExtraImpl(string key, string? value) =>
23+
_sentryJava.SetExtra(key, value);
2224

23-
public override void AddBreadcrumbImpl(Breadcrumb breadcrumb)
24-
{
25-
_jniExecutor.Run(() =>
26-
{
27-
using var sentry = GetSentryJava();
28-
using var javaBreadcrumb = new AndroidJavaObject("io.sentry.Breadcrumb");
29-
javaBreadcrumb.Set("message", breadcrumb.Message);
30-
javaBreadcrumb.Set("type", breadcrumb.Type);
31-
javaBreadcrumb.Set("category", breadcrumb.Category);
32-
using var javaLevel = breadcrumb.Level.ToJavaSentryLevel();
33-
javaBreadcrumb.Set("level", javaLevel);
34-
sentry.CallStatic("addBreadcrumb", javaBreadcrumb, null);
35-
});
36-
}
25+
public override void SetTagImpl(string key, string value) =>
26+
_sentryJava.SetTag(key, value);
3727

38-
public override void SetExtraImpl(string key, string? value)
39-
{
40-
_jniExecutor.Run(() =>
41-
{
42-
using var sentry = GetSentryJava();
43-
sentry.CallStatic("setExtra", key, value);
44-
});
45-
}
46-
public override void SetTagImpl(string key, string value)
47-
{
48-
_jniExecutor.Run(() =>
49-
{
50-
using var sentry = GetSentryJava();
51-
sentry.CallStatic("setTag", key, value);
52-
});
53-
}
28+
public override void UnsetTagImpl(string key) =>
29+
_sentryJava.UnsetTag(key);
5430

55-
public override void UnsetTagImpl(string key)
56-
{
57-
_jniExecutor.Run(() =>
58-
{
59-
using var sentry = GetSentryJava();
60-
sentry.CallStatic("removeTag", key);
61-
});
62-
}
31+
public override void SetUserImpl(SentryUser user) =>
32+
_sentryJava.SetUser(user);
6333

64-
public override void SetUserImpl(SentryUser user)
65-
{
66-
_jniExecutor.Run(() =>
67-
{
68-
AndroidJavaObject? javaUser = null;
69-
try
70-
{
71-
javaUser = new AndroidJavaObject("io.sentry.protocol.User");
72-
javaUser.Set("email", user.Email);
73-
javaUser.Set("id", user.Id);
74-
javaUser.Set("username", user.Username);
75-
javaUser.Set("ipAddress", user.IpAddress);
76-
using var sentry = GetSentryJava();
77-
sentry.CallStatic("setUser", javaUser);
78-
}
79-
finally
80-
{
81-
javaUser?.Dispose();
82-
}
83-
});
84-
}
34+
public override void UnsetUserImpl() =>
35+
_sentryJava.UnsetUser();
8536

86-
public override void UnsetUserImpl()
87-
{
88-
_jniExecutor.Run(() =>
89-
{
90-
using var sentry = GetSentryJava();
91-
sentry.CallStatic("setUser", null);
92-
});
93-
}
94-
95-
public override void SetTraceImpl(SentryId traceId, SpanId spanId)
96-
{
97-
_jniExecutor.Run(() =>
98-
{
99-
using var sentry = GetInternalSentryJava();
100-
// We have to explicitly cast to `(Double?)`
101-
sentry.CallStatic("setTrace", traceId.ToString(), spanId.ToString(), (Double?)null, (Double?)null);
102-
});
103-
}
37+
public override void SetTraceImpl(SentryId traceId, SpanId spanId) =>
38+
_sentryJava.SetTrace(traceId, spanId);
10439
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System;
2+
using Sentry.Extensibility;
3+
using UnityEngine;
4+
5+
namespace Sentry.Unity.Android;
6+
7+
internal class AndroidOptionsConfiguration : AndroidJavaProxy
8+
{
9+
private readonly Action<AndroidJavaObject> _callback;
10+
private readonly IDiagnosticLogger? _logger;
11+
12+
public AndroidOptionsConfiguration(Action<AndroidJavaObject> callback, IDiagnosticLogger? logger)
13+
: base("io.sentry.Sentry$OptionsConfiguration")
14+
{
15+
_callback = callback;
16+
_logger = logger;
17+
}
18+
19+
public override AndroidJavaObject? Invoke(string methodName, AndroidJavaObject[] args)
20+
{
21+
try
22+
{
23+
if (methodName != "configure" || args.Length != 1)
24+
{
25+
throw new Exception($"Invalid invocation: {methodName}({args.Length} args)");
26+
}
27+
28+
_callback(args[0]);
29+
}
30+
catch (Exception e)
31+
{
32+
_logger?.LogError(e, "Error invoking '{0}'.", methodName);
33+
}
34+
return null;
35+
}
36+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using UnityEngine;
2+
3+
namespace Sentry.Unity.Android;
4+
5+
public interface IAndroidJNI
6+
{
7+
public void AttachCurrentThread();
8+
public void DetachCurrentThread();
9+
}
10+
11+
public class AndroidJNIAdapter : IAndroidJNI
12+
{
13+
public static readonly AndroidJNIAdapter Instance = new();
14+
15+
public void AttachCurrentThread() => AndroidJNI.AttachCurrentThread();
16+
17+
public void DetachCurrentThread() => AndroidJNI.DetachCurrentThread();
18+
}

src/Sentry.Unity.Android/IJniExecutor.cs

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/Sentry.Unity.Android/JniExecutor.cs

Lines changed: 0 additions & 182 deletions
This file was deleted.

src/Sentry.Unity.Android/NativeContextWriter.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ namespace Sentry.Unity.Android;
44

55
internal class NativeContextWriter : ContextWriter
66
{
7-
private readonly IJniExecutor _jniExecutor;
87
private readonly ISentryJava _sentryJava;
98

10-
public NativeContextWriter(IJniExecutor jniExecutor, ISentryJava sentryJava)
9+
public NativeContextWriter(ISentryJava sentryJava)
1110
{
12-
_jniExecutor = jniExecutor;
1311
_sentryJava = sentryJava;
1412
}
1513

@@ -53,7 +51,6 @@ protected override void WriteScope(
5351
// the "unity" context, but it doesn't seem so useful and the effort to do is larger because there's no
5452
// class for it in Java - not sure how we could add a generic context object in Java...
5553
_sentryJava.WriteScope(
56-
_jniExecutor,
5754
GpuId,
5855
GpuName,
5956
GpuVendorName,

0 commit comments

Comments
 (0)