@sentry/react-native 7.12.0 → 8.0.0-beta.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 +9 -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 -395
- package/android/src/main/java/io/sentry/react/RNSentrySDK.java +68 -0
- package/android/src/main/java/io/sentry/react/RNSentryStart.java +413 -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+fetchNativeStack.m +1 -0
- package/ios/RNSentry.h +3 -0
- package/ios/RNSentry.mm +12 -45
- 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/SentrySDKWrapper.m +2 -2
- 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
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
package io.sentry.react;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
5
|
+
import io.sentry.ILogger;
|
|
6
|
+
import io.sentry.Sentry;
|
|
7
|
+
import io.sentry.SentryLevel;
|
|
8
|
+
import io.sentry.android.core.AndroidLogger;
|
|
9
|
+
import io.sentry.android.core.SentryAndroidOptions;
|
|
10
|
+
import org.jetbrains.annotations.NotNull;
|
|
11
|
+
import org.json.JSONObject;
|
|
12
|
+
|
|
13
|
+
public final class RNSentrySDK {
|
|
14
|
+
private static final String CONFIGURATION_FILE = "sentry.options.json";
|
|
15
|
+
private static final String NAME = "RNSentrySDK";
|
|
16
|
+
|
|
17
|
+
private static final ILogger logger = new AndroidLogger(NAME);
|
|
18
|
+
|
|
19
|
+
private RNSentrySDK() {
|
|
20
|
+
throw new AssertionError("Utility class should not be instantiated");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static void init(
|
|
24
|
+
@NotNull final Context context,
|
|
25
|
+
@NotNull Sentry.OptionsConfiguration<SentryAndroidOptions> configuration,
|
|
26
|
+
@NotNull String configurationFile,
|
|
27
|
+
@NotNull ILogger logger) {
|
|
28
|
+
try {
|
|
29
|
+
JSONObject jsonObject =
|
|
30
|
+
RNSentryJsonUtils.getOptionsFromConfigurationFile(context, configurationFile, logger);
|
|
31
|
+
if (jsonObject == null) {
|
|
32
|
+
RNSentryStart.startWithConfiguration(context, configuration);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
ReadableMap rnOptions = RNSentryJsonConverter.convertToWritable(jsonObject);
|
|
36
|
+
if (rnOptions == null) {
|
|
37
|
+
RNSentryStart.startWithConfiguration(context, configuration);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
RNSentryStart.startWithOptions(context, rnOptions, configuration, logger);
|
|
41
|
+
} catch (Exception e) {
|
|
42
|
+
logger.log(
|
|
43
|
+
SentryLevel.ERROR, "Failed to start Sentry with options from configuration file.", e);
|
|
44
|
+
throw new RuntimeException("Failed to initialize Sentry's React Native SDK", e);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @experimental Start the Native Android SDK with the provided configuration options. Uses as a
|
|
50
|
+
* base configurations the `sentry.options.json` configuration file if it exists.
|
|
51
|
+
* @param context Android Context
|
|
52
|
+
* @param configuration configuration options
|
|
53
|
+
*/
|
|
54
|
+
public static void init(
|
|
55
|
+
@NotNull final Context context,
|
|
56
|
+
@NotNull Sentry.OptionsConfiguration<SentryAndroidOptions> configuration) {
|
|
57
|
+
init(context, configuration, CONFIGURATION_FILE, logger);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @experimental Start the Native Android SDK with options from `sentry.options.json`
|
|
62
|
+
* configuration file.
|
|
63
|
+
* @param context Android Context
|
|
64
|
+
*/
|
|
65
|
+
public static void init(@NotNull final Context context) {
|
|
66
|
+
init(context, options -> {}, CONFIGURATION_FILE, logger);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
package io.sentry.react;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import android.content.Context;
|
|
5
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
6
|
+
import com.facebook.react.bridge.ReadableType;
|
|
7
|
+
import com.facebook.react.common.JavascriptException;
|
|
8
|
+
import io.sentry.ILogger;
|
|
9
|
+
import io.sentry.ProfileLifecycle;
|
|
10
|
+
import io.sentry.Sentry;
|
|
11
|
+
import io.sentry.SentryEvent;
|
|
12
|
+
import io.sentry.SentryLevel;
|
|
13
|
+
import io.sentry.SentryOptions.BeforeSendCallback;
|
|
14
|
+
import io.sentry.SentryReplayOptions;
|
|
15
|
+
import io.sentry.UncaughtExceptionHandlerIntegration;
|
|
16
|
+
import io.sentry.android.core.AnrIntegration;
|
|
17
|
+
import io.sentry.android.core.BuildConfig;
|
|
18
|
+
import io.sentry.android.core.CurrentActivityHolder;
|
|
19
|
+
import io.sentry.android.core.NdkIntegration;
|
|
20
|
+
import io.sentry.android.core.SentryAndroid;
|
|
21
|
+
import io.sentry.android.core.SentryAndroidOptions;
|
|
22
|
+
import io.sentry.protocol.SdkVersion;
|
|
23
|
+
import io.sentry.react.replay.RNSentryReplayMask;
|
|
24
|
+
import io.sentry.react.replay.RNSentryReplayUnmask;
|
|
25
|
+
import java.net.URI;
|
|
26
|
+
import java.net.URISyntaxException;
|
|
27
|
+
import org.jetbrains.annotations.NotNull;
|
|
28
|
+
import org.jetbrains.annotations.Nullable;
|
|
29
|
+
|
|
30
|
+
final class RNSentryStart {
|
|
31
|
+
|
|
32
|
+
private RNSentryStart() {
|
|
33
|
+
throw new AssertionError("Utility class should not be instantiated");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static void startWithConfiguration(
|
|
37
|
+
@NotNull final Context context,
|
|
38
|
+
@NotNull Sentry.OptionsConfiguration<SentryAndroidOptions> configuration) {
|
|
39
|
+
Sentry.OptionsConfiguration<SentryAndroidOptions> defaults =
|
|
40
|
+
options -> updateWithReactDefaults(options, null);
|
|
41
|
+
RNSentryCompositeOptionsConfiguration compositeConfiguration =
|
|
42
|
+
new RNSentryCompositeOptionsConfiguration(
|
|
43
|
+
defaults, configuration, RNSentryStart::updateWithReactFinals);
|
|
44
|
+
SentryAndroid.init(context, compositeConfiguration);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static void startWithOptions(
|
|
48
|
+
@NotNull final Context context,
|
|
49
|
+
@NotNull final ReadableMap rnOptions,
|
|
50
|
+
@NotNull Sentry.OptionsConfiguration<SentryAndroidOptions> configuration,
|
|
51
|
+
@NotNull ILogger logger) {
|
|
52
|
+
Sentry.OptionsConfiguration<SentryAndroidOptions> defaults =
|
|
53
|
+
options -> updateWithReactDefaults(options, null);
|
|
54
|
+
Sentry.OptionsConfiguration<SentryAndroidOptions> rnConfigurationOptions =
|
|
55
|
+
options -> getSentryAndroidOptions(options, rnOptions, logger);
|
|
56
|
+
RNSentryCompositeOptionsConfiguration compositeConfiguration =
|
|
57
|
+
new RNSentryCompositeOptionsConfiguration(
|
|
58
|
+
rnConfigurationOptions, defaults, configuration, RNSentryStart::updateWithReactFinals);
|
|
59
|
+
SentryAndroid.init(context, compositeConfiguration);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static void startWithOptions(
|
|
63
|
+
@NotNull final Context context,
|
|
64
|
+
@NotNull final ReadableMap rnOptions,
|
|
65
|
+
@Nullable Activity currentActivity,
|
|
66
|
+
@NotNull ILogger logger) {
|
|
67
|
+
Sentry.OptionsConfiguration<SentryAndroidOptions> defaults =
|
|
68
|
+
options -> updateWithReactDefaults(options, currentActivity);
|
|
69
|
+
Sentry.OptionsConfiguration<SentryAndroidOptions> rnConfigurationOptions =
|
|
70
|
+
options -> getSentryAndroidOptions(options, rnOptions, logger);
|
|
71
|
+
RNSentryCompositeOptionsConfiguration compositeConfiguration =
|
|
72
|
+
new RNSentryCompositeOptionsConfiguration(
|
|
73
|
+
rnConfigurationOptions, defaults, RNSentryStart::updateWithReactFinals);
|
|
74
|
+
SentryAndroid.init(context, compositeConfiguration);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static void getSentryAndroidOptions(
|
|
78
|
+
@NotNull SentryAndroidOptions options,
|
|
79
|
+
@NotNull ReadableMap rnOptions,
|
|
80
|
+
@NotNull ILogger logger) {
|
|
81
|
+
if (rnOptions.hasKey("debug") && rnOptions.getBoolean("debug")) {
|
|
82
|
+
options.setDebug(true);
|
|
83
|
+
}
|
|
84
|
+
if (rnOptions.hasKey("dsn") && rnOptions.getString("dsn") != null) {
|
|
85
|
+
String dsn = rnOptions.getString("dsn");
|
|
86
|
+
logger.log(SentryLevel.INFO, String.format("Starting with DSN: '%s'", dsn));
|
|
87
|
+
options.setDsn(dsn);
|
|
88
|
+
} else {
|
|
89
|
+
// SentryAndroid needs an empty string fallback for the dsn.
|
|
90
|
+
options.setDsn("");
|
|
91
|
+
}
|
|
92
|
+
if (rnOptions.hasKey("sampleRate")) {
|
|
93
|
+
options.setSampleRate(rnOptions.getDouble("sampleRate"));
|
|
94
|
+
}
|
|
95
|
+
if (rnOptions.hasKey("sendClientReports")) {
|
|
96
|
+
options.setSendClientReports(rnOptions.getBoolean("sendClientReports"));
|
|
97
|
+
}
|
|
98
|
+
if (rnOptions.hasKey("maxBreadcrumbs")) {
|
|
99
|
+
options.setMaxBreadcrumbs(rnOptions.getInt("maxBreadcrumbs"));
|
|
100
|
+
}
|
|
101
|
+
if (rnOptions.hasKey("maxCacheItems")) {
|
|
102
|
+
options.setMaxCacheItems(rnOptions.getInt("maxCacheItems"));
|
|
103
|
+
}
|
|
104
|
+
if (rnOptions.hasKey("environment") && rnOptions.getString("environment") != null) {
|
|
105
|
+
options.setEnvironment(rnOptions.getString("environment"));
|
|
106
|
+
}
|
|
107
|
+
if (rnOptions.hasKey("release") && rnOptions.getString("release") != null) {
|
|
108
|
+
options.setRelease(rnOptions.getString("release"));
|
|
109
|
+
}
|
|
110
|
+
if (rnOptions.hasKey("dist") && rnOptions.getString("dist") != null) {
|
|
111
|
+
options.setDist(rnOptions.getString("dist"));
|
|
112
|
+
}
|
|
113
|
+
if (rnOptions.hasKey("enableAutoSessionTracking")) {
|
|
114
|
+
options.setEnableAutoSessionTracking(rnOptions.getBoolean("enableAutoSessionTracking"));
|
|
115
|
+
}
|
|
116
|
+
if (rnOptions.hasKey("sessionTrackingIntervalMillis")) {
|
|
117
|
+
options.setSessionTrackingIntervalMillis(rnOptions.getInt("sessionTrackingIntervalMillis"));
|
|
118
|
+
}
|
|
119
|
+
if (rnOptions.hasKey("shutdownTimeout")) {
|
|
120
|
+
options.setShutdownTimeoutMillis(rnOptions.getInt("shutdownTimeout"));
|
|
121
|
+
}
|
|
122
|
+
if (rnOptions.hasKey("enableNdkScopeSync")) {
|
|
123
|
+
options.setEnableScopeSync(rnOptions.getBoolean("enableNdkScopeSync"));
|
|
124
|
+
}
|
|
125
|
+
if (rnOptions.hasKey("attachStacktrace")) {
|
|
126
|
+
options.setAttachStacktrace(rnOptions.getBoolean("attachStacktrace"));
|
|
127
|
+
}
|
|
128
|
+
if (rnOptions.hasKey("attachThreads")) {
|
|
129
|
+
// JS use top level stacktrace and android attaches Threads which hides them so
|
|
130
|
+
// by default we hide.
|
|
131
|
+
options.setAttachThreads(rnOptions.getBoolean("attachThreads"));
|
|
132
|
+
}
|
|
133
|
+
if (rnOptions.hasKey("attachScreenshot")) {
|
|
134
|
+
options.setAttachScreenshot(rnOptions.getBoolean("attachScreenshot"));
|
|
135
|
+
}
|
|
136
|
+
if (rnOptions.hasKey("attachViewHierarchy")) {
|
|
137
|
+
options.setAttachViewHierarchy(rnOptions.getBoolean("attachViewHierarchy"));
|
|
138
|
+
}
|
|
139
|
+
if (rnOptions.hasKey("sendDefaultPii")) {
|
|
140
|
+
options.setSendDefaultPii(rnOptions.getBoolean("sendDefaultPii"));
|
|
141
|
+
}
|
|
142
|
+
if (rnOptions.hasKey("maxQueueSize")) {
|
|
143
|
+
options.setMaxQueueSize(rnOptions.getInt("maxQueueSize"));
|
|
144
|
+
}
|
|
145
|
+
if (rnOptions.hasKey("enableNdk")) {
|
|
146
|
+
options.setEnableNdk(rnOptions.getBoolean("enableNdk"));
|
|
147
|
+
}
|
|
148
|
+
if (rnOptions.hasKey("spotlight")) {
|
|
149
|
+
if (rnOptions.getType("spotlight") == ReadableType.Boolean) {
|
|
150
|
+
options.setEnableSpotlight(rnOptions.getBoolean("spotlight"));
|
|
151
|
+
if (rnOptions.hasKey("defaultSidecarUrl")) {
|
|
152
|
+
options.setSpotlightConnectionUrl(rnOptions.getString("defaultSidecarUrl"));
|
|
153
|
+
}
|
|
154
|
+
} else if (rnOptions.getType("spotlight") == ReadableType.String) {
|
|
155
|
+
options.setEnableSpotlight(true);
|
|
156
|
+
options.setSpotlightConnectionUrl(rnOptions.getString("spotlight"));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
SentryReplayOptions replayOptions = getReplayOptions(rnOptions);
|
|
161
|
+
options.setSessionReplay(replayOptions);
|
|
162
|
+
if (isReplayEnabled(replayOptions)) {
|
|
163
|
+
options.getReplayController().setBreadcrumbConverter(new RNSentryReplayBreadcrumbConverter());
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Configure Android UI Profiling
|
|
167
|
+
configureAndroidProfiling(options, rnOptions, logger);
|
|
168
|
+
|
|
169
|
+
// Exclude Dev Server and Sentry Dsn request from Breadcrumbs
|
|
170
|
+
String dsn = rnOptions.hasKey("dsn") ? getURLFromDSN(rnOptions.getString("dsn")) : null;
|
|
171
|
+
String devServerUrl =
|
|
172
|
+
rnOptions.hasKey("devServerUrl") ? rnOptions.getString("devServerUrl") : null;
|
|
173
|
+
options.setBeforeBreadcrumb(
|
|
174
|
+
(breadcrumb, hint) -> {
|
|
175
|
+
Object urlObject = breadcrumb.getData("url");
|
|
176
|
+
String url = urlObject instanceof String ? (String) urlObject : "";
|
|
177
|
+
if ("http".equals(breadcrumb.getType())
|
|
178
|
+
&& ((dsn != null && url.startsWith(dsn))
|
|
179
|
+
|| (devServerUrl != null && url.startsWith(devServerUrl)))) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
return breadcrumb;
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
if (rnOptions.hasKey("enableNativeCrashHandling")
|
|
186
|
+
&& !rnOptions.getBoolean("enableNativeCrashHandling")) {
|
|
187
|
+
options
|
|
188
|
+
.getIntegrations()
|
|
189
|
+
.removeIf(
|
|
190
|
+
integration ->
|
|
191
|
+
integration instanceof UncaughtExceptionHandlerIntegration
|
|
192
|
+
|| integration instanceof AnrIntegration
|
|
193
|
+
|| integration instanceof NdkIntegration);
|
|
194
|
+
}
|
|
195
|
+
logger.log(
|
|
196
|
+
SentryLevel.INFO, String.format("Native Integrations '%s'", options.getIntegrations()));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private static void configureAndroidProfiling(
|
|
200
|
+
@NotNull SentryAndroidOptions options,
|
|
201
|
+
@NotNull ReadableMap rnOptions,
|
|
202
|
+
@NotNull ILogger logger) {
|
|
203
|
+
if (!rnOptions.hasKey("_experiments")) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
@Nullable final ReadableMap experiments = rnOptions.getMap("_experiments");
|
|
208
|
+
if (experiments == null || !experiments.hasKey("profilingOptions")) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
@Nullable final ReadableMap profilingOptions = experiments.getMap("profilingOptions");
|
|
213
|
+
if (profilingOptions == null) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Set profile session sample rate
|
|
218
|
+
if (profilingOptions.hasKey("profileSessionSampleRate")) {
|
|
219
|
+
if (profilingOptions.getType("profileSessionSampleRate") == ReadableType.Number) {
|
|
220
|
+
final double profileSessionSampleRate =
|
|
221
|
+
profilingOptions.getDouble("profileSessionSampleRate");
|
|
222
|
+
options.setProfileSessionSampleRate(profileSessionSampleRate);
|
|
223
|
+
logger.log(
|
|
224
|
+
SentryLevel.INFO,
|
|
225
|
+
String.format(
|
|
226
|
+
"UI Profiling profileSessionSampleRate set to: %.2f", profileSessionSampleRate));
|
|
227
|
+
} else {
|
|
228
|
+
logger.log(
|
|
229
|
+
SentryLevel.WARNING,
|
|
230
|
+
"UI Profiling profileSessionSampleRate must be a number, ignoring invalid value");
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Set profiling lifecycle mode
|
|
235
|
+
if (profilingOptions.hasKey("lifecycle")) {
|
|
236
|
+
if (profilingOptions.getType("lifecycle") == ReadableType.String) {
|
|
237
|
+
final String lifecycle = profilingOptions.getString("lifecycle");
|
|
238
|
+
if ("manual".equalsIgnoreCase(lifecycle)) {
|
|
239
|
+
options.setProfileLifecycle(ProfileLifecycle.MANUAL);
|
|
240
|
+
logger.log(SentryLevel.INFO, "UI Profile Lifecycle set to MANUAL");
|
|
241
|
+
} else if ("trace".equalsIgnoreCase(lifecycle)) {
|
|
242
|
+
options.setProfileLifecycle(ProfileLifecycle.TRACE);
|
|
243
|
+
logger.log(SentryLevel.INFO, "UI Profile Lifecycle set to TRACE");
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
246
|
+
logger.log(
|
|
247
|
+
SentryLevel.WARNING, "UI Profiling lifecycle must be a string, ignoring invalid value");
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Set start on app start
|
|
252
|
+
if (profilingOptions.hasKey("startOnAppStart")) {
|
|
253
|
+
if (profilingOptions.getType("startOnAppStart") == ReadableType.Boolean) {
|
|
254
|
+
final boolean startOnAppStart = profilingOptions.getBoolean("startOnAppStart");
|
|
255
|
+
options.setStartProfilerOnAppStart(startOnAppStart);
|
|
256
|
+
logger.log(
|
|
257
|
+
SentryLevel.INFO,
|
|
258
|
+
String.format("UI Profiling startOnAppStart set to %b", startOnAppStart));
|
|
259
|
+
} else {
|
|
260
|
+
logger.log(
|
|
261
|
+
SentryLevel.WARNING,
|
|
262
|
+
"UI Profiling startOnAppStart must be a boolean, ignoring invalid value");
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* This function updates the options with RNSentry defaults. These default can be overwritten by
|
|
269
|
+
* users during manual native initialization.
|
|
270
|
+
*/
|
|
271
|
+
static void updateWithReactDefaults(
|
|
272
|
+
@NotNull SentryAndroidOptions options, @Nullable Activity currentActivity) {
|
|
273
|
+
@Nullable SdkVersion sdkVersion = options.getSdkVersion();
|
|
274
|
+
if (sdkVersion == null) {
|
|
275
|
+
sdkVersion = new SdkVersion(RNSentryVersion.ANDROID_SDK_NAME, BuildConfig.VERSION_NAME);
|
|
276
|
+
} else {
|
|
277
|
+
sdkVersion.setName(RNSentryVersion.ANDROID_SDK_NAME);
|
|
278
|
+
}
|
|
279
|
+
sdkVersion.addPackage(
|
|
280
|
+
RNSentryVersion.REACT_NATIVE_SDK_PACKAGE_NAME,
|
|
281
|
+
RNSentryVersion.REACT_NATIVE_SDK_PACKAGE_VERSION);
|
|
282
|
+
|
|
283
|
+
options.setSentryClientName(sdkVersion.getName() + "/" + sdkVersion.getVersion());
|
|
284
|
+
options.setNativeSdkName(RNSentryVersion.NATIVE_SDK_NAME);
|
|
285
|
+
options.setSdkVersion(sdkVersion);
|
|
286
|
+
|
|
287
|
+
// Tracing is only enabled in JS to avoid duplicate navigation spans
|
|
288
|
+
options.setTracesSampleRate(null);
|
|
289
|
+
options.setTracesSampler(null);
|
|
290
|
+
|
|
291
|
+
// React native internally throws a JavascriptException.
|
|
292
|
+
// we want to ignore it on the native side to avoid sending it twice.
|
|
293
|
+
options.addIgnoredExceptionForType(JavascriptException.class);
|
|
294
|
+
|
|
295
|
+
setCurrentActivity(currentActivity);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* This function updates options with changes RNSentry users should not change and so this is
|
|
300
|
+
* applied after the configureOptions callback during manual native initialization.
|
|
301
|
+
*/
|
|
302
|
+
static void updateWithReactFinals(@NotNull SentryAndroidOptions options) {
|
|
303
|
+
BeforeSendCallback userBeforeSend = options.getBeforeSend();
|
|
304
|
+
options.setBeforeSend(
|
|
305
|
+
(event, hint) -> {
|
|
306
|
+
setEventOriginTag(event);
|
|
307
|
+
// Note: In Sentry Android SDK v7, native SDK packages/integrations are already
|
|
308
|
+
// included in the SDK version set during initialization, so no need to copy them here.
|
|
309
|
+
if (userBeforeSend != null) {
|
|
310
|
+
return userBeforeSend.execute(event, hint);
|
|
311
|
+
}
|
|
312
|
+
return event;
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
private static void setCurrentActivity(Activity currentActivity) {
|
|
317
|
+
final CurrentActivityHolder currentActivityHolder = CurrentActivityHolder.getInstance();
|
|
318
|
+
if (currentActivity != null) {
|
|
319
|
+
currentActivityHolder.setActivity(currentActivity);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
private static boolean isReplayEnabled(SentryReplayOptions replayOptions) {
|
|
324
|
+
return replayOptions.getSessionSampleRate() != null
|
|
325
|
+
|| replayOptions.getOnErrorSampleRate() != null;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
private static SentryReplayOptions getReplayOptions(@NotNull ReadableMap rnOptions) {
|
|
329
|
+
final SdkVersion replaySdkVersion =
|
|
330
|
+
new SdkVersion(
|
|
331
|
+
RNSentryVersion.REACT_NATIVE_SDK_NAME,
|
|
332
|
+
RNSentryVersion.REACT_NATIVE_SDK_PACKAGE_VERSION);
|
|
333
|
+
@NotNull
|
|
334
|
+
final SentryReplayOptions androidReplayOptions =
|
|
335
|
+
new SentryReplayOptions(false, replaySdkVersion);
|
|
336
|
+
|
|
337
|
+
if (!(rnOptions.hasKey("replaysSessionSampleRate")
|
|
338
|
+
|| rnOptions.hasKey("replaysOnErrorSampleRate"))) {
|
|
339
|
+
return androidReplayOptions;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
androidReplayOptions.setSessionSampleRate(
|
|
343
|
+
rnOptions.hasKey("replaysSessionSampleRate")
|
|
344
|
+
? rnOptions.getDouble("replaysSessionSampleRate")
|
|
345
|
+
: null);
|
|
346
|
+
androidReplayOptions.setOnErrorSampleRate(
|
|
347
|
+
rnOptions.hasKey("replaysOnErrorSampleRate")
|
|
348
|
+
? rnOptions.getDouble("replaysOnErrorSampleRate")
|
|
349
|
+
: null);
|
|
350
|
+
|
|
351
|
+
if (!rnOptions.hasKey("mobileReplayOptions")) {
|
|
352
|
+
return androidReplayOptions;
|
|
353
|
+
}
|
|
354
|
+
@Nullable final ReadableMap rnMobileReplayOptions = rnOptions.getMap("mobileReplayOptions");
|
|
355
|
+
if (rnMobileReplayOptions == null) {
|
|
356
|
+
return androidReplayOptions;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
androidReplayOptions.setMaskAllText(
|
|
360
|
+
!rnMobileReplayOptions.hasKey("maskAllText")
|
|
361
|
+
|| rnMobileReplayOptions.getBoolean("maskAllText"));
|
|
362
|
+
androidReplayOptions.setMaskAllImages(
|
|
363
|
+
!rnMobileReplayOptions.hasKey("maskAllImages")
|
|
364
|
+
|| rnMobileReplayOptions.getBoolean("maskAllImages"));
|
|
365
|
+
|
|
366
|
+
final boolean redactVectors =
|
|
367
|
+
!rnMobileReplayOptions.hasKey("maskAllVectors")
|
|
368
|
+
|| rnMobileReplayOptions.getBoolean("maskAllVectors");
|
|
369
|
+
if (redactVectors) {
|
|
370
|
+
androidReplayOptions.addMaskViewClass("com.horcrux.svg.SvgView"); // react-native-svg
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
androidReplayOptions.setMaskViewContainerClass(RNSentryReplayMask.class.getName());
|
|
374
|
+
androidReplayOptions.setUnmaskViewContainerClass(RNSentryReplayUnmask.class.getName());
|
|
375
|
+
|
|
376
|
+
return androidReplayOptions;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
private static void setEventOriginTag(SentryEvent event) {
|
|
380
|
+
// We hardcode native-java as only java events are processed by the Android SDK.
|
|
381
|
+
SdkVersion sdk = event.getSdk();
|
|
382
|
+
if (sdk != null) {
|
|
383
|
+
switch (sdk.getName()) {
|
|
384
|
+
case RNSentryVersion.NATIVE_SDK_NAME:
|
|
385
|
+
setEventEnvironmentTag(event, "native");
|
|
386
|
+
break;
|
|
387
|
+
case RNSentryVersion.ANDROID_SDK_NAME:
|
|
388
|
+
setEventEnvironmentTag(event, "java");
|
|
389
|
+
break;
|
|
390
|
+
default:
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
private static void setEventEnvironmentTag(SentryEvent event, String environment) {
|
|
397
|
+
event.setTag("event.origin", "android");
|
|
398
|
+
event.setTag("event.environment", environment);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
private static @Nullable String getURLFromDSN(@Nullable String dsn) {
|
|
402
|
+
if (dsn == null) {
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
URI uri = null;
|
|
406
|
+
try {
|
|
407
|
+
uri = new URI(dsn);
|
|
408
|
+
} catch (URISyntaxException e) {
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
return uri.getScheme() + "://" + uri.getHost();
|
|
412
|
+
}
|
|
413
|
+
}
|
|
@@ -2,7 +2,7 @@ package io.sentry.react;
|
|
|
2
2
|
|
|
3
3
|
class RNSentryVersion {
|
|
4
4
|
static final String REACT_NATIVE_SDK_PACKAGE_NAME = "npm:@sentry/react-native";
|
|
5
|
-
static final String REACT_NATIVE_SDK_PACKAGE_VERSION = "
|
|
5
|
+
static final String REACT_NATIVE_SDK_PACKAGE_VERSION = "8.0.0-beta.0";
|
|
6
6
|
static final String NATIVE_SDK_NAME = "sentry.native.android.react-native";
|
|
7
7
|
static final String ANDROID_SDK_NAME = "sentry.java.android.react-native";
|
|
8
8
|
static final String REACT_NATIVE_SDK_NAME = "sentry.javascript.react-native";
|
|
@@ -66,32 +66,6 @@ export interface MobileReplayOptions {
|
|
|
66
66
|
* @platform ios
|
|
67
67
|
*/
|
|
68
68
|
enableFastViewRendering?: boolean;
|
|
69
|
-
/**
|
|
70
|
-
* Array of view class names to include in subtree traversal during session replay and screenshot capture on iOS.
|
|
71
|
-
*
|
|
72
|
-
* Only views that are instances of these classes (or subclasses) will be traversed.
|
|
73
|
-
* This helps prevent crashes when traversing problematic view hierarchies by allowing you to explicitly include only safe view classes.
|
|
74
|
-
*
|
|
75
|
-
* If both `includedViewClasses` and `excludedViewClasses` are set, `excludedViewClasses` takes precedence:
|
|
76
|
-
* views matching excluded classes won't be traversed even if they match an included class.
|
|
77
|
-
*
|
|
78
|
-
* @default undefined
|
|
79
|
-
* @platform ios
|
|
80
|
-
*/
|
|
81
|
-
includedViewClasses?: string[];
|
|
82
|
-
/**
|
|
83
|
-
* Array of view class names to exclude from subtree traversal during session replay and screenshot capture on iOS.
|
|
84
|
-
*
|
|
85
|
-
* Views of these classes (or subclasses) will be skipped entirely, including all their children.
|
|
86
|
-
* This helps prevent crashes when traversing problematic view hierarchies by allowing you to explicitly exclude problematic view classes.
|
|
87
|
-
*
|
|
88
|
-
* If both `includedViewClasses` and `excludedViewClasses` are set, `excludedViewClasses` takes precedence:
|
|
89
|
-
* views matching excluded classes won't be traversed even if they match an included class.
|
|
90
|
-
*
|
|
91
|
-
* @default undefined
|
|
92
|
-
* @platform ios
|
|
93
|
-
*/
|
|
94
|
-
excludedViewClasses?: string[];
|
|
95
69
|
/**
|
|
96
70
|
* Sets the screenshot strategy used by the Session Replay integration on Android.
|
|
97
71
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mobilereplay.d.ts","sourceRoot":"","sources":["../../../src/js/replay/mobilereplay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAU,MAAM,cAAc,CAAC;AAQ1G,eAAO,MAAM,8BAA8B,iBAAiB,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,WAAW,CAAC;AAExD,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;;;;;;OAUG;IACH,8BAA8B,CAAC,EAAE,OAAO,CAAC;IAEzC;;;;;;;;;;;;OAYG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;;;;;;;;;OAWG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC
|
|
1
|
+
{"version":3,"file":"mobilereplay.d.ts","sourceRoot":"","sources":["../../../src/js/replay/mobilereplay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAU,MAAM,cAAc,CAAC;AAQ1G,eAAO,MAAM,8BAA8B,iBAAiB,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,WAAW,CAAC;AAExD,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;;;;;;OAUG;IACH,8BAA8B,CAAC,EAAE,OAAO,CAAC;IAEzC;;;;;;;;;;;;OAYG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;;;;;;;;;OAWG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC;;;;;;;;;;OAUG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IAExC;;;;;;;;OAQG;IACH,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,KAAK,OAAO,CAAC;CAClE;AAyBD,KAAK,uBAAuB,GAAG,WAAW,GAAG;IAC3C,OAAO,EAAE,mBAAmB,CAAC;IAC7B,WAAW,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,uBAAuB,iBAAiB,mBAAmB,KAAoB,uBA4I3F,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mobilereplay.js","sourceRoot":"","sources":["../../../src/js/replay/mobilereplay.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Client, DynamicSamplingContext, Event, EventHint, Integration, Metric } from '@sentry/core';\nimport { debug } from '@sentry/core';\nimport { isHardCrash } from '../misc';\nimport { hasHooks } from '../utils/clientutils';\nimport { isExpoGo, notMobileOs } from '../utils/environment';\nimport { NATIVE } from '../wrapper';\nimport { enrichXhrBreadcrumbsForMobileReplay } from './xhrUtils';\n\nexport const MOBILE_REPLAY_INTEGRATION_NAME = 'MobileReplay';\n\n/**\n * Screenshot strategy type for Android Session Replay.\n *\n * - `'canvas'`: Canvas-based screenshot strategy. This strategy does **not** support any masking options, it always masks text and images. Use this if your application has strict PII requirements.\n * - `'pixelCopy'`: Pixel copy screenshot strategy (default). Supports all masking options.\n */\nexport type ScreenshotStrategy = 'canvas' | 'pixelCopy';\n\nexport interface MobileReplayOptions {\n /**\n * Mask all text in recordings\n *\n * @default true\n */\n maskAllText?: boolean;\n\n /**\n * Mask all images in recordings\n *\n * @default true\n */\n maskAllImages?: boolean;\n\n /**\n * Mask all vector graphics in recordings\n * Supports `react-native-svg`\n *\n * @default true\n */\n maskAllVectors?: boolean;\n\n /**\n * Enables the up to 5x faster experimental view renderer used by the Session Replay integration on iOS.\n *\n * Enabling this flag will reduce the amount of time it takes to render each frame of the session replay on the main thread, therefore reducing\n * interruptions and visual lag.\n *\n * - Experiment: This is an experimental feature and is therefore disabled by default.\n *\n * @deprecated Use `enableViewRendererV2` instead.\n * @platform ios\n */\n enableExperimentalViewRenderer?: boolean;\n\n /**\n * Enables up to 5x faster new view renderer used by the Session Replay integration on iOS.\n *\n * Enabling this flag will reduce the amount of time it takes to render each frame of the session replay on the main thread, therefore reducing\n * interruptions and visual lag. [Our benchmarks](https://github.com/getsentry/sentry-cocoa/pull/4940) have shown a significant improvement of\n * **up to 4-5x faster rendering** (reducing `~160ms` to `~36ms` per frame) on older devices.\n *\n * - Experiment: In case you are noticing issues with the new view renderer, please report the issue on [GitHub](https://github.com/getsentry/sentry-cocoa).\n * Eventually, we will remove this feature flag and use the new view renderer by default.\n *\n * @default true\n * @platform ios\n */\n enableViewRendererV2?: boolean;\n\n /**\n * Enables up to 5x faster but incomplete view rendering used by the Session Replay integration on iOS.\n *\n * Enabling this flag will reduce the amount of time it takes to render each frame of the session replay on the main thread, therefore reducing\n * interruptions and visual lag.\n *\n * - Note: This flag can only be used together with `enableExperimentalViewRenderer` with up to 20% faster render times.\n * - Experiment: This is an experimental feature and is therefore disabled by default.\n *\n * @default false\n * @platform ios\n */\n enableFastViewRendering?: boolean;\n\n /**\n * Array of view class names to include in subtree traversal during session replay and screenshot capture on iOS.\n *\n * Only views that are instances of these classes (or subclasses) will be traversed.\n * This helps prevent crashes when traversing problematic view hierarchies by allowing you to explicitly include only safe view classes.\n *\n * If both `includedViewClasses` and `excludedViewClasses` are set, `excludedViewClasses` takes precedence:\n * views matching excluded classes won't be traversed even if they match an included class.\n *\n * @default undefined\n * @platform ios\n */\n includedViewClasses?: string[];\n\n /**\n * Array of view class names to exclude from subtree traversal during session replay and screenshot capture on iOS.\n *\n * Views of these classes (or subclasses) will be skipped entirely, including all their children.\n * This helps prevent crashes when traversing problematic view hierarchies by allowing you to explicitly exclude problematic view classes.\n *\n * If both `includedViewClasses` and `excludedViewClasses` are set, `excludedViewClasses` takes precedence:\n * views matching excluded classes won't be traversed even if they match an included class.\n *\n * @default undefined\n * @platform ios\n */\n excludedViewClasses?: string[];\n\n /**\n * Sets the screenshot strategy used by the Session Replay integration on Android.\n *\n * If your application has strict PII requirements we recommend using `'canvas'`.\n * This strategy does **not** support any masking options, it always masks text and images.\n *\n * - Experiment: In case you are noticing issues with the canvas screenshot strategy, please report the issue on [GitHub](https://github.com/getsentry/sentry-java).\n *\n * @default 'pixelCopy'\n * @platform android\n */\n screenshotStrategy?: ScreenshotStrategy;\n\n /**\n * Callback to determine if a replay should be captured for a specific error.\n * When this callback returns `false`, no replay will be captured for the error.\n * This callback is only called when an error occurs and `replaysOnErrorSampleRate` is set.\n *\n * @param event The error event\n * @param hint Additional event information\n * @returns `false` to skip capturing a replay for this error, `true` or `undefined` to proceed with sampling\n */\n beforeErrorSampling?: (event: Event, hint: EventHint) => boolean;\n}\n\nconst defaultOptions: MobileReplayOptions = {\n maskAllText: true,\n maskAllImages: true,\n maskAllVectors: true,\n enableExperimentalViewRenderer: false,\n enableViewRendererV2: true,\n enableFastViewRendering: false,\n screenshotStrategy: 'pixelCopy',\n};\n\nfunction mergeOptions(initOptions: Partial<MobileReplayOptions>): MobileReplayOptions {\n const merged = {\n ...defaultOptions,\n ...initOptions,\n };\n\n if (initOptions.enableViewRendererV2 === undefined && initOptions.enableExperimentalViewRenderer !== undefined) {\n merged.enableViewRendererV2 = initOptions.enableExperimentalViewRenderer;\n }\n\n return merged;\n}\n\ntype MobileReplayIntegration = Integration & {\n options: MobileReplayOptions;\n getReplayId: () => string | null;\n};\n\n/**\n * The Mobile Replay Integration, let's you adjust the default mobile replay options.\n * To be passed to `Sentry.init` with `replaysOnErrorSampleRate` or `replaysSessionSampleRate`.\n *\n * ```javascript\n * Sentry.init({\n * replaysOnErrorSampleRate: 1.0,\n * replaysSessionSampleRate: 1.0,\n * integrations: [mobileReplayIntegration({\n * // Adjust the default options\n * })],\n * });\n * ```\n *\n * @experimental\n */\nexport const mobileReplayIntegration = (initOptions: MobileReplayOptions = defaultOptions): MobileReplayIntegration => {\n if (isExpoGo()) {\n debug.warn(\n `[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} is not supported in Expo Go. Use EAS Build or \\`expo prebuild\\` to enable it.`,\n );\n }\n if (notMobileOs()) {\n debug.warn(`[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} is not supported on this platform.`);\n }\n\n if (isExpoGo() || notMobileOs()) {\n return mobileReplayIntegrationNoop();\n }\n\n const options = mergeOptions(initOptions);\n\n // Cache the replay ID in JavaScript to avoid excessive bridge calls\n // This will be updated when we know the replay ID changes (e.g., after captureReplay)\n let cachedReplayId: string | null = null;\n\n function updateCachedReplayId(replayId: string | null): void {\n cachedReplayId = replayId;\n }\n\n function getCachedReplayId(): string | null {\n if (cachedReplayId !== null) {\n return cachedReplayId;\n }\n const nativeReplayId = NATIVE.getCurrentReplayId();\n if (nativeReplayId) {\n cachedReplayId = nativeReplayId;\n }\n return nativeReplayId;\n }\n\n async function processEvent(event: Event, hint: EventHint): Promise<Event> {\n const hasException = event.exception?.values && event.exception.values.length > 0;\n if (!hasException) {\n // Event is not an error, will not capture replay\n return event;\n }\n\n // Check if beforeErrorSampling callback filters out this error\n if (initOptions.beforeErrorSampling) {\n try {\n if (initOptions.beforeErrorSampling(event, hint) === false) {\n debug.log(\n `[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} not sent; beforeErrorSampling conditions not met for event ${event.event_id}.`,\n );\n return event;\n }\n } catch (error) {\n debug.error(\n `[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} beforeErrorSampling callback threw an error, proceeding with replay capture`,\n error,\n );\n // Continue with replay capture if callback throws\n }\n }\n\n const replayId = await NATIVE.captureReplay(isHardCrash(event));\n if (replayId) {\n updateCachedReplayId(replayId);\n debug.log(\n `[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} Captured recording replay ${replayId} for event ${event.event_id}.`,\n );\n // Add replay_id to error event contexts to link replays to events/traces\n event.contexts = event.contexts || {};\n event.contexts.replay = {\n ...event.contexts.replay,\n replay_id: replayId,\n };\n } else {\n // Check if there's an ongoing recording and update cache if found\n const recordingReplayId = NATIVE.getCurrentReplayId();\n if (recordingReplayId) {\n updateCachedReplayId(recordingReplayId);\n debug.log(\n `[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} assign already recording replay ${recordingReplayId} for event ${event.event_id}.`,\n );\n // Add replay_id to error event contexts to link replays to events/traces\n event.contexts = event.contexts || {};\n event.contexts.replay = {\n ...event.contexts.replay,\n replay_id: recordingReplayId,\n };\n } else {\n updateCachedReplayId(null);\n debug.log(`[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} not sampled for event ${event.event_id}.`);\n }\n }\n\n return event;\n }\n\n function setup(client: Client): void {\n if (!hasHooks(client)) {\n return;\n }\n\n // Initialize the cached replay ID on setup\n cachedReplayId = NATIVE.getCurrentReplayId();\n\n client.on('createDsc', (dsc: DynamicSamplingContext) => {\n if (dsc.replay_id) {\n return;\n }\n\n // Use cached replay ID to avoid bridge calls\n const currentReplayId = getCachedReplayId();\n if (currentReplayId) {\n dsc.replay_id = currentReplayId;\n }\n });\n\n client.on('processMetric', (metric: Metric) => {\n // Add replay_id to metric attributes to link metrics to replays\n const currentReplayId = getCachedReplayId();\n if (currentReplayId) {\n metric.attributes = metric.attributes || {};\n metric.attributes.replay_id = currentReplayId;\n }\n });\n\n client.on('beforeAddBreadcrumb', enrichXhrBreadcrumbsForMobileReplay);\n }\n\n function getReplayId(): string | null {\n return getCachedReplayId();\n }\n\n // TODO: When adding manual API, ensure overlap with the web replay so users can use the same API interchangeably\n // https://github.com/getsentry/sentry-javascript/blob/develop/packages/replay-internal/src/integration.ts#L45\n return {\n name: MOBILE_REPLAY_INTEGRATION_NAME,\n setup,\n processEvent,\n options: options,\n getReplayId: getReplayId,\n };\n};\n\nconst mobileReplayIntegrationNoop = (): MobileReplayIntegration => {\n return {\n name: MOBILE_REPLAY_INTEGRATION_NAME,\n options: defaultOptions,\n getReplayId: () => null, // Mock implementation for noop version\n };\n};\n"]}
|
|
1
|
+
{"version":3,"file":"mobilereplay.js","sourceRoot":"","sources":["../../../src/js/replay/mobilereplay.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Client, DynamicSamplingContext, Event, EventHint, Integration, Metric } from '@sentry/core';\nimport { debug } from '@sentry/core';\nimport { isHardCrash } from '../misc';\nimport { hasHooks } from '../utils/clientutils';\nimport { isExpoGo, notMobileOs } from '../utils/environment';\nimport { NATIVE } from '../wrapper';\nimport { enrichXhrBreadcrumbsForMobileReplay } from './xhrUtils';\n\nexport const MOBILE_REPLAY_INTEGRATION_NAME = 'MobileReplay';\n\n/**\n * Screenshot strategy type for Android Session Replay.\n *\n * - `'canvas'`: Canvas-based screenshot strategy. This strategy does **not** support any masking options, it always masks text and images. Use this if your application has strict PII requirements.\n * - `'pixelCopy'`: Pixel copy screenshot strategy (default). Supports all masking options.\n */\nexport type ScreenshotStrategy = 'canvas' | 'pixelCopy';\n\nexport interface MobileReplayOptions {\n /**\n * Mask all text in recordings\n *\n * @default true\n */\n maskAllText?: boolean;\n\n /**\n * Mask all images in recordings\n *\n * @default true\n */\n maskAllImages?: boolean;\n\n /**\n * Mask all vector graphics in recordings\n * Supports `react-native-svg`\n *\n * @default true\n */\n maskAllVectors?: boolean;\n\n /**\n * Enables the up to 5x faster experimental view renderer used by the Session Replay integration on iOS.\n *\n * Enabling this flag will reduce the amount of time it takes to render each frame of the session replay on the main thread, therefore reducing\n * interruptions and visual lag.\n *\n * - Experiment: This is an experimental feature and is therefore disabled by default.\n *\n * @deprecated Use `enableViewRendererV2` instead.\n * @platform ios\n */\n enableExperimentalViewRenderer?: boolean;\n\n /**\n * Enables up to 5x faster new view renderer used by the Session Replay integration on iOS.\n *\n * Enabling this flag will reduce the amount of time it takes to render each frame of the session replay on the main thread, therefore reducing\n * interruptions and visual lag. [Our benchmarks](https://github.com/getsentry/sentry-cocoa/pull/4940) have shown a significant improvement of\n * **up to 4-5x faster rendering** (reducing `~160ms` to `~36ms` per frame) on older devices.\n *\n * - Experiment: In case you are noticing issues with the new view renderer, please report the issue on [GitHub](https://github.com/getsentry/sentry-cocoa).\n * Eventually, we will remove this feature flag and use the new view renderer by default.\n *\n * @default true\n * @platform ios\n */\n enableViewRendererV2?: boolean;\n\n /**\n * Enables up to 5x faster but incomplete view rendering used by the Session Replay integration on iOS.\n *\n * Enabling this flag will reduce the amount of time it takes to render each frame of the session replay on the main thread, therefore reducing\n * interruptions and visual lag.\n *\n * - Note: This flag can only be used together with `enableExperimentalViewRenderer` with up to 20% faster render times.\n * - Experiment: This is an experimental feature and is therefore disabled by default.\n *\n * @default false\n * @platform ios\n */\n enableFastViewRendering?: boolean;\n\n /**\n * Sets the screenshot strategy used by the Session Replay integration on Android.\n *\n * If your application has strict PII requirements we recommend using `'canvas'`.\n * This strategy does **not** support any masking options, it always masks text and images.\n *\n * - Experiment: In case you are noticing issues with the canvas screenshot strategy, please report the issue on [GitHub](https://github.com/getsentry/sentry-java).\n *\n * @default 'pixelCopy'\n * @platform android\n */\n screenshotStrategy?: ScreenshotStrategy;\n\n /**\n * Callback to determine if a replay should be captured for a specific error.\n * When this callback returns `false`, no replay will be captured for the error.\n * This callback is only called when an error occurs and `replaysOnErrorSampleRate` is set.\n *\n * @param event The error event\n * @param hint Additional event information\n * @returns `false` to skip capturing a replay for this error, `true` or `undefined` to proceed with sampling\n */\n beforeErrorSampling?: (event: Event, hint: EventHint) => boolean;\n}\n\nconst defaultOptions: MobileReplayOptions = {\n maskAllText: true,\n maskAllImages: true,\n maskAllVectors: true,\n enableExperimentalViewRenderer: false,\n enableViewRendererV2: true,\n enableFastViewRendering: false,\n screenshotStrategy: 'pixelCopy',\n};\n\nfunction mergeOptions(initOptions: Partial<MobileReplayOptions>): MobileReplayOptions {\n const merged = {\n ...defaultOptions,\n ...initOptions,\n };\n\n if (initOptions.enableViewRendererV2 === undefined && initOptions.enableExperimentalViewRenderer !== undefined) {\n merged.enableViewRendererV2 = initOptions.enableExperimentalViewRenderer;\n }\n\n return merged;\n}\n\ntype MobileReplayIntegration = Integration & {\n options: MobileReplayOptions;\n getReplayId: () => string | null;\n};\n\n/**\n * The Mobile Replay Integration, let's you adjust the default mobile replay options.\n * To be passed to `Sentry.init` with `replaysOnErrorSampleRate` or `replaysSessionSampleRate`.\n *\n * ```javascript\n * Sentry.init({\n * replaysOnErrorSampleRate: 1.0,\n * replaysSessionSampleRate: 1.0,\n * integrations: [mobileReplayIntegration({\n * // Adjust the default options\n * })],\n * });\n * ```\n *\n * @experimental\n */\nexport const mobileReplayIntegration = (initOptions: MobileReplayOptions = defaultOptions): MobileReplayIntegration => {\n if (isExpoGo()) {\n debug.warn(\n `[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} is not supported in Expo Go. Use EAS Build or \\`expo prebuild\\` to enable it.`,\n );\n }\n if (notMobileOs()) {\n debug.warn(`[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} is not supported on this platform.`);\n }\n\n if (isExpoGo() || notMobileOs()) {\n return mobileReplayIntegrationNoop();\n }\n\n const options = mergeOptions(initOptions);\n\n // Cache the replay ID in JavaScript to avoid excessive bridge calls\n // This will be updated when we know the replay ID changes (e.g., after captureReplay)\n let cachedReplayId: string | null = null;\n\n function updateCachedReplayId(replayId: string | null): void {\n cachedReplayId = replayId;\n }\n\n function getCachedReplayId(): string | null {\n if (cachedReplayId !== null) {\n return cachedReplayId;\n }\n const nativeReplayId = NATIVE.getCurrentReplayId();\n if (nativeReplayId) {\n cachedReplayId = nativeReplayId;\n }\n return nativeReplayId;\n }\n\n async function processEvent(event: Event, hint: EventHint): Promise<Event> {\n const hasException = event.exception?.values && event.exception.values.length > 0;\n if (!hasException) {\n // Event is not an error, will not capture replay\n return event;\n }\n\n // Check if beforeErrorSampling callback filters out this error\n if (initOptions.beforeErrorSampling) {\n try {\n if (initOptions.beforeErrorSampling(event, hint) === false) {\n debug.log(\n `[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} not sent; beforeErrorSampling conditions not met for event ${event.event_id}.`,\n );\n return event;\n }\n } catch (error) {\n debug.error(\n `[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} beforeErrorSampling callback threw an error, proceeding with replay capture`,\n error,\n );\n // Continue with replay capture if callback throws\n }\n }\n\n const replayId = await NATIVE.captureReplay(isHardCrash(event));\n if (replayId) {\n updateCachedReplayId(replayId);\n debug.log(\n `[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} Captured recording replay ${replayId} for event ${event.event_id}.`,\n );\n // Add replay_id to error event contexts to link replays to events/traces\n event.contexts = event.contexts || {};\n event.contexts.replay = {\n ...event.contexts.replay,\n replay_id: replayId,\n };\n } else {\n // Check if there's an ongoing recording and update cache if found\n const recordingReplayId = NATIVE.getCurrentReplayId();\n if (recordingReplayId) {\n updateCachedReplayId(recordingReplayId);\n debug.log(\n `[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} assign already recording replay ${recordingReplayId} for event ${event.event_id}.`,\n );\n // Add replay_id to error event contexts to link replays to events/traces\n event.contexts = event.contexts || {};\n event.contexts.replay = {\n ...event.contexts.replay,\n replay_id: recordingReplayId,\n };\n } else {\n updateCachedReplayId(null);\n debug.log(`[Sentry] ${MOBILE_REPLAY_INTEGRATION_NAME} not sampled for event ${event.event_id}.`);\n }\n }\n\n return event;\n }\n\n function setup(client: Client): void {\n if (!hasHooks(client)) {\n return;\n }\n\n // Initialize the cached replay ID on setup\n cachedReplayId = NATIVE.getCurrentReplayId();\n\n client.on('createDsc', (dsc: DynamicSamplingContext) => {\n if (dsc.replay_id) {\n return;\n }\n\n // Use cached replay ID to avoid bridge calls\n const currentReplayId = getCachedReplayId();\n if (currentReplayId) {\n dsc.replay_id = currentReplayId;\n }\n });\n\n client.on('processMetric', (metric: Metric) => {\n // Add replay_id to metric attributes to link metrics to replays\n const currentReplayId = getCachedReplayId();\n if (currentReplayId) {\n metric.attributes = metric.attributes || {};\n metric.attributes.replay_id = currentReplayId;\n }\n });\n\n client.on('beforeAddBreadcrumb', enrichXhrBreadcrumbsForMobileReplay);\n }\n\n function getReplayId(): string | null {\n return getCachedReplayId();\n }\n\n // TODO: When adding manual API, ensure overlap with the web replay so users can use the same API interchangeably\n // https://github.com/getsentry/sentry-javascript/blob/develop/packages/replay-internal/src/integration.ts#L45\n return {\n name: MOBILE_REPLAY_INTEGRATION_NAME,\n setup,\n processEvent,\n options: options,\n getReplayId: getReplayId,\n };\n};\n\nconst mobileReplayIntegrationNoop = (): MobileReplayIntegration => {\n return {\n name: MOBILE_REPLAY_INTEGRATION_NAME,\n options: defaultOptions,\n getReplayId: () => null, // Mock implementation for noop version\n };\n};\n"]}
|
package/dist/js/sdk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/js/sdk.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA2C,KAAK,EAAE,MAAM,cAAc,CAAC;AAanF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,KAAK,EAA4B,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/js/sdk.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA2C,KAAK,EAAE,MAAM,cAAc,CAAC;AAanF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,KAAK,EAA4B,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AAgCzG;;GAEG;AACH,wBAAgB,IAAI,CAAC,aAAa,EAAE,kBAAkB,GAAG,IAAI,CAyH5D;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpD,aAAa,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EACrC,OAAO,CAAC,EAAE,yBAAyB,GAClC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAsBxB;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED;;;GAGG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,CAe9C;AAED;;GAEG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAU3C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAUzE;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAE9D"}
|