Skip to content

Commit 44282b5

Browse files
committed
Merge branch 'v8' into antonis/capture-app-start-errors-v8
# Conflicts: # CHANGELOG.md
2 parents f4584c5 + 5fc24f0 commit 44282b5

10 files changed

Lines changed: 358 additions & 19 deletions

File tree

.github/workflows/native-tests.yml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,36 @@ jobs:
4848
working-directory: packages/core/RNSentryCocoaTester
4949
run: pod install
5050

51+
- name: List Available Simulators
52+
run: xcrun simctl list devices available iPhone
53+
5154
- name: Run iOS Tests
5255
working-directory: packages/core/RNSentryCocoaTester
5356
env:
5457
SCHEME: RNSentryCocoaTester
5558
CONFIGURATION: Release
56-
DESTINATION: 'platform=iOS Simulator,OS=latest,name=iPhone 16'
5759
run: |
60+
# Find first available iPhone simulator from latest iOS runtime
61+
DEVICE_ID=$(xcrun simctl list devices available iPhone -j | jq -r '
62+
.devices |
63+
to_entries |
64+
map(select(.key | startswith("com.apple.CoreSimulator.SimRuntime.iOS-"))) |
65+
sort_by(.key) |
66+
reverse |
67+
.[0].value[] |
68+
select(.isAvailable == true) |
69+
.udid
70+
' | head -1)
71+
if [ -z "$DEVICE_ID" ]; then
72+
echo "No iPhone simulators available"
73+
exit 1
74+
fi
75+
echo "Using simulator: $DEVICE_ID"
76+
5877
env NSUnbufferedIO=YES \
5978
xcodebuild -workspace *.xcworkspace \
6079
-scheme $SCHEME -configuration $CONFIGURATION \
61-
-destination "$DESTINATION" \
80+
-destination "id=$DEVICE_ID" \
6281
-quiet \
6382
test
6483

CHANGELOG.md

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

1111
### Features
1212

13+
- Add experimental `sentry-span-attributes` prop to attach custom attributes to user interaction spans ([#5569](https://github.com/getsentry/sentry-react-native/pull/5569))
14+
```tsx
15+
<Pressable
16+
sentry-label="checkout"
17+
sentry-span-attributes={{
18+
'user.type': 'premium',
19+
'cart.value': 150
20+
}}
21+
onPress={handleCheckout}>
22+
<Text>Checkout</Text>
23+
</Pressable>
24+
```
25+
1326
- Capture App Start errors and crashes by initializing Sentry from `sentry.options.json` ([#4472](https://github.com/getsentry/sentry-react-native/pull/4472))
1427

1528
Create `sentry.options.json` in the React Native project root and set options the same as you currently have in `Sentry.init` in JS.
@@ -85,6 +98,9 @@
8598
- Bump CLI from v2.58.4 to v3.1.0 ([#5523](https://github.com/getsentry/sentry-react-native/pull/5523), [#5471](https://github.com/getsentry/sentry-react-native/pull/5471), [#5514](https://github.com/getsentry/sentry-react-native/pull/5514), [#5502](https://github.com/getsentry/sentry-react-native/pull/5502))
8699
- [changelog](https://github.com/getsentry/sentry-cli/blob/master/CHANGELOG.md#310)
87100
- [diff](https://github.com/getsentry/sentry-cli/compare/2.58.4...3.1.0)
101+
- Bump Bundler Plugins from v4.7.0 to v4.8.0 ([#5581](https://github.com/getsentry/sentry-react-native/pull/5581))
102+
- [changelog](https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/main/CHANGELOG.md#480)
103+
- [diff](https://github.com/getsentry/sentry-javascript-bundler-plugins/compare/4.7.0...4.8.0)
88104

89105
## 7.10.0
90106

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
"react-native": ">=0.65.0"
6969
},
7070
"dependencies": {
71-
"@sentry/babel-plugin-component-annotate": "4.7.0",
71+
"@sentry/babel-plugin-component-annotate": "4.8.0",
7272
"@sentry/browser": "10.36.0",
7373
"@sentry/cli": "3.1.0",
7474
"@sentry/core": "10.36.0",

packages/core/src/js/touchevents.tsx

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { SeverityLevel } from '@sentry/core';
1+
import type { SeverityLevel, SpanAttributeValue } from '@sentry/core';
22
import { addBreadcrumb, debug, dropUndefinedKeys, getClient, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
33
import * as React from 'react';
44
import type { GestureResponderEvent } from 'react-native';
@@ -39,6 +39,13 @@ export type TouchEventBoundaryProps = {
3939
* Label Name used to identify the touched element.
4040
*/
4141
labelName?: string;
42+
/**
43+
* Custom attributes to add to user interaction spans.
44+
* Accepts an object with string keys and values that are strings, numbers, booleans, or arrays.
45+
*
46+
* @experimental This API is experimental and may change in future releases.
47+
*/
48+
spanAttributes?: Record<string, SpanAttributeValue>;
4249
};
4350

4451
const touchEventStyles = StyleSheet.create({
@@ -52,6 +59,7 @@ const DEFAULT_BREADCRUMB_TYPE = 'user';
5259
const DEFAULT_MAX_COMPONENT_TREE_SIZE = 20;
5360

5461
const SENTRY_LABEL_PROP_KEY = 'sentry-label';
62+
const SENTRY_SPAN_ATTRIBUTES_PROP_KEY = 'sentry-span-attributes';
5563
const SENTRY_COMPONENT_PROP_KEY = 'data-sentry-component';
5664
const SENTRY_ELEMENT_PROP_KEY = 'data-sentry-element';
5765
const SENTRY_FILE_PROP_KEY = 'data-sentry-source-file';
@@ -204,6 +212,28 @@ class TouchEventBoundary extends React.Component<TouchEventBoundaryProps> {
204212
});
205213
if (span) {
206214
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_ORIGIN_AUTO_INTERACTION);
215+
216+
// Apply custom attributes from sentry-span-attributes prop
217+
// Traverse the component tree to find custom attributes
218+
let instForAttributes: ElementInstance | undefined = e._targetInst;
219+
let customAttributes: Record<string, SpanAttributeValue> | undefined;
220+
221+
while (instForAttributes) {
222+
if (instForAttributes.elementType?.displayName === TouchEventBoundary.displayName) {
223+
break;
224+
}
225+
226+
customAttributes = getSpanAttributes(instForAttributes);
227+
if (customAttributes && Object.keys(customAttributes).length > 0) {
228+
break;
229+
}
230+
231+
instForAttributes = instForAttributes.return;
232+
}
233+
234+
if (customAttributes && Object.keys(customAttributes).length > 0) {
235+
span.setAttributes(customAttributes);
236+
}
207237
}
208238
}
209239

@@ -291,6 +321,26 @@ function getLabelValue(props: Record<string, unknown>, labelKey: string | undefi
291321
: undefined;
292322
}
293323

324+
function getSpanAttributes(currentInst: ElementInstance): Record<string, SpanAttributeValue> | undefined {
325+
if (!currentInst.memoizedProps) {
326+
return undefined;
327+
}
328+
329+
const props = currentInst.memoizedProps;
330+
const attributes = props[SENTRY_SPAN_ATTRIBUTES_PROP_KEY];
331+
332+
// Validate that it's an object (not null, not array)
333+
if (
334+
typeof attributes === 'object' &&
335+
attributes !== null &&
336+
!Array.isArray(attributes)
337+
) {
338+
return attributes as Record<string, SpanAttributeValue>;
339+
}
340+
341+
return undefined;
342+
}
343+
294344
/**
295345
* Convenience Higher-Order-Component for TouchEventBoundary
296346
* @param WrappedComponent any React Component

0 commit comments

Comments
 (0)