@sentry/react-native 7.11.0 → 8.0.0-alpha.0
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/RNSentry.podspec +8 -4
- package/android/libs/replay-stubs.jar +0 -0
- package/android/src/main/java/io/sentry/react/RNSentryCompositeOptionsConfiguration.java +25 -0
- package/android/src/main/java/io/sentry/react/RNSentryJsonConverter.java +76 -0
- package/android/src/main/java/io/sentry/react/RNSentryJsonUtils.java +41 -0
- package/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java +2 -398
- package/android/src/main/java/io/sentry/react/RNSentrySDK.java +68 -0
- package/android/src/main/java/io/sentry/react/RNSentryStart.java +417 -0
- package/android/src/main/java/io/sentry/react/RNSentryVersion.java +1 -1
- package/dist/js/replay/mobilereplay.d.ts +0 -26
- package/dist/js/replay/mobilereplay.d.ts.map +1 -1
- package/dist/js/replay/mobilereplay.js.map +1 -1
- package/dist/js/sdk.d.ts.map +1 -1
- package/dist/js/sdk.js +21 -10
- package/dist/js/sdk.js.map +1 -1
- package/dist/js/tools/metroconfig.d.ts +9 -1
- package/dist/js/tools/metroconfig.d.ts.map +1 -1
- package/dist/js/tools/metroconfig.js +9 -2
- package/dist/js/tools/metroconfig.js.map +1 -1
- package/dist/js/tools/sentryMetroSerializer.d.ts.map +1 -1
- package/dist/js/tools/sentryMetroSerializer.js +1 -0
- package/dist/js/tools/sentryMetroSerializer.js.map +1 -1
- package/dist/js/tools/sentryOptionsSerializer.d.ts +6 -0
- package/dist/js/tools/sentryOptionsSerializer.d.ts.map +1 -0
- package/dist/js/tools/sentryOptionsSerializer.js +92 -0
- package/dist/js/tools/sentryOptionsSerializer.js.map +1 -0
- package/dist/js/tools/utils.d.ts +2 -1
- package/dist/js/tools/utils.d.ts.map +1 -1
- package/dist/js/tools/utils.js.map +1 -1
- package/dist/js/utils/worldwide.d.ts +2 -0
- package/dist/js/utils/worldwide.d.ts.map +1 -1
- package/dist/js/utils/worldwide.js.map +1 -1
- package/dist/js/version.d.ts +1 -1
- package/dist/js/version.d.ts.map +1 -1
- package/dist/js/version.js +1 -1
- package/dist/js/version.js.map +1 -1
- package/ios/RNSentry.h +3 -0
- package/ios/RNSentry.mm +12 -44
- package/ios/RNSentryDependencyContainer.h +2 -1
- package/ios/RNSentryDependencyContainer.m +1 -0
- package/ios/RNSentryEmitNewFrameEvent.h +3 -0
- package/ios/RNSentryExperimentalOptions.m +1 -1
- package/ios/RNSentryFramesTrackerListener.h +2 -2
- package/ios/RNSentryFramesTrackerListener.m +2 -0
- package/ios/RNSentryOnDrawReporter.h +2 -1
- package/ios/RNSentryOnDrawReporter.m +2 -0
- package/ios/RNSentryRNSScreen.m +3 -4
- package/ios/RNSentryReplay.mm +0 -5
- package/ios/RNSentryReplayBreadcrumbConverter.m +12 -12
- package/ios/RNSentrySDK.h +31 -0
- package/ios/RNSentrySDK.m +78 -0
- package/ios/RNSentryStart.h +25 -0
- package/ios/RNSentryStart.m +228 -0
- package/ios/RNSentryVersion.m +1 -1
- package/ios/SentryScreenFramesWrapper.h +14 -0
- package/ios/SentryScreenFramesWrapper.m +39 -0
- package/package.json +2 -2
- package/plugin/build/logger.d.ts +24 -0
- package/plugin/build/logger.js +44 -0
- package/plugin/build/utils.d.ts +0 -18
- package/plugin/build/utils.js +1 -34
- package/plugin/build/version.d.ts +2 -0
- package/plugin/build/version.js +6 -0
- package/plugin/build/withSentry.d.ts +1 -0
- package/plugin/build/withSentry.js +11 -10
- package/plugin/build/withSentryAndroid.d.ts +6 -1
- package/plugin/build/withSentryAndroid.js +52 -8
- package/plugin/build/withSentryAndroidGradlePlugin.d.ts +1 -1
- package/plugin/build/withSentryAndroidGradlePlugin.js +8 -8
- package/plugin/build/withSentryIOS.d.ts +6 -1
- package/plugin/build/withSentryIOS.js +55 -7
- package/scripts/sentry-xcode.sh +20 -0
- package/sentry.gradle +51 -0
- package/ts3.8/dist/js/replay/mobilereplay.d.ts +0 -26
- package/ts3.8/dist/js/utils/worldwide.d.ts +2 -0
- package/ts3.8/dist/js/version.d.ts +1 -1
package/RNSentry.podspec
CHANGED
|
@@ -42,11 +42,15 @@ Pod::Spec.new do |s|
|
|
|
42
42
|
s.preserve_paths = '*.js'
|
|
43
43
|
|
|
44
44
|
s.source_files = 'ios/**/*.{h,m,mm}'
|
|
45
|
-
s.public_header_files = 'ios/RNSentry.h'
|
|
45
|
+
s.public_header_files = 'ios/RNSentry.h', 'ios/RNSentrySDK.h', 'ios/RNSentryStart.h', 'ios/RNSentryVersion.h', 'ios/RNSentryBreadcrumb.h', 'ios/RNSentryReplay.h', 'ios/RNSentryReplayBreadcrumbConverter.h', 'ios/Replay/RNSentryReplayMask.h', 'ios/Replay/RNSentryReplayUnmask.h', 'ios/RNSentryTimeToDisplay.h'
|
|
46
46
|
|
|
47
47
|
s.compiler_flags = other_cflags
|
|
48
48
|
|
|
49
|
-
s.
|
|
49
|
+
s.pod_target_xcconfig = {
|
|
50
|
+
'DEFINES_MODULE' => 'YES'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
s.dependency 'Sentry/HybridSDK', '9.1.0'
|
|
50
54
|
|
|
51
55
|
if defined? install_modules_dependencies
|
|
52
56
|
# Default React Native dependencies for 0.71 and above (new and legacy architecture)
|
|
@@ -56,10 +60,10 @@ Pod::Spec.new do |s|
|
|
|
56
60
|
|
|
57
61
|
if is_new_arch_enabled then
|
|
58
62
|
# New Architecture on React Native 0.70 and older
|
|
59
|
-
s.pod_target_xcconfig
|
|
63
|
+
s.pod_target_xcconfig.merge!({
|
|
60
64
|
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
61
65
|
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
62
|
-
}
|
|
66
|
+
})
|
|
63
67
|
|
|
64
68
|
s.dependency "React-RCTFabric" # Required for Fabric Components (like RCTViewComponentView)
|
|
65
69
|
s.dependency "React-Codegen"
|
|
Binary file
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
package io.sentry.react;
|
|
2
|
+
|
|
3
|
+
import io.sentry.Sentry.OptionsConfiguration;
|
|
4
|
+
import io.sentry.android.core.SentryAndroidOptions;
|
|
5
|
+
import java.util.List;
|
|
6
|
+
import org.jetbrains.annotations.NotNull;
|
|
7
|
+
|
|
8
|
+
class RNSentryCompositeOptionsConfiguration implements OptionsConfiguration<SentryAndroidOptions> {
|
|
9
|
+
private final @NotNull List<OptionsConfiguration<SentryAndroidOptions>> configurations;
|
|
10
|
+
|
|
11
|
+
@SafeVarargs
|
|
12
|
+
protected RNSentryCompositeOptionsConfiguration(
|
|
13
|
+
@NotNull OptionsConfiguration<SentryAndroidOptions>... configurations) {
|
|
14
|
+
this.configurations = List.of(configurations);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@Override
|
|
18
|
+
public void configure(@NotNull SentryAndroidOptions options) {
|
|
19
|
+
for (OptionsConfiguration<SentryAndroidOptions> configuration : configurations) {
|
|
20
|
+
if (configuration != null) {
|
|
21
|
+
configuration.configure(options);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
package io.sentry.react;
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.JavaOnlyArray;
|
|
4
|
+
import com.facebook.react.bridge.JavaOnlyMap;
|
|
5
|
+
import com.facebook.react.bridge.WritableArray;
|
|
6
|
+
import com.facebook.react.bridge.WritableMap;
|
|
7
|
+
import io.sentry.ILogger;
|
|
8
|
+
import io.sentry.SentryLevel;
|
|
9
|
+
import io.sentry.android.core.AndroidLogger;
|
|
10
|
+
import java.util.Iterator;
|
|
11
|
+
import org.jetbrains.annotations.NotNull;
|
|
12
|
+
import org.jetbrains.annotations.Nullable;
|
|
13
|
+
import org.json.JSONArray;
|
|
14
|
+
import org.json.JSONException;
|
|
15
|
+
import org.json.JSONObject;
|
|
16
|
+
|
|
17
|
+
final class RNSentryJsonConverter {
|
|
18
|
+
public static final String NAME = "RNSentry.RNSentryJsonConverter";
|
|
19
|
+
|
|
20
|
+
private static final ILogger logger = new AndroidLogger(NAME);
|
|
21
|
+
|
|
22
|
+
private RNSentryJsonConverter() {
|
|
23
|
+
throw new AssertionError("Utility class should not be instantiated");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@Nullable
|
|
27
|
+
static WritableMap convertToWritable(@NotNull JSONObject jsonObject) {
|
|
28
|
+
try {
|
|
29
|
+
WritableMap writableMap = new JavaOnlyMap();
|
|
30
|
+
Iterator<String> iterator = jsonObject.keys();
|
|
31
|
+
while (iterator.hasNext()) {
|
|
32
|
+
String key = iterator.next();
|
|
33
|
+
Object value = jsonObject.get(key);
|
|
34
|
+
if (value instanceof Float || value instanceof Double) {
|
|
35
|
+
writableMap.putDouble(key, jsonObject.getDouble(key));
|
|
36
|
+
} else if (value instanceof Number) {
|
|
37
|
+
writableMap.putInt(key, jsonObject.getInt(key));
|
|
38
|
+
} else if (value instanceof String) {
|
|
39
|
+
writableMap.putString(key, jsonObject.getString(key));
|
|
40
|
+
} else if (value instanceof JSONObject) {
|
|
41
|
+
writableMap.putMap(key, convertToWritable(jsonObject.getJSONObject(key)));
|
|
42
|
+
} else if (value instanceof JSONArray) {
|
|
43
|
+
writableMap.putArray(key, convertToWritable(jsonObject.getJSONArray(key)));
|
|
44
|
+
} else if (value == JSONObject.NULL) {
|
|
45
|
+
writableMap.putNull(key);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return writableMap;
|
|
49
|
+
} catch (JSONException e) {
|
|
50
|
+
logger.log(SentryLevel.ERROR, "Error parsing json object:" + e.getMessage());
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@NotNull
|
|
56
|
+
static WritableArray convertToWritable(@NotNull JSONArray jsonArray) throws JSONException {
|
|
57
|
+
WritableArray writableArray = new JavaOnlyArray();
|
|
58
|
+
for (int i = 0; i < jsonArray.length(); i++) {
|
|
59
|
+
Object value = jsonArray.get(i);
|
|
60
|
+
if (value instanceof Float || value instanceof Double) {
|
|
61
|
+
writableArray.pushDouble(jsonArray.getDouble(i));
|
|
62
|
+
} else if (value instanceof Number) {
|
|
63
|
+
writableArray.pushInt(jsonArray.getInt(i));
|
|
64
|
+
} else if (value instanceof String) {
|
|
65
|
+
writableArray.pushString(jsonArray.getString(i));
|
|
66
|
+
} else if (value instanceof JSONObject) {
|
|
67
|
+
writableArray.pushMap(convertToWritable(jsonArray.getJSONObject(i)));
|
|
68
|
+
} else if (value instanceof JSONArray) {
|
|
69
|
+
writableArray.pushArray(convertToWritable(jsonArray.getJSONArray(i)));
|
|
70
|
+
} else if (value == JSONObject.NULL) {
|
|
71
|
+
writableArray.pushNull();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return writableArray;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package io.sentry.react;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import io.sentry.ILogger;
|
|
5
|
+
import io.sentry.SentryLevel;
|
|
6
|
+
import java.io.BufferedReader;
|
|
7
|
+
import java.io.InputStream;
|
|
8
|
+
import java.io.InputStreamReader;
|
|
9
|
+
import org.jetbrains.annotations.NotNull;
|
|
10
|
+
import org.jetbrains.annotations.Nullable;
|
|
11
|
+
import org.json.JSONObject;
|
|
12
|
+
|
|
13
|
+
final class RNSentryJsonUtils {
|
|
14
|
+
private RNSentryJsonUtils() {
|
|
15
|
+
throw new AssertionError("Utility class should not be instantiated");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static @Nullable JSONObject getOptionsFromConfigurationFile(
|
|
19
|
+
@NotNull Context context, @NotNull String fileName, @NotNull ILogger logger) {
|
|
20
|
+
try (InputStream inputStream = context.getAssets().open(fileName);
|
|
21
|
+
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
|
|
22
|
+
|
|
23
|
+
StringBuilder stringBuilder = new StringBuilder();
|
|
24
|
+
String line;
|
|
25
|
+
while ((line = reader.readLine()) != null) {
|
|
26
|
+
stringBuilder.append(line);
|
|
27
|
+
}
|
|
28
|
+
String configFileContent = stringBuilder.toString();
|
|
29
|
+
return new JSONObject(configFileContent);
|
|
30
|
+
|
|
31
|
+
} catch (Exception e) {
|
|
32
|
+
logger.log(
|
|
33
|
+
SentryLevel.ERROR,
|
|
34
|
+
"Failed to read configuration file. Please make sure "
|
|
35
|
+
+ fileName
|
|
36
|
+
+ " exists in the root of your project.",
|
|
37
|
+
e);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -23,41 +23,27 @@ import com.facebook.react.bridge.ReactApplicationContext;
|
|
|
23
23
|
import com.facebook.react.bridge.ReadableArray;
|
|
24
24
|
import com.facebook.react.bridge.ReadableMap;
|
|
25
25
|
import com.facebook.react.bridge.ReadableMapKeySetIterator;
|
|
26
|
-
import com.facebook.react.bridge.ReadableType;
|
|
27
26
|
import com.facebook.react.bridge.UiThreadUtil;
|
|
28
27
|
import com.facebook.react.bridge.WritableArray;
|
|
29
28
|
import com.facebook.react.bridge.WritableMap;
|
|
30
29
|
import com.facebook.react.bridge.WritableNativeArray;
|
|
31
30
|
import com.facebook.react.bridge.WritableNativeMap;
|
|
32
|
-
import com.facebook.react.common.JavascriptException;
|
|
33
31
|
import io.sentry.Breadcrumb;
|
|
34
32
|
import io.sentry.ILogger;
|
|
35
33
|
import io.sentry.IScope;
|
|
36
34
|
import io.sentry.ISentryExecutorService;
|
|
37
35
|
import io.sentry.ISerializer;
|
|
38
|
-
import io.sentry.Integration;
|
|
39
|
-
import io.sentry.ProfileLifecycle;
|
|
40
36
|
import io.sentry.ScopesAdapter;
|
|
41
|
-
import io.sentry.ScreenshotStrategyType;
|
|
42
37
|
import io.sentry.Sentry;
|
|
43
38
|
import io.sentry.SentryDate;
|
|
44
39
|
import io.sentry.SentryDateProvider;
|
|
45
|
-
import io.sentry.SentryEvent;
|
|
46
40
|
import io.sentry.SentryExecutorService;
|
|
47
41
|
import io.sentry.SentryLevel;
|
|
48
42
|
import io.sentry.SentryOptions;
|
|
49
|
-
import io.sentry.SentryReplayOptions;
|
|
50
|
-
import io.sentry.SentryReplayOptions.SentryReplayQuality;
|
|
51
|
-
import io.sentry.UncaughtExceptionHandlerIntegration;
|
|
52
43
|
import io.sentry.android.core.AndroidLogger;
|
|
53
44
|
import io.sentry.android.core.AndroidProfiler;
|
|
54
|
-
import io.sentry.android.core.AnrIntegration;
|
|
55
|
-
import io.sentry.android.core.BuildConfig;
|
|
56
45
|
import io.sentry.android.core.BuildInfoProvider;
|
|
57
|
-
import io.sentry.android.core.CurrentActivityHolder;
|
|
58
46
|
import io.sentry.android.core.InternalSentrySdk;
|
|
59
|
-
import io.sentry.android.core.NdkIntegration;
|
|
60
|
-
import io.sentry.android.core.SentryAndroid;
|
|
61
47
|
import io.sentry.android.core.SentryAndroidDateProvider;
|
|
62
48
|
import io.sentry.android.core.SentryAndroidOptions;
|
|
63
49
|
import io.sentry.android.core.ViewHierarchyEventProcessor;
|
|
@@ -67,12 +53,8 @@ import io.sentry.android.core.performance.AppStartMetrics;
|
|
|
67
53
|
import io.sentry.protocol.Geo;
|
|
68
54
|
import io.sentry.protocol.SdkVersion;
|
|
69
55
|
import io.sentry.protocol.SentryId;
|
|
70
|
-
import io.sentry.protocol.SentryPackage;
|
|
71
56
|
import io.sentry.protocol.User;
|
|
72
57
|
import io.sentry.protocol.ViewHierarchy;
|
|
73
|
-
import io.sentry.react.replay.RNSentryReplayFragmentLifecycleTracer;
|
|
74
|
-
import io.sentry.react.replay.RNSentryReplayMask;
|
|
75
|
-
import io.sentry.react.replay.RNSentryReplayUnmask;
|
|
76
58
|
import io.sentry.util.DebugMetaPropertiesApplier;
|
|
77
59
|
import io.sentry.util.FileUtils;
|
|
78
60
|
import io.sentry.util.JsonSerializationUtils;
|
|
@@ -93,10 +75,8 @@ import java.util.ArrayList;
|
|
|
93
75
|
import java.util.HashMap;
|
|
94
76
|
import java.util.Iterator;
|
|
95
77
|
import java.util.List;
|
|
96
|
-
import java.util.Locale;
|
|
97
78
|
import java.util.Map;
|
|
98
79
|
import java.util.Properties;
|
|
99
|
-
import java.util.Set;
|
|
100
80
|
import java.util.concurrent.CountDownLatch;
|
|
101
81
|
import java.util.regex.Pattern;
|
|
102
82
|
import org.jetbrains.annotations.NotNull;
|
|
@@ -185,30 +165,13 @@ public class RNSentryModuleImpl {
|
|
|
185
165
|
}
|
|
186
166
|
}
|
|
187
167
|
|
|
188
|
-
private void initFragmentReplayTracking() {
|
|
189
|
-
final RNSentryReplayFragmentLifecycleTracer fragmentLifecycleTracer =
|
|
190
|
-
new RNSentryReplayFragmentLifecycleTracer(logger);
|
|
191
|
-
|
|
192
|
-
final @Nullable Activity currentActivity = getCurrentActivity();
|
|
193
|
-
if (!(currentActivity instanceof FragmentActivity)) {
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
final @NotNull FragmentActivity fragmentActivity = (FragmentActivity) currentActivity;
|
|
198
|
-
final @Nullable FragmentManager supportFragmentManager =
|
|
199
|
-
fragmentActivity.getSupportFragmentManager();
|
|
200
|
-
if (supportFragmentManager != null) {
|
|
201
|
-
supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleTracer, true);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
168
|
public void initNativeReactNavigationNewFrameTracking(Promise promise) {
|
|
206
169
|
this.initFragmentInitialFrameTracking();
|
|
207
170
|
}
|
|
208
171
|
|
|
209
172
|
public void initNativeSdk(final ReadableMap rnOptions, Promise promise) {
|
|
210
|
-
|
|
211
|
-
getApplicationContext(),
|
|
173
|
+
RNSentryStart.startWithOptions(
|
|
174
|
+
getApplicationContext(), rnOptions, getCurrentActivity(), logger);
|
|
212
175
|
|
|
213
176
|
promise.resolve(true);
|
|
214
177
|
}
|
|
@@ -224,320 +187,6 @@ public class RNSentryModuleImpl {
|
|
|
224
187
|
return context;
|
|
225
188
|
}
|
|
226
189
|
|
|
227
|
-
protected void getSentryAndroidOptions(
|
|
228
|
-
@NotNull SentryAndroidOptions options, @NotNull ReadableMap rnOptions, ILogger logger) {
|
|
229
|
-
@Nullable SdkVersion sdkVersion = options.getSdkVersion();
|
|
230
|
-
if (sdkVersion == null) {
|
|
231
|
-
sdkVersion = new SdkVersion(RNSentryVersion.ANDROID_SDK_NAME, BuildConfig.VERSION_NAME);
|
|
232
|
-
} else {
|
|
233
|
-
sdkVersion.setName(RNSentryVersion.ANDROID_SDK_NAME);
|
|
234
|
-
}
|
|
235
|
-
sdkVersion.addPackage(
|
|
236
|
-
RNSentryVersion.REACT_NATIVE_SDK_PACKAGE_NAME,
|
|
237
|
-
RNSentryVersion.REACT_NATIVE_SDK_PACKAGE_VERSION);
|
|
238
|
-
|
|
239
|
-
options.setSentryClientName(sdkVersion.getName() + "/" + sdkVersion.getVersion());
|
|
240
|
-
options.setNativeSdkName(RNSentryVersion.NATIVE_SDK_NAME);
|
|
241
|
-
options.setSdkVersion(sdkVersion);
|
|
242
|
-
|
|
243
|
-
if (rnOptions.hasKey("debug") && rnOptions.getBoolean("debug")) {
|
|
244
|
-
options.setDebug(true);
|
|
245
|
-
}
|
|
246
|
-
if (rnOptions.hasKey("enabled")) {
|
|
247
|
-
options.setEnabled(rnOptions.getBoolean("enabled"));
|
|
248
|
-
}
|
|
249
|
-
if (rnOptions.hasKey("dsn") && rnOptions.getString("dsn") != null) {
|
|
250
|
-
String dsn = rnOptions.getString("dsn");
|
|
251
|
-
logger.log(SentryLevel.INFO, String.format("Starting with DSN: '%s'", dsn));
|
|
252
|
-
options.setDsn(dsn);
|
|
253
|
-
} else {
|
|
254
|
-
// SentryAndroid needs an empty string fallback for the dsn.
|
|
255
|
-
options.setDsn("");
|
|
256
|
-
}
|
|
257
|
-
if (rnOptions.hasKey("sampleRate")) {
|
|
258
|
-
options.setSampleRate(rnOptions.getDouble("sampleRate"));
|
|
259
|
-
}
|
|
260
|
-
if (rnOptions.hasKey("sendClientReports")) {
|
|
261
|
-
options.setSendClientReports(rnOptions.getBoolean("sendClientReports"));
|
|
262
|
-
}
|
|
263
|
-
if (rnOptions.hasKey("maxBreadcrumbs")) {
|
|
264
|
-
options.setMaxBreadcrumbs(rnOptions.getInt("maxBreadcrumbs"));
|
|
265
|
-
}
|
|
266
|
-
if (rnOptions.hasKey("maxCacheItems")) {
|
|
267
|
-
options.setMaxCacheItems(rnOptions.getInt("maxCacheItems"));
|
|
268
|
-
}
|
|
269
|
-
if (rnOptions.hasKey("environment") && rnOptions.getString("environment") != null) {
|
|
270
|
-
options.setEnvironment(rnOptions.getString("environment"));
|
|
271
|
-
}
|
|
272
|
-
if (rnOptions.hasKey("release") && rnOptions.getString("release") != null) {
|
|
273
|
-
options.setRelease(rnOptions.getString("release"));
|
|
274
|
-
}
|
|
275
|
-
if (rnOptions.hasKey("dist") && rnOptions.getString("dist") != null) {
|
|
276
|
-
options.setDist(rnOptions.getString("dist"));
|
|
277
|
-
}
|
|
278
|
-
if (rnOptions.hasKey("enableAutoSessionTracking")) {
|
|
279
|
-
options.setEnableAutoSessionTracking(rnOptions.getBoolean("enableAutoSessionTracking"));
|
|
280
|
-
}
|
|
281
|
-
if (rnOptions.hasKey("sessionTrackingIntervalMillis")) {
|
|
282
|
-
options.setSessionTrackingIntervalMillis(rnOptions.getInt("sessionTrackingIntervalMillis"));
|
|
283
|
-
}
|
|
284
|
-
if (rnOptions.hasKey("shutdownTimeout")) {
|
|
285
|
-
options.setShutdownTimeoutMillis(rnOptions.getInt("shutdownTimeout"));
|
|
286
|
-
}
|
|
287
|
-
if (rnOptions.hasKey("enableNdkScopeSync")) {
|
|
288
|
-
options.setEnableScopeSync(rnOptions.getBoolean("enableNdkScopeSync"));
|
|
289
|
-
}
|
|
290
|
-
if (rnOptions.hasKey("attachStacktrace")) {
|
|
291
|
-
options.setAttachStacktrace(rnOptions.getBoolean("attachStacktrace"));
|
|
292
|
-
}
|
|
293
|
-
if (rnOptions.hasKey("attachThreads")) {
|
|
294
|
-
// JS use top level stacktrace and android attaches Threads which hides them so
|
|
295
|
-
// by default we hide.
|
|
296
|
-
options.setAttachThreads(rnOptions.getBoolean("attachThreads"));
|
|
297
|
-
}
|
|
298
|
-
if (rnOptions.hasKey("attachScreenshot")) {
|
|
299
|
-
options.setAttachScreenshot(rnOptions.getBoolean("attachScreenshot"));
|
|
300
|
-
}
|
|
301
|
-
if (rnOptions.hasKey("attachViewHierarchy")) {
|
|
302
|
-
options.setAttachViewHierarchy(rnOptions.getBoolean("attachViewHierarchy"));
|
|
303
|
-
}
|
|
304
|
-
if (rnOptions.hasKey("sendDefaultPii")) {
|
|
305
|
-
options.setSendDefaultPii(rnOptions.getBoolean("sendDefaultPii"));
|
|
306
|
-
}
|
|
307
|
-
if (rnOptions.hasKey("maxQueueSize")) {
|
|
308
|
-
options.setMaxQueueSize(rnOptions.getInt("maxQueueSize"));
|
|
309
|
-
}
|
|
310
|
-
if (rnOptions.hasKey("enableNdk")) {
|
|
311
|
-
options.setEnableNdk(rnOptions.getBoolean("enableNdk"));
|
|
312
|
-
}
|
|
313
|
-
if (rnOptions.hasKey("enableLogs")) {
|
|
314
|
-
options.getLogs().setEnabled(rnOptions.getBoolean("enableLogs"));
|
|
315
|
-
}
|
|
316
|
-
if (rnOptions.hasKey("spotlight")) {
|
|
317
|
-
if (rnOptions.getType("spotlight") == ReadableType.Boolean) {
|
|
318
|
-
options.setEnableSpotlight(rnOptions.getBoolean("spotlight"));
|
|
319
|
-
options.setSpotlightConnectionUrl(rnOptions.getString("defaultSidecarUrl"));
|
|
320
|
-
} else if (rnOptions.getType("spotlight") == ReadableType.String) {
|
|
321
|
-
options.setEnableSpotlight(true);
|
|
322
|
-
options.setSpotlightConnectionUrl(rnOptions.getString("spotlight"));
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
SentryReplayOptions replayOptions = getReplayOptions(rnOptions);
|
|
327
|
-
options.setSessionReplay(replayOptions);
|
|
328
|
-
// Check if the replay integration is available on the classpath. It's already
|
|
329
|
-
// kept from R8
|
|
330
|
-
// shrinking by sentry-android-core
|
|
331
|
-
final boolean isReplayAvailable =
|
|
332
|
-
loadClass.isClassAvailable("io.sentry.android.replay.ReplayIntegration", logger);
|
|
333
|
-
if (isReplayEnabled(replayOptions) && isReplayAvailable) {
|
|
334
|
-
options.getReplayController().setBreadcrumbConverter(new RNSentryReplayBreadcrumbConverter());
|
|
335
|
-
initFragmentReplayTracking();
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// Configure Android UI Profiling
|
|
339
|
-
configureAndroidProfiling(options, rnOptions);
|
|
340
|
-
|
|
341
|
-
// Exclude Dev Server and Sentry Dsn request from Breadcrumbs
|
|
342
|
-
String dsn = getURLFromDSN(rnOptions.getString("dsn"));
|
|
343
|
-
String devServerUrl = rnOptions.getString("devServerUrl");
|
|
344
|
-
options.setBeforeBreadcrumb(
|
|
345
|
-
(breadcrumb, hint) -> {
|
|
346
|
-
Object urlObject = breadcrumb.getData("url");
|
|
347
|
-
String url = urlObject instanceof String ? (String) urlObject : "";
|
|
348
|
-
if ("http".equals(breadcrumb.getType())
|
|
349
|
-
&& ((dsn != null && url.startsWith(dsn))
|
|
350
|
-
|| (devServerUrl != null && url.startsWith(devServerUrl)))) {
|
|
351
|
-
return null;
|
|
352
|
-
}
|
|
353
|
-
return breadcrumb;
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
// React native internally throws a JavascriptException.
|
|
357
|
-
// we want to ignore it on the native side to avoid sending it twice.
|
|
358
|
-
options.addIgnoredExceptionForType(JavascriptException.class);
|
|
359
|
-
|
|
360
|
-
trySetIgnoreErrors(options, rnOptions);
|
|
361
|
-
|
|
362
|
-
options.setBeforeSend(
|
|
363
|
-
(event, hint) -> {
|
|
364
|
-
setEventOriginTag(event);
|
|
365
|
-
addPackages(event, options.getSdkVersion());
|
|
366
|
-
|
|
367
|
-
return event;
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
if (rnOptions.hasKey("enableNativeCrashHandling")
|
|
371
|
-
&& !rnOptions.getBoolean("enableNativeCrashHandling")) {
|
|
372
|
-
final List<Integration> integrations = options.getIntegrations();
|
|
373
|
-
for (final Integration integration : integrations) {
|
|
374
|
-
if (integration instanceof UncaughtExceptionHandlerIntegration
|
|
375
|
-
|| integration instanceof AnrIntegration
|
|
376
|
-
|| integration instanceof NdkIntegration) {
|
|
377
|
-
integrations.remove(integration);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
logger.log(
|
|
382
|
-
SentryLevel.INFO, String.format("Native Integrations '%s'", options.getIntegrations()));
|
|
383
|
-
|
|
384
|
-
final CurrentActivityHolder currentActivityHolder = CurrentActivityHolder.getInstance();
|
|
385
|
-
final Activity currentActivity = getCurrentActivity();
|
|
386
|
-
if (currentActivity != null) {
|
|
387
|
-
currentActivityHolder.setActivity(currentActivity);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
private boolean isReplayEnabled(SentryReplayOptions replayOptions) {
|
|
392
|
-
return replayOptions.getSessionSampleRate() != null
|
|
393
|
-
|| replayOptions.getOnErrorSampleRate() != null;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
private SentryReplayOptions getReplayOptions(@NotNull ReadableMap rnOptions) {
|
|
397
|
-
final SdkVersion replaySdkVersion =
|
|
398
|
-
new SdkVersion(
|
|
399
|
-
RNSentryVersion.REACT_NATIVE_SDK_NAME,
|
|
400
|
-
RNSentryVersion.REACT_NATIVE_SDK_PACKAGE_VERSION);
|
|
401
|
-
@NotNull
|
|
402
|
-
final SentryReplayOptions androidReplayOptions =
|
|
403
|
-
new SentryReplayOptions(false, replaySdkVersion);
|
|
404
|
-
|
|
405
|
-
if (!(rnOptions.hasKey("replaysSessionSampleRate")
|
|
406
|
-
|| rnOptions.hasKey("replaysOnErrorSampleRate"))) {
|
|
407
|
-
return androidReplayOptions;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
androidReplayOptions.setSessionSampleRate(
|
|
411
|
-
rnOptions.hasKey("replaysSessionSampleRate")
|
|
412
|
-
? rnOptions.getDouble("replaysSessionSampleRate")
|
|
413
|
-
: null);
|
|
414
|
-
androidReplayOptions.setOnErrorSampleRate(
|
|
415
|
-
rnOptions.hasKey("replaysOnErrorSampleRate")
|
|
416
|
-
? rnOptions.getDouble("replaysOnErrorSampleRate")
|
|
417
|
-
: null);
|
|
418
|
-
|
|
419
|
-
if (rnOptions.hasKey("replaysSessionQuality")) {
|
|
420
|
-
final String qualityString = rnOptions.getString("replaysSessionQuality");
|
|
421
|
-
final SentryReplayQuality quality = parseReplayQuality(qualityString);
|
|
422
|
-
androidReplayOptions.setQuality(quality);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
if (!rnOptions.hasKey("mobileReplayOptions")) {
|
|
426
|
-
return androidReplayOptions;
|
|
427
|
-
}
|
|
428
|
-
@Nullable final ReadableMap rnMobileReplayOptions = rnOptions.getMap("mobileReplayOptions");
|
|
429
|
-
if (rnMobileReplayOptions == null) {
|
|
430
|
-
return androidReplayOptions;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
androidReplayOptions.setMaskAllText(
|
|
434
|
-
!rnMobileReplayOptions.hasKey("maskAllText")
|
|
435
|
-
|| rnMobileReplayOptions.getBoolean("maskAllText"));
|
|
436
|
-
androidReplayOptions.setMaskAllImages(
|
|
437
|
-
!rnMobileReplayOptions.hasKey("maskAllImages")
|
|
438
|
-
|| rnMobileReplayOptions.getBoolean("maskAllImages"));
|
|
439
|
-
|
|
440
|
-
final boolean redactVectors =
|
|
441
|
-
!rnMobileReplayOptions.hasKey("maskAllVectors")
|
|
442
|
-
|| rnMobileReplayOptions.getBoolean("maskAllVectors");
|
|
443
|
-
if (redactVectors) {
|
|
444
|
-
androidReplayOptions.addMaskViewClass("com.horcrux.svg.SvgView"); // react-native-svg
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
if (rnMobileReplayOptions.hasKey("screenshotStrategy")) {
|
|
448
|
-
final String screenshotStrategyString = rnMobileReplayOptions.getString("screenshotStrategy");
|
|
449
|
-
final ScreenshotStrategyType screenshotStrategy =
|
|
450
|
-
parseScreenshotStrategy(screenshotStrategyString);
|
|
451
|
-
androidReplayOptions.setScreenshotStrategy(screenshotStrategy);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
androidReplayOptions.setMaskViewContainerClass(RNSentryReplayMask.class.getName());
|
|
455
|
-
androidReplayOptions.setUnmaskViewContainerClass(RNSentryReplayUnmask.class.getName());
|
|
456
|
-
|
|
457
|
-
return androidReplayOptions;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
private ScreenshotStrategyType parseScreenshotStrategy(@Nullable String strategyString) {
|
|
461
|
-
if (strategyString == null) {
|
|
462
|
-
return ScreenshotStrategyType.PIXEL_COPY;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
switch (strategyString.toLowerCase(Locale.ROOT)) {
|
|
466
|
-
case "canvas":
|
|
467
|
-
return ScreenshotStrategyType.CANVAS;
|
|
468
|
-
default:
|
|
469
|
-
return ScreenshotStrategyType.PIXEL_COPY;
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
private SentryReplayQuality parseReplayQuality(@Nullable String qualityString) {
|
|
474
|
-
if (qualityString == null) {
|
|
475
|
-
return SentryReplayQuality.MEDIUM;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
switch (qualityString.toLowerCase(Locale.ROOT)) {
|
|
479
|
-
case "low":
|
|
480
|
-
return SentryReplayQuality.LOW;
|
|
481
|
-
case "medium":
|
|
482
|
-
return SentryReplayQuality.MEDIUM;
|
|
483
|
-
case "high":
|
|
484
|
-
return SentryReplayQuality.HIGH;
|
|
485
|
-
default:
|
|
486
|
-
return SentryReplayQuality.MEDIUM;
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
private void configureAndroidProfiling(
|
|
491
|
-
@NotNull SentryAndroidOptions options, @NotNull ReadableMap rnOptions) {
|
|
492
|
-
if (!rnOptions.hasKey("_experiments")) {
|
|
493
|
-
return;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
@Nullable final ReadableMap experiments = rnOptions.getMap("_experiments");
|
|
497
|
-
if (experiments == null || !experiments.hasKey("androidProfilingOptions")) {
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
@Nullable
|
|
502
|
-
final ReadableMap androidProfilingOptions = experiments.getMap("androidProfilingOptions");
|
|
503
|
-
if (androidProfilingOptions == null) {
|
|
504
|
-
return;
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
// Set profile session sample rate
|
|
508
|
-
if (androidProfilingOptions.hasKey("profileSessionSampleRate")) {
|
|
509
|
-
final double profileSessionSampleRate =
|
|
510
|
-
androidProfilingOptions.getDouble("profileSessionSampleRate");
|
|
511
|
-
options.setProfileSessionSampleRate(profileSessionSampleRate);
|
|
512
|
-
logger.log(
|
|
513
|
-
SentryLevel.INFO,
|
|
514
|
-
String.format(
|
|
515
|
-
"Android UI Profiling profileSessionSampleRate set to: %.2f",
|
|
516
|
-
profileSessionSampleRate));
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
// Set profiling lifecycle mode
|
|
520
|
-
if (androidProfilingOptions.hasKey("lifecycle")) {
|
|
521
|
-
final String lifecycle = androidProfilingOptions.getString("lifecycle");
|
|
522
|
-
if ("manual".equalsIgnoreCase(lifecycle)) {
|
|
523
|
-
options.setProfileLifecycle(ProfileLifecycle.MANUAL);
|
|
524
|
-
logger.log(SentryLevel.INFO, "Android UI Profile Lifecycle set to MANUAL");
|
|
525
|
-
} else if ("trace".equalsIgnoreCase(lifecycle)) {
|
|
526
|
-
options.setProfileLifecycle(ProfileLifecycle.TRACE);
|
|
527
|
-
logger.log(SentryLevel.INFO, "Android UI Profile Lifecycle set to TRACE");
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
// Set start on app start
|
|
532
|
-
if (androidProfilingOptions.hasKey("startOnAppStart")) {
|
|
533
|
-
final boolean startOnAppStart = androidProfilingOptions.getBoolean("startOnAppStart");
|
|
534
|
-
options.setStartProfilerOnAppStart(startOnAppStart);
|
|
535
|
-
logger.log(
|
|
536
|
-
SentryLevel.INFO,
|
|
537
|
-
String.format("Android UI Profiling startOnAppStart set to %b", startOnAppStart));
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
|
|
541
190
|
public void crash() {
|
|
542
191
|
throw new RuntimeException("TEST - Sentry Client Crash (only works in release mode)");
|
|
543
192
|
}
|
|
@@ -1276,51 +925,6 @@ public class RNSentryModuleImpl {
|
|
|
1276
925
|
promise.resolve(Sentry.isCrashedLastRun());
|
|
1277
926
|
}
|
|
1278
927
|
|
|
1279
|
-
private void setEventOriginTag(SentryEvent event) {
|
|
1280
|
-
// We hardcode native-java as only java events are processed by the Android SDK.
|
|
1281
|
-
SdkVersion sdk = event.getSdk();
|
|
1282
|
-
if (sdk != null) {
|
|
1283
|
-
switch (sdk.getName()) {
|
|
1284
|
-
case RNSentryVersion.NATIVE_SDK_NAME:
|
|
1285
|
-
setEventEnvironmentTag(event, "native");
|
|
1286
|
-
break;
|
|
1287
|
-
case RNSentryVersion.ANDROID_SDK_NAME:
|
|
1288
|
-
setEventEnvironmentTag(event, "java");
|
|
1289
|
-
break;
|
|
1290
|
-
default:
|
|
1291
|
-
break;
|
|
1292
|
-
}
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
|
|
1296
|
-
private void setEventEnvironmentTag(SentryEvent event, String environment) {
|
|
1297
|
-
event.setTag("event.origin", "android");
|
|
1298
|
-
event.setTag("event.environment", environment);
|
|
1299
|
-
}
|
|
1300
|
-
|
|
1301
|
-
private void addPackages(SentryEvent event, SdkVersion sdk) {
|
|
1302
|
-
SdkVersion eventSdk = event.getSdk();
|
|
1303
|
-
if (eventSdk != null
|
|
1304
|
-
&& "sentry.javascript.react-native".equals(eventSdk.getName())
|
|
1305
|
-
&& sdk != null) {
|
|
1306
|
-
Set<SentryPackage> sentryPackages = sdk.getPackageSet();
|
|
1307
|
-
if (sentryPackages != null) {
|
|
1308
|
-
for (SentryPackage sentryPackage : sentryPackages) {
|
|
1309
|
-
eventSdk.addPackage(sentryPackage.getName(), sentryPackage.getVersion());
|
|
1310
|
-
}
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
|
-
Set<String> integrations = sdk.getIntegrationSet();
|
|
1314
|
-
if (integrations != null) {
|
|
1315
|
-
for (String integration : integrations) {
|
|
1316
|
-
eventSdk.addIntegration(integration);
|
|
1317
|
-
}
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
event.setSdk(eventSdk);
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
928
|
private boolean checkAndroidXAvailability() {
|
|
1325
929
|
try {
|
|
1326
930
|
Class.forName("androidx.core.app.FrameMetricsAggregator");
|