Skip to content

Commit be1aafb

Browse files
committed
Merge branch 'main' into v8
# Conflicts: # CHANGELOG.md # packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java
2 parents 2e93e80 + 6c36ba5 commit be1aafb

17 files changed

Lines changed: 511 additions & 82 deletions

File tree

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,19 @@
1010

1111
### Features
1212

13+
- Extends the experimental support of UI profiling to iOS ([#5611](https://github.com/getsentry/sentry-react-native/pull/5611))
14+
```js
15+
Sentry.init({
16+
_experiments: {
17+
profilingOptions: {
18+
profileSessionSampleRate: 1.0,
19+
lifecycle: 'trace', // or 'manual'
20+
startOnAppStart: true,
21+
},
22+
},
23+
});
24+
```
25+
- Note that the `androidProfilingOptions` key is now deprecated, and `profilingOptions` should be used instead
1326
- Add performance tracking for Expo Router route prefetching ([#5606](https://github.com/getsentry/sentry-react-native/pull/5606))
1427
- New `wrapExpoRouter` utility to instrument manual `prefetch()` calls with performance spans
1528
- New `enablePrefetchTracking` option for `reactNavigationIntegration` to automatically track PRELOAD actions
@@ -31,6 +44,10 @@
3144
});
3245
```
3346

47+
### Fixes
48+
49+
- Fix `SENTRY_ALLOW_FAILURE` environment variable not being respected in Xcode build scripts ([#5616](https://github.com/getsentry/sentry-react-native/pull/5616))
50+
3451
### Dependencies
3552

3653
- Bump Cocoa SDK from v9.1.0 to v9.3.0 ([#5515](https://github.com/getsentry/sentry-react-native/pull/5515))

dev-packages/e2e-tests/patch-scripts/rn.patch.app.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ Sentry.init({
2727
release: '${SENTRY_RELEASE}',
2828
dist: '${SENTRY_DIST}',
2929
dsn: 'https://1df17bd4e543fdb31351dee1768bb679@o447951.ingest.sentry.io/5428561',
30-
_experiments: {
31-
replaysOnErrorSampleRate: LaunchArguments.value().replaysOnErrorSampleRate,
32-
},
30+
replaysOnErrorSampleRate: LaunchArguments.value().replaysOnErrorSampleRate,
3331
integrations: [
3432
Sentry.mobileReplayIntegration(),
3533
Sentry.feedbackIntegration({

packages/core/android/src/main/java/io/sentry/react/RNSentryStart.java

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -205,65 +205,61 @@ private static void configureAndroidProfiling(
205205
}
206206

207207
@Nullable final ReadableMap experiments = rnOptions.getMap("_experiments");
208-
if (experiments == null || !experiments.hasKey("androidProfilingOptions")) {
208+
if (experiments == null || !experiments.hasKey("profilingOptions")) {
209209
return;
210210
}
211211

212-
@Nullable
213-
final ReadableMap androidProfilingOptions = experiments.getMap("androidProfilingOptions");
214-
if (androidProfilingOptions == null) {
212+
@Nullable final ReadableMap profilingOptions = experiments.getMap("profilingOptions");
213+
if (profilingOptions == null) {
215214
return;
216215
}
217216

218217
// Set profile session sample rate
219-
if (androidProfilingOptions.hasKey("profileSessionSampleRate")) {
220-
if (androidProfilingOptions.getType("profileSessionSampleRate") == ReadableType.Number) {
218+
if (profilingOptions.hasKey("profileSessionSampleRate")) {
219+
if (profilingOptions.getType("profileSessionSampleRate") == ReadableType.Number) {
221220
final double profileSessionSampleRate =
222-
androidProfilingOptions.getDouble("profileSessionSampleRate");
221+
profilingOptions.getDouble("profileSessionSampleRate");
223222
options.setProfileSessionSampleRate(profileSessionSampleRate);
224223
logger.log(
225224
SentryLevel.INFO,
226225
String.format(
227-
"Android UI Profiling profileSessionSampleRate set to: %.2f",
228-
profileSessionSampleRate));
226+
"UI Profiling profileSessionSampleRate set to: %.2f", profileSessionSampleRate));
229227
} else {
230228
logger.log(
231229
SentryLevel.WARNING,
232-
"Android UI Profiling profileSessionSampleRate must be a number, ignoring invalid"
233-
+ " value");
230+
"UI Profiling profileSessionSampleRate must be a number, ignoring invalid value");
234231
}
235232
}
236233

237234
// Set profiling lifecycle mode
238-
if (androidProfilingOptions.hasKey("lifecycle")) {
239-
if (androidProfilingOptions.getType("lifecycle") == ReadableType.String) {
240-
final String lifecycle = androidProfilingOptions.getString("lifecycle");
235+
if (profilingOptions.hasKey("lifecycle")) {
236+
if (profilingOptions.getType("lifecycle") == ReadableType.String) {
237+
final String lifecycle = profilingOptions.getString("lifecycle");
241238
if ("manual".equalsIgnoreCase(lifecycle)) {
242239
options.setProfileLifecycle(ProfileLifecycle.MANUAL);
243-
logger.log(SentryLevel.INFO, "Android UI Profile Lifecycle set to MANUAL");
240+
logger.log(SentryLevel.INFO, "UI Profile Lifecycle set to MANUAL");
244241
} else if ("trace".equalsIgnoreCase(lifecycle)) {
245242
options.setProfileLifecycle(ProfileLifecycle.TRACE);
246-
logger.log(SentryLevel.INFO, "Android UI Profile Lifecycle set to TRACE");
243+
logger.log(SentryLevel.INFO, "UI Profile Lifecycle set to TRACE");
247244
}
248245
} else {
249246
logger.log(
250-
SentryLevel.WARNING,
251-
"Android UI Profiling lifecycle must be a string, ignoring invalid value");
247+
SentryLevel.WARNING, "UI Profiling lifecycle must be a string, ignoring invalid value");
252248
}
253249
}
254250

255251
// Set start on app start
256-
if (androidProfilingOptions.hasKey("startOnAppStart")) {
257-
if (androidProfilingOptions.getType("startOnAppStart") == ReadableType.Boolean) {
258-
final boolean startOnAppStart = androidProfilingOptions.getBoolean("startOnAppStart");
252+
if (profilingOptions.hasKey("startOnAppStart")) {
253+
if (profilingOptions.getType("startOnAppStart") == ReadableType.Boolean) {
254+
final boolean startOnAppStart = profilingOptions.getBoolean("startOnAppStart");
259255
options.setStartProfilerOnAppStart(startOnAppStart);
260256
logger.log(
261257
SentryLevel.INFO,
262-
String.format("Android UI Profiling startOnAppStart set to %b", startOnAppStart));
258+
String.format("UI Profiling startOnAppStart set to %b", startOnAppStart));
263259
} else {
264260
logger.log(
265261
SentryLevel.WARNING,
266-
"Android UI Profiling startOnAppStart must be a boolean, ignoring invalid value");
262+
"UI Profiling startOnAppStart must be a boolean, ignoring invalid value");
267263
}
268264
}
269265
}

packages/core/ios/RNSentryExperimentalOptions.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ NS_ASSUME_NONNULL_BEGIN
3737
+ (void)setEnableSessionReplayInUnreliableEnvironment:(BOOL)enabled
3838
sentryOptions:(SentryOptions *)sentryOptions;
3939

40+
/**
41+
* Configures iOS UI profiling options on SentryOptions
42+
* @param profilingOptions Dictionary containing profiling configuration
43+
* @param sentryOptions The SentryOptions instance to configure
44+
*/
45+
+ (void)configureProfilingWithOptions:(NSDictionary *)profilingOptions
46+
sentryOptions:(SentryOptions *)sentryOptions;
47+
4048
@end
4149

4250
NS_ASSUME_NONNULL_END

packages/core/ios/RNSentryExperimentalOptions.m

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#import "RNSentryExperimentalOptions.h"
2+
#import <Sentry/SentryProfilingConditionals.h>
23
@import Sentry;
34

45
@implementation RNSentryExperimentalOptions
@@ -36,4 +37,45 @@ + (void)setEnableSessionReplayInUnreliableEnvironment:(BOOL)enabled
3637
sentryOptions.experimental.enableSessionReplayInUnreliableEnvironment = enabled;
3738
}
3839

40+
+ (void)configureProfilingWithOptions:(NSDictionary *)profilingOptions
41+
sentryOptions:(SentryOptions *)sentryOptions
42+
{
43+
#if SENTRY_TARGET_PROFILING_SUPPORTED
44+
if (sentryOptions == nil || profilingOptions == nil) {
45+
return;
46+
}
47+
48+
sentryOptions.configureProfiling = ^(SentryProfileOptions *_Nonnull profiling) {
49+
// Set session sample rate
50+
id profileSessionSampleRate = profilingOptions[@"profileSessionSampleRate"];
51+
if (profileSessionSampleRate != nil &&
52+
[profileSessionSampleRate isKindOfClass:[NSNumber class]]) {
53+
profiling.sessionSampleRate = [profileSessionSampleRate floatValue];
54+
NSLog(@"Sentry: UI Profiling sessionSampleRate set to: %.2f",
55+
profiling.sessionSampleRate);
56+
}
57+
58+
// Set lifecycle mode
59+
NSString *lifecycle = profilingOptions[@"lifecycle"];
60+
if ([lifecycle isKindOfClass:[NSString class]]) {
61+
if ([lifecycle caseInsensitiveCompare:@"manual"] == NSOrderedSame) {
62+
profiling.lifecycle = SentryProfileLifecycleManual;
63+
NSLog(@"Sentry: UI Profiling Lifecycle set to MANUAL");
64+
} else if ([lifecycle caseInsensitiveCompare:@"trace"] == NSOrderedSame) {
65+
profiling.lifecycle = SentryProfileLifecycleTrace;
66+
NSLog(@"Sentry: UI Profiling Lifecycle set to TRACE");
67+
}
68+
}
69+
70+
// Set profile app starts
71+
id startOnAppStart = profilingOptions[@"startOnAppStart"];
72+
if (startOnAppStart != nil && [startOnAppStart isKindOfClass:[NSNumber class]]) {
73+
profiling.profileAppStarts = [startOnAppStart boolValue];
74+
NSLog(@"Sentry: UI Profiling profileAppStarts set to %@",
75+
profiling.profileAppStarts ? @"YES" : @"NO");
76+
}
77+
};
78+
#endif
79+
}
80+
3981
@end

packages/core/ios/SentrySDKWrapper.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ + (SentryOptions *)createOptionsWithDictionary:(NSDictionary *)options
106106
[experiments[@"enableUnhandledCPPExceptionsV2"] boolValue];
107107
[RNSentryExperimentalOptions setEnableUnhandledCPPExceptionsV2:enableUnhandledCPPExceptions
108108
sentryOptions:sentryOptions];
109+
110+
// Configure iOS UI Profiling
111+
NSDictionary *profilingOptions = experiments[@"profilingOptions"];
112+
if (profilingOptions != nil && [profilingOptions isKindOfClass:[NSDictionary class]]) {
113+
[RNSentryExperimentalOptions configureProfilingWithOptions:profilingOptions
114+
sentryOptions:sentryOptions];
115+
}
109116
}
110117

111118
if (isSessionReplayEnabled) {

packages/core/scripts/sentry-xcode-debug-files.sh

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,17 @@ else
7070
# 'warning:' triggers a warning in Xcode, 'error:' triggers an error
7171
set +x +e # disable printing commands otherwise we might print `error:` by accident and allow continuing on error
7272
SENTRY_UPLOAD_COMMAND_OUTPUT=$(/bin/sh -c "\"$LOCAL_NODE_BINARY\" $UPLOAD_DEBUG_FILES" 2>&1)
73-
if [ $? -eq 0 ]; then
73+
UPLOAD_EXIT_CODE=$?
74+
if [ $UPLOAD_EXIT_CODE -eq 0 ]; then
7475
echo "$SENTRY_UPLOAD_COMMAND_OUTPUT" | awk '{print "output: sentry-cli - " $0}'
7576
else
76-
echo "error: sentry-cli - To disable native debug files auto upload, set SENTRY_DISABLE_AUTO_UPLOAD=true in your environment variables. Or to allow failing upload, set SENTRY_ALLOW_FAILURE=true"
77-
echo "error: sentry-cli - $SENTRY_UPLOAD_COMMAND_OUTPUT"
77+
if [ "$SENTRY_ALLOW_FAILURE" == true ]; then
78+
echo "warning: sentry-cli - Debug files upload failed, but continuing build because SENTRY_ALLOW_FAILURE=true"
79+
echo "warning: sentry-cli - $SENTRY_UPLOAD_COMMAND_OUTPUT"
80+
else
81+
echo "error: sentry-cli - To disable native debug files auto upload, set SENTRY_DISABLE_AUTO_UPLOAD=true in your environment variables. Or to allow failing upload, set SENTRY_ALLOW_FAILURE=true"
82+
echo "error: sentry-cli - $SENTRY_UPLOAD_COMMAND_OUTPUT"
83+
fi
7884
fi
7985
set -x -e # re-enable
8086
fi

packages/core/scripts/sentry-xcode.sh

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,14 @@ if [ "$SENTRY_DISABLE_AUTO_UPLOAD" != true ]; then
5656
if [ $? -eq 0 ]; then
5757
echo "$SENTRY_XCODE_COMMAND_OUTPUT" | awk '{print "output: sentry-cli - " $0}'
5858
else
59-
echo "error: sentry-cli - To disable source maps auto upload, set SENTRY_DISABLE_AUTO_UPLOAD=true in your environment variables. Or to allow failing upload, set SENTRY_ALLOW_FAILURE=true"
60-
echo "error: sentry-cli - $SENTRY_XCODE_COMMAND_OUTPUT"
61-
exitCode=1
59+
if [ "$SENTRY_ALLOW_FAILURE" == true ]; then
60+
echo "warning: sentry-cli - Source maps upload failed, but continuing build because SENTRY_ALLOW_FAILURE=true"
61+
echo "warning: sentry-cli - $SENTRY_XCODE_COMMAND_OUTPUT"
62+
else
63+
echo "error: sentry-cli - To disable source maps auto upload, set SENTRY_DISABLE_AUTO_UPLOAD=true in your environment variables. Or to allow failing upload, set SENTRY_ALLOW_FAILURE=true"
64+
echo "error: sentry-cli - $SENTRY_XCODE_COMMAND_OUTPUT"
65+
exitCode=1
66+
fi
6267
fi
6368
set -x -e # re-enable
6469
else

packages/core/src/js/client.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,8 @@ export class ReactNativeClient extends Client<ReactNativeClientOptions> {
224224
'options' in this._integrations[MOBILE_REPLAY_INTEGRATION_NAME]
225225
? (this._integrations[MOBILE_REPLAY_INTEGRATION_NAME] as ReturnType<typeof mobileReplayIntegration>).options
226226
: undefined,
227-
androidProfilingOptions: this._options._experiments?.androidProfilingOptions,
227+
profilingOptions:
228+
this._options._experiments?.profilingOptions ?? this._options._experiments?.androidProfilingOptions,
228229
})
229230
.then(
230231
(result: boolean) => {

packages/core/src/js/options.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -294,16 +294,26 @@ export interface BaseReactNativeOptions {
294294
*/
295295
enableUnhandledCPPExceptionsV2?: boolean;
296296

297+
/**
298+
* Configuration options for UI profiling.
299+
* It supports two modes: `manual` and `trace`.
300+
* - In `trace` mode, the profiler runs based on active sampled spans.
301+
* - In `manual` mode, profiling is controlled via start/stop API calls.
302+
*
303+
* @experimental
304+
*/
305+
profilingOptions?: ProfilingOptions;
306+
297307
/**
298308
* Configuration options for Android UI profiling.
299-
* UI profiling supports two modes: `manual` and `trace`.
309+
* It supports two modes: `manual` and `trace`.
300310
* - In `trace` mode, the profiler runs based on active sampled spans.
301311
* - In `manual` mode, profiling is controlled via start/stop API calls.
302312
*
303313
* @experimental
304-
* @platform android
314+
* @deprecated Use `profilingOptions` instead. This option will be removed in the next major version.
305315
*/
306-
androidProfilingOptions?: AndroidProfilingOptions;
316+
androidProfilingOptions?: ProfilingOptions;
307317
};
308318

309319
/**
@@ -342,19 +352,18 @@ export interface BaseReactNativeOptions {
342352
export type SentryReplayQuality = 'low' | 'medium' | 'high';
343353

344354
/**
345-
* Android UI profiling lifecycle modes.
355+
* UI profiling lifecycle modes.
346356
* - `trace`: Profiler runs based on active sampled spans
347357
* - `manual`: Profiler is controlled manually via start/stop API calls
348358
*/
349-
export type AndroidProfilingLifecycle = 'trace' | 'manual';
359+
export type ProfilingLifecycle = 'trace' | 'manual';
350360

351361
/**
352-
* Configuration options for Android UI profiling.
362+
* Configuration options for UI profiling.
353363
*
354364
* @experimental
355-
* @platform android
356365
*/
357-
export interface AndroidProfilingOptions {
366+
export interface ProfilingOptions {
358367
/**
359368
* Sample rate for profiling sessions.
360369
* This is evaluated once per session and determines if profiling should be enabled for that session.
@@ -369,9 +378,9 @@ export interface AndroidProfilingOptions {
369378
* - `trace`: Profiler runs while there is at least one active sampled span
370379
* - `manual`: Profiler is controlled manually via Sentry.profiler.startProfiler/stopProfiler
371380
*
372-
* @default 'trace'
381+
* @default 'manual'
373382
*/
374-
lifecycle?: AndroidProfilingLifecycle;
383+
lifecycle?: ProfilingLifecycle;
375384

376385
/**
377386
* Enable profiling on app start.

0 commit comments

Comments
 (0)