@sentry/react-native 5.0.0-alpha.1 → 5.0.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +403 -4
- package/README.md +6 -0
- package/RNSentry.podspec +22 -5
- package/android/build.gradle +20 -2
- package/android/src/main/java/io/sentry/react/{RNSentryModule.java → RNSentryModuleImpl.java} +174 -114
- package/android/src/main/java/io/sentry/react/RNSentryPackage.java +35 -19
- package/android/src/newarch/java/io/sentry/react/RNSentryModule.java +119 -0
- package/android/src/oldarch/java/io/sentry/react/RNSentryModule.java +119 -0
- package/dist/js/NativeRNSentry.d.ts +52 -0
- package/dist/js/NativeRNSentry.d.ts.map +1 -0
- package/dist/js/NativeRNSentry.js +4 -0
- package/dist/js/NativeRNSentry.js.map +1 -0
- package/dist/js/client.d.ts +18 -6
- package/dist/js/client.d.ts.map +1 -1
- package/dist/js/client.js +96 -37
- package/dist/js/client.js.map +1 -1
- package/dist/js/index.d.ts +4 -3
- package/dist/js/index.d.ts.map +1 -1
- package/dist/js/index.js +3 -2
- package/dist/js/index.js.map +1 -1
- package/dist/js/integrations/debugsymbolicator.d.ts +9 -0
- package/dist/js/integrations/debugsymbolicator.d.ts.map +1 -1
- package/dist/js/integrations/debugsymbolicator.js +0 -2
- package/dist/js/integrations/debugsymbolicator.js.map +1 -1
- package/dist/js/integrations/index.d.ts +2 -0
- package/dist/js/integrations/index.d.ts.map +1 -1
- package/dist/js/integrations/index.js +2 -0
- package/dist/js/integrations/index.js.map +1 -1
- package/dist/js/integrations/modulesloader.d.ts +17 -0
- package/dist/js/integrations/modulesloader.d.ts.map +1 -0
- package/dist/js/integrations/modulesloader.js +39 -0
- package/dist/js/integrations/modulesloader.js.map +1 -0
- package/dist/js/integrations/reactnativeerrorhandlers.d.ts.map +1 -1
- package/dist/js/integrations/reactnativeerrorhandlers.js +10 -7
- package/dist/js/integrations/reactnativeerrorhandlers.js.map +1 -1
- package/dist/js/integrations/reactnativeinfo.d.ts +23 -0
- package/dist/js/integrations/reactnativeinfo.d.ts.map +1 -0
- package/dist/js/integrations/reactnativeinfo.js +43 -0
- package/dist/js/integrations/reactnativeinfo.js.map +1 -0
- package/dist/js/integrations/screenshot.d.ts +23 -0
- package/dist/js/integrations/screenshot.d.ts.map +1 -0
- package/dist/js/integrations/screenshot.js +39 -0
- package/dist/js/integrations/screenshot.js.map +1 -0
- package/dist/js/integrations/sdkinfo.d.ts +4 -1
- package/dist/js/integrations/sdkinfo.d.ts.map +1 -1
- package/dist/js/integrations/sdkinfo.js +13 -7
- package/dist/js/integrations/sdkinfo.js.map +1 -1
- package/dist/js/measurements.d.ts +4 -0
- package/dist/js/measurements.d.ts.map +1 -1
- package/dist/js/measurements.js +12 -1
- package/dist/js/measurements.js.map +1 -1
- package/dist/js/misc.d.ts +9 -0
- package/dist/js/misc.d.ts.map +1 -0
- package/dist/js/misc.js +17 -0
- package/dist/js/misc.js.map +1 -0
- package/dist/js/options.d.ts +45 -9
- package/dist/js/options.d.ts.map +1 -1
- package/dist/js/options.js.map +1 -1
- package/dist/js/scope.d.ts +10 -2
- package/dist/js/scope.d.ts.map +1 -1
- package/dist/js/scope.js +13 -1
- package/dist/js/scope.js.map +1 -1
- package/dist/js/sdk.d.ts +25 -0
- package/dist/js/sdk.d.ts.map +1 -1
- package/dist/js/sdk.js +86 -27
- package/dist/js/sdk.js.map +1 -1
- package/dist/js/tools/ModulesCollector.d.ts +17 -0
- package/dist/js/tools/ModulesCollector.d.ts.map +1 -0
- package/dist/js/tools/ModulesCollector.js +109 -0
- package/dist/js/tools/ModulesCollector.js.map +1 -0
- package/dist/js/tools/collectModules.d.ts +2 -0
- package/dist/js/tools/collectModules.d.ts.map +1 -0
- package/dist/js/tools/collectModules.js +11 -0
- package/dist/js/tools/collectModules.js.map +1 -0
- package/dist/js/touchevents.d.ts +8 -0
- package/dist/js/touchevents.d.ts.map +1 -1
- package/dist/js/touchevents.js +10 -5
- package/dist/js/touchevents.js.map +1 -1
- package/dist/js/tracing/nativeframes.js.map +1 -1
- package/dist/js/tracing/reactnativenavigation.d.ts +9 -0
- package/dist/js/tracing/reactnativenavigation.d.ts.map +1 -1
- package/dist/js/tracing/reactnativenavigation.js +20 -12
- package/dist/js/tracing/reactnativenavigation.js.map +1 -1
- package/dist/js/tracing/reactnativetracing.d.ts +15 -6
- package/dist/js/tracing/reactnativetracing.d.ts.map +1 -1
- package/dist/js/tracing/reactnativetracing.js +16 -9
- package/dist/js/tracing/reactnativetracing.js.map +1 -1
- package/dist/js/tracing/reactnavigation.d.ts +7 -1
- package/dist/js/tracing/reactnavigation.d.ts.map +1 -1
- package/dist/js/tracing/reactnavigation.js +31 -23
- package/dist/js/tracing/reactnavigation.js.map +1 -1
- package/dist/js/tracing/reactnavigationv4.d.ts +9 -9
- package/dist/js/tracing/reactnavigationv4.d.ts.map +1 -1
- package/dist/js/tracing/reactnavigationv4.js +27 -15
- package/dist/js/tracing/reactnavigationv4.js.map +1 -1
- package/dist/js/tracing/routingInstrumentation.d.ts +1 -1
- package/dist/js/tracing/routingInstrumentation.d.ts.map +1 -1
- package/dist/js/tracing/routingInstrumentation.js.map +1 -1
- package/dist/js/tracing/utils.d.ts +4 -3
- package/dist/js/tracing/utils.d.ts.map +1 -1
- package/dist/js/tracing/utils.js +7 -10
- package/dist/js/tracing/utils.js.map +1 -1
- package/dist/js/transports/TextEncoder.d.ts +3 -0
- package/dist/js/transports/TextEncoder.d.ts.map +1 -0
- package/dist/js/transports/TextEncoder.js +12 -0
- package/dist/js/transports/TextEncoder.js.map +1 -0
- package/dist/js/transports/native.d.ts +10 -1
- package/dist/js/transports/native.d.ts.map +1 -1
- package/dist/js/transports/native.js +15 -4
- package/dist/js/transports/native.js.map +1 -1
- package/dist/js/user.d.ts +6 -0
- package/dist/js/user.d.ts.map +1 -0
- package/dist/js/user.js +1 -0
- package/dist/js/user.js.map +1 -0
- package/dist/js/utils/envelope.d.ts +12 -0
- package/dist/js/utils/envelope.d.ts.map +1 -0
- package/dist/js/utils/envelope.js +21 -0
- package/dist/js/utils/envelope.js.map +1 -0
- package/dist/js/utils/environment.d.ts +7 -0
- package/dist/js/utils/environment.d.ts.map +1 -0
- package/dist/js/utils/environment.js +14 -0
- package/dist/js/utils/environment.js.map +1 -0
- package/dist/js/utils/ignorerequirecyclelogs.d.ts +6 -0
- package/dist/js/utils/ignorerequirecyclelogs.d.ts.map +1 -0
- package/dist/js/utils/ignorerequirecyclelogs.js +15 -0
- package/dist/js/utils/ignorerequirecyclelogs.js.map +1 -0
- package/dist/js/utils/outcome.d.ts +6 -0
- package/dist/js/utils/outcome.d.ts.map +1 -0
- package/dist/js/utils/outcome.js +19 -0
- package/dist/js/utils/outcome.js.map +1 -0
- package/dist/js/utils/safe.d.ts +18 -0
- package/dist/js/utils/safe.d.ts.map +1 -0
- package/dist/js/utils/safe.js +46 -0
- package/dist/js/utils/safe.js.map +1 -0
- package/dist/js/utils/worldwide.d.ts +13 -0
- package/dist/js/utils/worldwide.d.ts.map +1 -0
- package/dist/js/utils/worldwide.js +4 -0
- package/dist/js/utils/worldwide.js.map +1 -0
- package/dist/js/vendor/buffer/index.d.ts +2 -0
- package/dist/js/vendor/buffer/index.d.ts.map +1 -0
- package/dist/js/vendor/buffer/index.js +2 -0
- package/dist/js/vendor/buffer/index.js.map +1 -0
- package/dist/js/vendor/buffer/utf8ToBytes.d.ts +10 -0
- package/dist/js/vendor/buffer/utf8ToBytes.d.ts.map +1 -0
- package/dist/js/vendor/buffer/utf8ToBytes.js +82 -0
- package/dist/js/vendor/buffer/utf8ToBytes.js.map +1 -0
- package/dist/js/vendor/index.d.ts +2 -0
- package/dist/js/vendor/index.d.ts.map +1 -0
- package/dist/js/vendor/index.js +2 -0
- package/dist/js/vendor/index.js.map +1 -0
- package/dist/js/version.d.ts +2 -1
- package/dist/js/version.d.ts.map +1 -1
- package/dist/js/version.js +2 -1
- package/dist/js/version.js.map +1 -1
- package/dist/js/wrapper.d.ts +13 -4
- package/dist/js/wrapper.d.ts.map +1 -1
- package/dist/js/wrapper.js +129 -71
- package/dist/js/wrapper.js.map +1 -1
- package/ios/{RNSentry.m → RNSentry.mm} +98 -57
- package/package.json +32 -26
- package/sample-new-architecture/react-native.config.js +10 -0
- package/scripts/collect-modules.sh +43 -0
- package/sentry.gradle +57 -6
- package/src/js/NativeRNSentry.ts +66 -0
- package/dist/js/definitions.d.ts +0 -52
- package/dist/js/definitions.d.ts.map +0 -1
- package/dist/js/definitions.js +0 -1
- package/dist/js/definitions.js.map +0 -1
package/android/src/main/java/io/sentry/react/{RNSentryModule.java → RNSentryModuleImpl.java}
RENAMED
|
@@ -1,62 +1,76 @@
|
|
|
1
1
|
package io.sentry.react;
|
|
2
2
|
|
|
3
|
+
import static io.sentry.android.core.internal.util.ScreenshotUtils.takeScreenshot;
|
|
4
|
+
|
|
3
5
|
import android.app.Activity;
|
|
4
6
|
import android.content.Context;
|
|
5
7
|
import android.content.pm.PackageInfo;
|
|
6
8
|
import android.content.pm.PackageManager;
|
|
9
|
+
import android.content.res.AssetManager;
|
|
7
10
|
import android.util.SparseIntArray;
|
|
8
11
|
|
|
12
|
+
import androidx.annotation.Nullable;
|
|
9
13
|
import androidx.core.app.FrameMetricsAggregator;
|
|
10
14
|
|
|
11
15
|
import com.facebook.react.bridge.Arguments;
|
|
12
|
-
import com.facebook.react.bridge.LifecycleEventListener;
|
|
13
16
|
import com.facebook.react.bridge.Promise;
|
|
14
17
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
15
|
-
import com.facebook.react.bridge.
|
|
16
|
-
import com.facebook.react.bridge.ReactMethod;
|
|
18
|
+
import com.facebook.react.bridge.ReadableArray;
|
|
17
19
|
import com.facebook.react.bridge.ReadableMap;
|
|
18
20
|
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
|
21
|
+
import com.facebook.react.bridge.WritableArray;
|
|
19
22
|
import com.facebook.react.bridge.WritableMap;
|
|
23
|
+
import com.facebook.react.bridge.WritableNativeArray;
|
|
24
|
+
import com.facebook.react.bridge.WritableNativeMap;
|
|
20
25
|
import com.facebook.react.module.annotations.ReactModule;
|
|
21
26
|
|
|
27
|
+
import java.io.BufferedInputStream;
|
|
22
28
|
import java.io.File;
|
|
29
|
+
import java.io.FileNotFoundException;
|
|
23
30
|
import java.io.FileOutputStream;
|
|
24
|
-
import java.io.
|
|
31
|
+
import java.io.InputStream;
|
|
25
32
|
import java.nio.charset.Charset;
|
|
26
33
|
import java.util.Date;
|
|
27
34
|
import java.util.HashMap;
|
|
28
35
|
import java.util.List;
|
|
29
36
|
import java.util.Map;
|
|
30
37
|
import java.util.UUID;
|
|
31
|
-
import java.util.logging.Level;
|
|
32
|
-
import java.util.logging.Logger;
|
|
33
38
|
|
|
34
|
-
import io.sentry.SentryEvent;
|
|
35
|
-
import io.sentry.android.core.AnrIntegration;
|
|
36
|
-
import io.sentry.android.core.AppStartState;
|
|
37
|
-
import io.sentry.android.core.NdkIntegration;
|
|
38
|
-
import io.sentry.android.core.SentryAndroid;
|
|
39
39
|
import io.sentry.Breadcrumb;
|
|
40
40
|
import io.sentry.HubAdapter;
|
|
41
|
+
import io.sentry.ILogger;
|
|
41
42
|
import io.sentry.Integration;
|
|
42
43
|
import io.sentry.Sentry;
|
|
44
|
+
import io.sentry.SentryEvent;
|
|
43
45
|
import io.sentry.SentryLevel;
|
|
44
46
|
import io.sentry.UncaughtExceptionHandlerIntegration;
|
|
47
|
+
import io.sentry.android.core.AnrIntegration;
|
|
48
|
+
import io.sentry.android.core.AppStartState;
|
|
49
|
+
import io.sentry.android.core.BuildInfoProvider;
|
|
50
|
+
import io.sentry.android.core.CurrentActivityHolder;
|
|
51
|
+
import io.sentry.android.core.NdkIntegration;
|
|
52
|
+
import io.sentry.android.core.ScreenshotEventProcessor;
|
|
53
|
+
import io.sentry.android.core.SentryAndroid;
|
|
54
|
+
import io.sentry.android.core.AndroidLogger;
|
|
45
55
|
import io.sentry.protocol.SdkVersion;
|
|
46
56
|
import io.sentry.protocol.SentryException;
|
|
47
57
|
import io.sentry.protocol.SentryPackage;
|
|
48
58
|
import io.sentry.protocol.User;
|
|
49
59
|
|
|
50
|
-
|
|
51
|
-
public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
60
|
+
public class RNSentryModuleImpl {
|
|
52
61
|
|
|
53
62
|
public static final String NAME = "RNSentry";
|
|
54
63
|
|
|
55
|
-
private static final
|
|
64
|
+
private static final ILogger logger = new AndroidLogger(NAME);
|
|
65
|
+
private static final BuildInfoProvider buildInfo = new BuildInfoProvider(logger);
|
|
66
|
+
private static final String modulesPath = "modules.json";
|
|
67
|
+
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
|
56
68
|
|
|
57
|
-
private
|
|
69
|
+
private final ReactApplicationContext reactApplicationContext;
|
|
70
|
+
private final PackageInfo packageInfo;
|
|
58
71
|
private FrameMetricsAggregator frameMetricsAggregator = null;
|
|
59
|
-
private boolean androidXAvailable
|
|
72
|
+
private boolean androidXAvailable;
|
|
73
|
+
private ScreenshotEventProcessor screenshotEventProcessor;
|
|
60
74
|
|
|
61
75
|
private static boolean didFetchAppStart;
|
|
62
76
|
|
|
@@ -65,39 +79,36 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
|
65
79
|
// 16ms (slower than 60fps) to constitute slow frames.
|
|
66
80
|
private static final int SLOW_FRAME_THRESHOLD = 16;
|
|
67
81
|
|
|
68
|
-
public
|
|
69
|
-
|
|
70
|
-
|
|
82
|
+
public RNSentryModuleImpl(ReactApplicationContext reactApplicationContext) {
|
|
83
|
+
packageInfo = getPackageInfo(reactApplicationContext);
|
|
84
|
+
this.reactApplicationContext = reactApplicationContext;
|
|
71
85
|
}
|
|
72
86
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return NAME;
|
|
87
|
+
private ReactApplicationContext getReactApplicationContext() {
|
|
88
|
+
return this.reactApplicationContext;
|
|
76
89
|
}
|
|
77
90
|
|
|
78
|
-
@
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
constants.put("nativeClientAvailable", true);
|
|
82
|
-
constants.put("nativeTransport", true);
|
|
83
|
-
return constants;
|
|
91
|
+
private @Nullable
|
|
92
|
+
Activity getCurrentActivity() {
|
|
93
|
+
return this.reactApplicationContext.getCurrentActivity();
|
|
84
94
|
}
|
|
85
95
|
|
|
86
|
-
@ReactMethod
|
|
87
96
|
public void initNativeSdk(final ReadableMap rnOptions, Promise promise) {
|
|
88
97
|
SentryAndroid.init(this.getReactApplicationContext(), options -> {
|
|
89
98
|
if (rnOptions.hasKey("debug") && rnOptions.getBoolean("debug")) {
|
|
90
99
|
options.setDebug(true);
|
|
91
|
-
logger.setLevel(Level.INFO);
|
|
92
100
|
}
|
|
93
101
|
if (rnOptions.hasKey("dsn") && rnOptions.getString("dsn") != null) {
|
|
94
102
|
String dsn = rnOptions.getString("dsn");
|
|
95
|
-
logger.
|
|
103
|
+
logger.log(SentryLevel.INFO, String.format("Starting with DSN: '%s'", dsn));
|
|
96
104
|
options.setDsn(dsn);
|
|
97
105
|
} else {
|
|
98
106
|
// SentryAndroid needs an empty string fallback for the dsn.
|
|
99
107
|
options.setDsn("");
|
|
100
108
|
}
|
|
109
|
+
if (rnOptions.hasKey("sendClientReports")) {
|
|
110
|
+
options.setSendClientReports(rnOptions.getBoolean("sendClientReports"));
|
|
111
|
+
}
|
|
101
112
|
if (rnOptions.hasKey("maxBreadcrumbs")) {
|
|
102
113
|
options.setMaxBreadcrumbs(rnOptions.getInt("maxBreadcrumbs"));
|
|
103
114
|
}
|
|
@@ -129,35 +140,18 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
|
129
140
|
options.setAttachStacktrace(rnOptions.getBoolean("attachStacktrace"));
|
|
130
141
|
}
|
|
131
142
|
if (rnOptions.hasKey("attachThreads")) {
|
|
132
|
-
// JS use top level
|
|
143
|
+
// JS use top level stacktrace and android attaches Threads which hides them so
|
|
133
144
|
// by default we hide.
|
|
134
145
|
options.setAttachThreads(rnOptions.getBoolean("attachThreads"));
|
|
135
146
|
}
|
|
147
|
+
if (rnOptions.hasKey("attachScreenshot")) {
|
|
148
|
+
options.setAttachScreenshot(rnOptions.getBoolean("attachScreenshot"));
|
|
149
|
+
}
|
|
136
150
|
if (rnOptions.hasKey("sendDefaultPii")) {
|
|
137
151
|
options.setSendDefaultPii(rnOptions.getBoolean("sendDefaultPii"));
|
|
138
152
|
}
|
|
139
|
-
if (rnOptions.hasKey("
|
|
140
|
-
|
|
141
|
-
androidXAvailable = checkAndroidXAvailability();
|
|
142
|
-
|
|
143
|
-
if (androidXAvailable) {
|
|
144
|
-
frameMetricsAggregator = new FrameMetricsAggregator();
|
|
145
|
-
final Activity currentActivity = getCurrentActivity();
|
|
146
|
-
|
|
147
|
-
if (frameMetricsAggregator != null && currentActivity != null) {
|
|
148
|
-
try {
|
|
149
|
-
frameMetricsAggregator.add(currentActivity);
|
|
150
|
-
} catch (Throwable ignored) {
|
|
151
|
-
// throws ConcurrentModification when calling addOnFrameMetricsAvailableListener
|
|
152
|
-
// this is a best effort since we can't reproduce it
|
|
153
|
-
logger.warning("Error adding Activity to frameMetricsAggregator.");
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
} else {
|
|
157
|
-
logger.warning("androidx.core' isn't available as a dependency.");
|
|
158
|
-
}
|
|
159
|
-
} else {
|
|
160
|
-
this.disableNativeFramesTracking();
|
|
153
|
+
if (rnOptions.hasKey("maxQueueSize")) {
|
|
154
|
+
options.setMaxQueueSize(rnOptions.getInt("maxQueueSize"));
|
|
161
155
|
}
|
|
162
156
|
|
|
163
157
|
options.setBeforeSend((event, hint) -> {
|
|
@@ -188,19 +182,40 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
|
188
182
|
}
|
|
189
183
|
}
|
|
190
184
|
}
|
|
185
|
+
logger.log(SentryLevel.INFO, String.format("Native Integrations '%s'", options.getIntegrations()));
|
|
191
186
|
|
|
192
|
-
|
|
187
|
+
final CurrentActivityHolder currentActivityHolder = CurrentActivityHolder.getInstance();
|
|
188
|
+
final Activity currentActivity = getCurrentActivity();
|
|
189
|
+
if (currentActivity != null) {
|
|
190
|
+
currentActivityHolder.setActivity(currentActivity);
|
|
191
|
+
}
|
|
193
192
|
});
|
|
194
193
|
|
|
195
194
|
promise.resolve(true);
|
|
196
195
|
}
|
|
197
196
|
|
|
198
|
-
@ReactMethod
|
|
199
197
|
public void crash() {
|
|
200
198
|
throw new RuntimeException("TEST - Sentry Client Crash (only works in release mode)");
|
|
201
199
|
}
|
|
202
200
|
|
|
203
|
-
|
|
201
|
+
public void fetchModules(Promise promise) {
|
|
202
|
+
final AssetManager assets = this.getReactApplicationContext().getResources().getAssets();
|
|
203
|
+
try (final InputStream stream =
|
|
204
|
+
new BufferedInputStream(assets.open(RNSentryModuleImpl.modulesPath))) {
|
|
205
|
+
int size = stream.available();
|
|
206
|
+
byte[] buffer = new byte[size];
|
|
207
|
+
stream.read(buffer);
|
|
208
|
+
stream.close();
|
|
209
|
+
String modulesJson = new String(buffer, RNSentryModuleImpl.UTF_8);
|
|
210
|
+
promise.resolve(modulesJson);
|
|
211
|
+
} catch (FileNotFoundException e) {
|
|
212
|
+
promise.resolve(null);
|
|
213
|
+
} catch (Throwable e) {
|
|
214
|
+
logger.log(SentryLevel.WARNING, "Fetching JS Modules failed.");
|
|
215
|
+
promise.resolve(null);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
204
219
|
public void fetchNativeRelease(Promise promise) {
|
|
205
220
|
WritableMap release = Arguments.createMap();
|
|
206
221
|
release.putString("id", packageInfo.packageName);
|
|
@@ -209,17 +224,16 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
|
209
224
|
promise.resolve(release);
|
|
210
225
|
}
|
|
211
226
|
|
|
212
|
-
@ReactMethod
|
|
213
227
|
public void fetchNativeAppStart(Promise promise) {
|
|
214
228
|
final AppStartState appStartInstance = AppStartState.getInstance();
|
|
215
229
|
final Date appStartTime = appStartInstance.getAppStartTime();
|
|
216
230
|
final Boolean isColdStart = appStartInstance.isColdStart();
|
|
217
231
|
|
|
218
232
|
if (appStartTime == null) {
|
|
219
|
-
logger.
|
|
233
|
+
logger.log(SentryLevel.WARNING, "App start won't be sent due to missing appStartTime.");
|
|
220
234
|
promise.resolve(null);
|
|
221
235
|
} else if (isColdStart == null) {
|
|
222
|
-
logger.
|
|
236
|
+
logger.log(SentryLevel.WARNING, "App start won't be sent due to missing isColdStart.");
|
|
223
237
|
promise.resolve(null);
|
|
224
238
|
} else {
|
|
225
239
|
final double appStartTimestamp = (double) appStartTime.getTime();
|
|
@@ -241,7 +255,6 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
|
241
255
|
/**
|
|
242
256
|
* Returns frames metrics at the current point in time.
|
|
243
257
|
*/
|
|
244
|
-
@ReactMethod
|
|
245
258
|
public void fetchNativeFrames(Promise promise) {
|
|
246
259
|
if (!isFrameMetricsAggregatorAvailable()) {
|
|
247
260
|
promise.resolve(null);
|
|
@@ -285,87 +298,118 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
|
285
298
|
|
|
286
299
|
promise.resolve(map);
|
|
287
300
|
} catch (Throwable ignored) {
|
|
288
|
-
logger.
|
|
301
|
+
logger.log(SentryLevel.WARNING, "Error fetching native frames.");
|
|
289
302
|
promise.resolve(null);
|
|
290
303
|
}
|
|
291
304
|
}
|
|
292
305
|
}
|
|
293
306
|
|
|
294
|
-
|
|
295
|
-
|
|
307
|
+
public void captureEnvelope(ReadableArray rawBytes, ReadableMap options, Promise promise) {
|
|
308
|
+
byte[] bytes = new byte[rawBytes.size()];
|
|
309
|
+
for (int i = 0; i < rawBytes.size(); i++) {
|
|
310
|
+
bytes[i] = (byte) rawBytes.getInt(i);
|
|
311
|
+
}
|
|
312
|
+
|
|
296
313
|
try {
|
|
297
314
|
final String outboxPath = HubAdapter.getInstance().getOptions().getOutboxPath();
|
|
298
315
|
|
|
299
316
|
if (outboxPath == null) {
|
|
300
|
-
logger.
|
|
317
|
+
logger.log(SentryLevel.ERROR,
|
|
301
318
|
"Error retrieving outboxPath. Envelope will not be sent. Is the Android SDK initialized?");
|
|
302
319
|
} else {
|
|
303
320
|
File installation = new File(outboxPath, UUID.randomUUID().toString());
|
|
304
321
|
try (FileOutputStream out = new FileOutputStream(installation)) {
|
|
305
|
-
out.write(
|
|
322
|
+
out.write(bytes);
|
|
306
323
|
}
|
|
307
324
|
}
|
|
308
325
|
} catch (Throwable ignored) {
|
|
309
|
-
logger.
|
|
326
|
+
logger.log(SentryLevel.ERROR, "Error while writing envelope to outbox.");
|
|
310
327
|
}
|
|
311
328
|
promise.resolve(true);
|
|
312
329
|
}
|
|
313
330
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
promise.
|
|
331
|
+
public void captureScreenshot(Promise promise) {
|
|
332
|
+
|
|
333
|
+
final Activity activity = getCurrentActivity();
|
|
334
|
+
if (activity == null) {
|
|
335
|
+
logger.log(SentryLevel.WARNING, "CurrentActivity is null, can't capture screenshot.");
|
|
336
|
+
promise.resolve(null);
|
|
337
|
+
return;
|
|
320
338
|
}
|
|
339
|
+
|
|
340
|
+
final byte[] raw = takeScreenshot(activity, logger, buildInfo);
|
|
341
|
+
if (raw == null) {
|
|
342
|
+
logger.log(SentryLevel.WARNING, "Screenshot is null, screen was not captured.");
|
|
343
|
+
promise.resolve(null);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
final WritableNativeArray data = new WritableNativeArray();
|
|
348
|
+
for (final byte b : raw) {
|
|
349
|
+
data.pushInt(b);
|
|
350
|
+
}
|
|
351
|
+
final WritableMap screenshot = new WritableNativeMap();
|
|
352
|
+
screenshot.putString("contentType", "image/png");
|
|
353
|
+
screenshot.putArray("data", data);
|
|
354
|
+
screenshot.putString("filename", "screenshot.png");
|
|
355
|
+
|
|
356
|
+
final WritableArray screenshotsArray = new WritableNativeArray();
|
|
357
|
+
screenshotsArray.pushMap(screenshot);
|
|
358
|
+
promise.resolve(screenshotsArray);
|
|
321
359
|
}
|
|
322
360
|
|
|
323
361
|
private static PackageInfo getPackageInfo(Context ctx) {
|
|
324
362
|
try {
|
|
325
363
|
return ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0);
|
|
326
364
|
} catch (PackageManager.NameNotFoundException e) {
|
|
327
|
-
logger.
|
|
365
|
+
logger.log(SentryLevel.WARNING, "Error getting package info.");
|
|
328
366
|
return null;
|
|
329
367
|
}
|
|
330
368
|
}
|
|
331
369
|
|
|
332
|
-
|
|
333
|
-
public void setUser(final ReadableMap user, final ReadableMap otherUserKeys) {
|
|
370
|
+
public void setUser(final ReadableMap userKeys, final ReadableMap userDataKeys) {
|
|
334
371
|
Sentry.configureScope(scope -> {
|
|
335
|
-
if (
|
|
372
|
+
if (userKeys == null && userDataKeys == null) {
|
|
336
373
|
scope.setUser(null);
|
|
337
374
|
} else {
|
|
338
375
|
User userInstance = new User();
|
|
339
376
|
|
|
340
|
-
if (
|
|
341
|
-
if (
|
|
342
|
-
userInstance.setEmail(
|
|
377
|
+
if (userKeys != null) {
|
|
378
|
+
if (userKeys.hasKey("email")) {
|
|
379
|
+
userInstance.setEmail(userKeys.getString("email"));
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (userKeys.hasKey("id")) {
|
|
383
|
+
userInstance.setId(userKeys.getString("id"));
|
|
343
384
|
}
|
|
344
385
|
|
|
345
|
-
if (
|
|
346
|
-
userInstance.
|
|
386
|
+
if (userKeys.hasKey("username")) {
|
|
387
|
+
userInstance.setUsername(userKeys.getString("username"));
|
|
347
388
|
}
|
|
348
389
|
|
|
349
|
-
if (
|
|
350
|
-
userInstance.
|
|
390
|
+
if (userKeys.hasKey("ip_address")) {
|
|
391
|
+
userInstance.setIpAddress(userKeys.getString("ip_address"));
|
|
351
392
|
}
|
|
352
393
|
|
|
353
|
-
if (
|
|
354
|
-
userInstance.
|
|
394
|
+
if (userKeys.hasKey("segment")) {
|
|
395
|
+
userInstance.setSegment(userKeys.getString("segment"));
|
|
355
396
|
}
|
|
356
397
|
}
|
|
357
398
|
|
|
358
|
-
if (
|
|
359
|
-
HashMap<String, String>
|
|
360
|
-
ReadableMapKeySetIterator it =
|
|
399
|
+
if (userDataKeys != null) {
|
|
400
|
+
HashMap<String, String> userDataMap = new HashMap<>();
|
|
401
|
+
ReadableMapKeySetIterator it = userDataKeys.keySetIterator();
|
|
361
402
|
while (it.hasNextKey()) {
|
|
362
403
|
String key = it.nextKey();
|
|
363
|
-
String value =
|
|
404
|
+
String value = userDataKeys.getString(key);
|
|
364
405
|
|
|
365
|
-
|
|
406
|
+
// other is ConcurrentHashMap and can't have null values
|
|
407
|
+
if (value != null) {
|
|
408
|
+
userDataMap.put(key, value);
|
|
409
|
+
}
|
|
366
410
|
}
|
|
367
411
|
|
|
368
|
-
userInstance.
|
|
412
|
+
userInstance.setData(userDataMap);
|
|
369
413
|
}
|
|
370
414
|
|
|
371
415
|
scope.setUser(userInstance);
|
|
@@ -373,7 +417,6 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
|
373
417
|
});
|
|
374
418
|
}
|
|
375
419
|
|
|
376
|
-
@ReactMethod
|
|
377
420
|
public void addBreadcrumb(final ReadableMap breadcrumb) {
|
|
378
421
|
Sentry.configureScope(scope -> {
|
|
379
422
|
Breadcrumb breadcrumbInstance = new Breadcrumb();
|
|
@@ -398,29 +441,27 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
|
398
441
|
case "warning":
|
|
399
442
|
breadcrumbInstance.setLevel(SentryLevel.WARNING);
|
|
400
443
|
break;
|
|
401
|
-
case "info":
|
|
402
|
-
breadcrumbInstance.setLevel(SentryLevel.INFO);
|
|
403
|
-
break;
|
|
404
444
|
case "debug":
|
|
405
445
|
breadcrumbInstance.setLevel(SentryLevel.DEBUG);
|
|
406
446
|
break;
|
|
407
447
|
case "error":
|
|
408
448
|
breadcrumbInstance.setLevel(SentryLevel.ERROR);
|
|
409
449
|
break;
|
|
450
|
+
case "info":
|
|
410
451
|
default:
|
|
411
|
-
breadcrumbInstance.setLevel(SentryLevel.
|
|
452
|
+
breadcrumbInstance.setLevel(SentryLevel.INFO);
|
|
412
453
|
break;
|
|
413
454
|
}
|
|
414
455
|
}
|
|
415
456
|
|
|
416
457
|
if (breadcrumb.hasKey("data")) {
|
|
417
|
-
ReadableMap data = breadcrumb.getMap("data");
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
458
|
+
final ReadableMap data = breadcrumb.getMap("data");
|
|
459
|
+
for (final Map.Entry<String, Object> entry : data.toHashMap().entrySet()) {
|
|
460
|
+
final Object value = entry.getValue();
|
|
461
|
+
// data is ConcurrentHashMap and can't have null values
|
|
462
|
+
if (value != null) {
|
|
463
|
+
breadcrumbInstance.setData(entry.getKey(), entry.getValue());
|
|
464
|
+
}
|
|
424
465
|
}
|
|
425
466
|
}
|
|
426
467
|
|
|
@@ -428,21 +469,18 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
|
428
469
|
});
|
|
429
470
|
}
|
|
430
471
|
|
|
431
|
-
@ReactMethod
|
|
432
472
|
public void clearBreadcrumbs() {
|
|
433
473
|
Sentry.configureScope(scope -> {
|
|
434
474
|
scope.clearBreadcrumbs();
|
|
435
475
|
});
|
|
436
476
|
}
|
|
437
477
|
|
|
438
|
-
@ReactMethod
|
|
439
478
|
public void setExtra(String key, String extra) {
|
|
440
479
|
Sentry.configureScope(scope -> {
|
|
441
480
|
scope.setExtra(key, extra);
|
|
442
481
|
});
|
|
443
482
|
}
|
|
444
483
|
|
|
445
|
-
@ReactMethod
|
|
446
484
|
public void setContext(final String key, final ReadableMap context) {
|
|
447
485
|
if (key == null || context == null) {
|
|
448
486
|
return;
|
|
@@ -454,14 +492,12 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
|
454
492
|
});
|
|
455
493
|
}
|
|
456
494
|
|
|
457
|
-
@ReactMethod
|
|
458
495
|
public void setTag(String key, String value) {
|
|
459
496
|
Sentry.configureScope(scope -> {
|
|
460
497
|
scope.setTag(key, value);
|
|
461
498
|
});
|
|
462
499
|
}
|
|
463
500
|
|
|
464
|
-
@ReactMethod
|
|
465
501
|
public void closeNativeSdk(Promise promise) {
|
|
466
502
|
Sentry.close();
|
|
467
503
|
|
|
@@ -470,7 +506,31 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
|
470
506
|
promise.resolve(true);
|
|
471
507
|
}
|
|
472
508
|
|
|
473
|
-
|
|
509
|
+
public void enableNativeFramesTracking() {
|
|
510
|
+
androidXAvailable = checkAndroidXAvailability();
|
|
511
|
+
|
|
512
|
+
if (androidXAvailable) {
|
|
513
|
+
frameMetricsAggregator = new FrameMetricsAggregator();
|
|
514
|
+
final Activity currentActivity = getCurrentActivity();
|
|
515
|
+
|
|
516
|
+
if (frameMetricsAggregator != null && currentActivity != null) {
|
|
517
|
+
try {
|
|
518
|
+
frameMetricsAggregator.add(currentActivity);
|
|
519
|
+
|
|
520
|
+
logger.log(SentryLevel.INFO, "FrameMetricsAggregator installed.");
|
|
521
|
+
} catch (Throwable ignored) {
|
|
522
|
+
// throws ConcurrentModification when calling addOnFrameMetricsAvailableListener
|
|
523
|
+
// this is a best effort since we can't reproduce it
|
|
524
|
+
logger.log(SentryLevel.ERROR, "Error adding Activity to frameMetricsAggregator.");
|
|
525
|
+
}
|
|
526
|
+
} else {
|
|
527
|
+
logger.log(SentryLevel.INFO, "currentActivity isn't available.");
|
|
528
|
+
}
|
|
529
|
+
} else {
|
|
530
|
+
logger.log(SentryLevel.WARNING, "androidx.core' isn't available as a dependency.");
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
474
534
|
public void disableNativeFramesTracking() {
|
|
475
535
|
if (isFrameMetricsAggregatorAvailable()) {
|
|
476
536
|
frameMetricsAggregator.stop();
|
|
@@ -485,10 +545,10 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
|
485
545
|
// If the event is from capacitor js, it gets set there and we do not handle it
|
|
486
546
|
// here.
|
|
487
547
|
case "sentry.native":
|
|
488
|
-
setEventEnvironmentTag(event, "
|
|
548
|
+
setEventEnvironmentTag(event, "native");
|
|
489
549
|
break;
|
|
490
550
|
case "sentry.java.android":
|
|
491
|
-
setEventEnvironmentTag(event, "
|
|
551
|
+
setEventEnvironmentTag(event, "java");
|
|
492
552
|
break;
|
|
493
553
|
default:
|
|
494
554
|
break;
|
|
@@ -496,8 +556,8 @@ public class RNSentryModule extends ReactContextBaseJavaModule {
|
|
|
496
556
|
}
|
|
497
557
|
}
|
|
498
558
|
|
|
499
|
-
private void setEventEnvironmentTag(SentryEvent event, String
|
|
500
|
-
event.setTag("event.origin",
|
|
559
|
+
private void setEventEnvironmentTag(SentryEvent event, String environment) {
|
|
560
|
+
event.setTag("event.origin", "android");
|
|
501
561
|
event.setTag("event.environment", environment);
|
|
502
562
|
}
|
|
503
563
|
|
|
@@ -1,30 +1,46 @@
|
|
|
1
1
|
package io.sentry.react;
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
import java.util.
|
|
3
|
+
import androidx.annotation.Nullable;
|
|
4
|
+
|
|
5
|
+
import java.util.HashMap;
|
|
6
|
+
import java.util.Map;
|
|
6
7
|
|
|
7
|
-
import com.facebook.react.ReactPackage;
|
|
8
8
|
import com.facebook.react.bridge.NativeModule;
|
|
9
9
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
10
|
-
import com.facebook.react.
|
|
11
|
-
import com.facebook.react.
|
|
10
|
+
import com.facebook.react.module.model.ReactModuleInfo;
|
|
11
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
|
12
|
+
import com.facebook.react.TurboReactPackage;
|
|
12
13
|
|
|
13
|
-
public class RNSentryPackage
|
|
14
|
-
public RNSentryPackage() {
|
|
15
|
-
}
|
|
14
|
+
public class RNSentryPackage extends TurboReactPackage {
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
@Nullable
|
|
17
|
+
@Override
|
|
18
|
+
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
|
|
19
|
+
if (name.equals(RNSentryModuleImpl.NAME)) {
|
|
20
|
+
return new RNSentryModule(reactContext);
|
|
21
|
+
} else {
|
|
22
|
+
return null;
|
|
20
23
|
}
|
|
24
|
+
}
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
@Override
|
|
27
|
+
public ReactModuleInfoProvider getReactModuleInfoProvider() {
|
|
28
|
+
return () -> {
|
|
29
|
+
final Map<String, ReactModuleInfo> moduleInfos = new HashMap<>();
|
|
30
|
+
boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
|
31
|
+
moduleInfos.put(
|
|
32
|
+
RNSentryModuleImpl.NAME,
|
|
33
|
+
new ReactModuleInfo(
|
|
34
|
+
RNSentryModuleImpl.NAME,
|
|
35
|
+
RNSentryModuleImpl.NAME,
|
|
36
|
+
false, // canOverrideExistingModule
|
|
37
|
+
false, // needsEagerInit
|
|
38
|
+
true, // hasConstants
|
|
39
|
+
false, // isCxxModule
|
|
40
|
+
isTurboModule // isTurboModule
|
|
41
|
+
));
|
|
42
|
+
return moduleInfos;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
25
45
|
|
|
26
|
-
@Override
|
|
27
|
-
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
|
28
|
-
return Collections.emptyList();
|
|
29
|
-
}
|
|
30
46
|
}
|