Skip to content

Commit f1482f4

Browse files
committed
refactor: SentryNative integration
1 parent 15b1e21 commit f1482f4

13 files changed

+296
-344
lines changed

flutter/lib/src/native/sentry_native.dart

+74-61
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,17 @@ import 'dart:async';
33
import 'package:meta/meta.dart';
44

55
import '../../sentry_flutter.dart';
6-
import 'sentry_native_channel.dart';
6+
import 'sentry_native_binding.dart';
77

8-
/// [SentryNative] holds state that it fetches from to the native SDKs. Always
9-
/// use the shared instance with [SentryNative()].
8+
/// [SentryNative] holds state that it fetches from to the native SDKs.
9+
/// It forwards to platform-specific implementations of [SentryNativeBinding].
10+
/// Any errors are logged and ignored.
1011
@internal
1112
class SentryNative {
12-
SentryNative._();
13+
final SentryOptions _options;
14+
final SentryNativeBinding _binding;
1315

14-
static final SentryNative _instance = SentryNative._();
15-
16-
SentryNativeChannel? _nativeChannel;
17-
18-
factory SentryNative() {
19-
return _instance;
20-
}
21-
22-
SentryNativeChannel? get nativeChannel => _instance._nativeChannel;
23-
24-
/// Provide [nativeChannel] for native communication.
25-
set nativeChannel(SentryNativeChannel? nativeChannel) {
26-
_instance._nativeChannel = nativeChannel;
27-
}
16+
SentryNative(this._options, this._binding);
2817

2918
// AppStart
3019

@@ -41,75 +30,99 @@ class SentryNative {
4130
/// Fetch [NativeAppStart] from native channels. Can only be called once.
4231
Future<NativeAppStart?> fetchNativeAppStart() async {
4332
_didFetchAppStart = true;
44-
return await _nativeChannel?.fetchNativeAppStart();
33+
return _invoke("fetchNativeAppStart", _binding.fetchNativeAppStart);
4534
}
4635

4736
// NativeFrames
4837

49-
Future<void> beginNativeFramesCollection() async {
50-
await _nativeChannel?.beginNativeFrames();
51-
}
38+
Future<void> beginNativeFramesCollection() =>
39+
_invoke("beginNativeFrames", _binding.beginNativeFrames);
5240

53-
Future<NativeFrames?> endNativeFramesCollection(SentryId traceId) async {
54-
return await _nativeChannel?.endNativeFrames(traceId);
55-
}
41+
Future<NativeFrames?> endNativeFramesCollection(SentryId traceId) =>
42+
_invoke("endNativeFrames", () => _binding.endNativeFrames(traceId));
5643

5744
// Scope
5845

59-
Future<void> setContexts(String key, dynamic value) async {
60-
return await _nativeChannel?.setContexts(key, value);
61-
}
46+
Future<void> setContexts(String key, dynamic value) =>
47+
_invoke("setContexts", () => _binding.setContexts(key, value));
6248

63-
Future<void> removeContexts(String key) async {
64-
return await _nativeChannel?.removeContexts(key);
65-
}
49+
Future<void> removeContexts(String key) =>
50+
_invoke("removeContexts", () => _binding.removeContexts(key));
6651

67-
Future<void> setUser(SentryUser? sentryUser) async {
68-
return await _nativeChannel?.setUser(sentryUser);
69-
}
52+
Future<void> setUser(SentryUser? sentryUser) =>
53+
_invoke("setUser", () => _binding.setUser(sentryUser));
7054

71-
Future<void> addBreadcrumb(Breadcrumb breadcrumb) async {
72-
return await _nativeChannel?.addBreadcrumb(breadcrumb);
73-
}
55+
Future<void> addBreadcrumb(Breadcrumb breadcrumb) =>
56+
_invoke("addBreadcrumb", () => _binding.addBreadcrumb(breadcrumb));
7457

75-
Future<void> clearBreadcrumbs() async {
76-
return await _nativeChannel?.clearBreadcrumbs();
77-
}
58+
Future<void> clearBreadcrumbs() =>
59+
_invoke("clearBreadcrumbs", _binding.clearBreadcrumbs);
7860

79-
Future<void> setExtra(String key, dynamic value) async {
80-
return await _nativeChannel?.setExtra(key, value);
81-
}
61+
Future<void> setExtra(String key, dynamic value) =>
62+
_invoke("setExtra", () => _binding.setExtra(key, value));
8263

83-
Future<void> removeExtra(String key) async {
84-
return await _nativeChannel?.removeExtra(key);
85-
}
64+
Future<void> removeExtra(String key) =>
65+
_invoke("removeExtra", () => _binding.removeExtra(key));
8666

87-
Future<void> setTag(String key, String value) async {
88-
return await _nativeChannel?.setTag(key, value);
89-
}
67+
Future<void> setTag(String key, String value) =>
68+
_invoke("setTag", () => _binding.setTag(key, value));
9069

91-
Future<void> removeTag(String key) async {
92-
return await _nativeChannel?.removeTag(key);
93-
}
70+
Future<void> removeTag(String key) =>
71+
_invoke("removeTag", () => _binding.removeTag(key));
9472

95-
Future<int?> startProfiler(SentryId traceId) async {
96-
return _nativeChannel?.startProfiler(traceId);
97-
}
73+
int? startProfiler(SentryId traceId) =>
74+
_invokeSync("startProfiler", () => _binding.startProfiler(traceId));
9875

99-
Future<void> discardProfiler(SentryId traceId) async {
100-
return _nativeChannel?.discardProfiler(traceId);
101-
}
76+
Future<void> discardProfiler(SentryId traceId) =>
77+
_invoke("discardProfiler", () => _binding.discardProfiler(traceId));
10278

10379
Future<Map<String, dynamic>?> collectProfile(
104-
SentryId traceId, int startTimeNs, int endTimeNs) async {
105-
return _nativeChannel?.collectProfile(traceId, startTimeNs, endTimeNs);
106-
}
80+
SentryId traceId, int startTimeNs, int endTimeNs) =>
81+
_invoke("collectProfile",
82+
() => _binding.collectProfile(traceId, startTimeNs, endTimeNs));
10783

10884
/// Reset state
10985
void reset() {
11086
appStartEnd = null;
11187
_didFetchAppStart = false;
11288
}
89+
90+
// Helpers
91+
Future<T?> _invoke<T>(
92+
String nativeMethodName, Future<T?> Function() fn) async {
93+
try {
94+
return await fn();
95+
} catch (error, stackTrace) {
96+
_logError(nativeMethodName, error, stackTrace);
97+
// ignore: invalid_use_of_internal_member
98+
if (_options.devMode) {
99+
rethrow;
100+
}
101+
return null;
102+
}
103+
}
104+
105+
T? _invokeSync<T>(String nativeMethodName, T? Function() fn) {
106+
try {
107+
return fn();
108+
} catch (error, stackTrace) {
109+
_logError(nativeMethodName, error, stackTrace);
110+
// ignore: invalid_use_of_internal_member
111+
if (_options.devMode) {
112+
rethrow;
113+
}
114+
return null;
115+
}
116+
}
117+
118+
void _logError(String nativeMethodName, Object error, StackTrace stackTrace) {
119+
_options.logger(
120+
SentryLevel.error,
121+
'Native call `$nativeMethodName` failed',
122+
exception: error,
123+
stackTrace: stackTrace,
124+
);
125+
}
113126
}
114127

115128
class NativeAppStart {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import 'dart:async';
2+
3+
import 'package:meta/meta.dart';
4+
5+
import '../../sentry_flutter.dart';
6+
import 'sentry_native.dart';
7+
8+
/// Provide typed methods to access native layer.
9+
@internal
10+
abstract class SentryNativeBinding {
11+
// TODO Move other native calls here.
12+
13+
Future<NativeAppStart?> fetchNativeAppStart();
14+
15+
Future<void> beginNativeFrames();
16+
17+
Future<NativeFrames?> endNativeFrames(SentryId id);
18+
19+
Future<void> setUser(SentryUser? user);
20+
21+
Future<void> addBreadcrumb(Breadcrumb breadcrumb);
22+
23+
Future<void> clearBreadcrumbs();
24+
25+
Future<void> setContexts(String key, dynamic value);
26+
27+
Future<void> removeContexts(String key);
28+
29+
Future<void> setExtra(String key, dynamic value);
30+
31+
Future<void> removeExtra(String key);
32+
33+
Future<void> setTag(String key, String value);
34+
35+
Future<void> removeTag(String key);
36+
37+
int? startProfiler(SentryId traceId);
38+
39+
Future<void> discardProfiler(SentryId traceId);
40+
41+
Future<Map<String, dynamic>?> collectProfile(
42+
SentryId traceId, int startTimeNs, int endTimeNs);
43+
}

0 commit comments

Comments
 (0)