Skip to content

Commit 6c91dce

Browse files
fix(spotlight): Stop tracing Sidecar network request in JS (#3559)
1 parent 4e41557 commit 6c91dce

File tree

7 files changed

+107
-36
lines changed

7 files changed

+107
-36
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
- Prevent pod install crash when visionos is not present ([#3548](https://github.com/getsentry/sentry-react-native/pull/3548))
2525
- Fetch Organization slug from `@sentry/react-native/expo` config when uploading artifacts ([#3557](https://github.com/getsentry/sentry-react-native/pull/3557))
2626
- Remove 404 Http Client Errors reports for Metro Dev Server Requests ([#3553](https://github.com/getsentry/sentry-react-native/pull/3553))
27+
- Stop tracing Spotlight Sidecar network request in JS ([#3559](https://github.com/getsentry/sentry-react-native/pull/3559))
2728

2829
## 5.17.0
2930

jest.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module.exports = {
22
collectCoverage: true,
33
preset: 'react-native',
4-
setupFilesAfterEnv: ['jest-extended/all', '<rootDir>/test/mockConsole.ts', '<rootDir>/test/mockFetch.ts'],
4+
setupFilesAfterEnv: ['jest-extended/all', '<rootDir>/test/mockConsole.ts'],
55
globals: {
66
__DEV__: true,
77
'ts-jest': {

package.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"devDependencies": {
7979
"@babel/core": "^7.23.5",
8080
"@expo/metro-config": "0.16.0",
81+
"@mswjs/interceptors": "^0.25.15",
8182
"@sentry-internal/eslint-config-sdk": "7.81.1",
8283
"@sentry-internal/eslint-plugin-sdk": "7.81.1",
8384
"@sentry-internal/typescript": "7.80.0",
@@ -87,6 +88,7 @@
8788
"@types/react": "^18.2.14",
8889
"@types/uglify-js": "^3.17.2",
8990
"@types/uuid": "^9.0.4",
91+
"@types/xmlhttprequest": "^1.8.2",
9092
"babel-jest": "^29.6.2",
9193
"downlevel-dts": "^0.11.0",
9294
"eslint": "^7.6.0",
@@ -96,7 +98,6 @@
9698
"expo-module-scripts": "^3.1.0",
9799
"jest": "^29.6.2",
98100
"jest-environment-jsdom": "^29.6.2",
99-
"jest-fetch-mock": "^3.0.3",
100101
"jest-extended": "^4.0.2",
101102
"madge": "^6.1.0",
102103
"metro": "0.76",
@@ -108,7 +109,8 @@
108109
"ts-jest": "^29.1.1",
109110
"typescript": "4.9.5",
110111
"uglify-js": "^3.17.4",
111-
"uuid": "^9.0.1"
112+
"uuid": "^9.0.1",
113+
"xmlhttprequest": "^1.8.0"
112114
},
113115
"rnpm": {
114116
"commands": {},

src/js/integrations/spotlight.ts

+26-13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { logger, serializeEnvelope } from '@sentry/utils';
33

44
import { makeUtf8TextEncoder } from '../transports/TextEncoder';
55
import { ReactNativeLibraries } from '../utils/rnlibraries';
6+
import { createStealthXhr, XHR_READYSTATE_DONE } from '../utils/xhr';
67

78
type SpotlightReactNativeIntegrationOptions = {
89
/**
@@ -56,19 +57,31 @@ function sendEnvelopesToSidecar(client: Client, sidecarUrl: string): void {
5657

5758
spotlightEnvelope[1] = envelopeItems as Envelope[1];
5859

59-
fetch(sidecarUrl, {
60-
method: 'POST',
61-
body: serializeEnvelope(spotlightEnvelope, makeUtf8TextEncoder()),
62-
headers: {
63-
'Content-Type': 'application/x-sentry-envelope',
64-
},
65-
mode: 'cors',
66-
}).catch(err => {
67-
logger.error(
68-
"[Spotlight] Sentry SDK can't connect to Spotlight is it running? See https://spotlightjs.com to download it.",
69-
err,
70-
);
71-
});
60+
const xhr = createStealthXhr();
61+
if (!xhr) {
62+
logger.error('[Spotlight] Sentry SDK can not create XHR object');
63+
return;
64+
}
65+
66+
xhr.open('POST', sidecarUrl, true);
67+
xhr.setRequestHeader('Content-Type', 'application/x-sentry-envelope');
68+
69+
xhr.onreadystatechange = function () {
70+
if (xhr.readyState === XHR_READYSTATE_DONE) {
71+
const status = xhr.status;
72+
if (status === 0 || (status >= 200 && status < 400)) {
73+
// The request has been completed successfully
74+
} else {
75+
// Handle the error
76+
logger.error(
77+
"[Spotlight] Sentry SDK can't connect to Spotlight is it running? See https://spotlightjs.com to download it.",
78+
new Error(xhr.statusText),
79+
);
80+
}
81+
}
82+
};
83+
84+
xhr.send(serializeEnvelope(spotlightEnvelope, makeUtf8TextEncoder()));
7285
});
7386
}
7487

test/integrations/spotlight.test.ts

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
1+
import type { HttpRequestEventMap } from '@mswjs/interceptors';
2+
import { XMLHttpRequestInterceptor } from '@mswjs/interceptors/XMLHttpRequest';
13
import type { Envelope, Hub } from '@sentry/types';
2-
import fetchMock from 'jest-fetch-mock';
4+
import { XMLHttpRequest } from 'xmlhttprequest';
35

46
import { Spotlight } from '../../src/js/integrations/spotlight';
57

8+
globalThis.XMLHttpRequest = XMLHttpRequest;
9+
const requestListener = jest.fn<void, HttpRequestEventMap['request']>();
10+
const interceptor = new XMLHttpRequestInterceptor();
11+
interceptor.on('request', requestListener);
12+
613
describe('spotlight', () => {
14+
beforeAll(async () => {
15+
interceptor.apply();
16+
});
17+
18+
afterEach(() => {
19+
jest.resetAllMocks();
20+
});
21+
722
it('should not change the original envelope', () => {
823
const mockHub = createMockHub();
924

@@ -24,8 +39,7 @@ describe('spotlight', () => {
2439
expect(originalEnvelopeReference).toEqual(createMockEnvelope());
2540
});
2641

27-
it('should remove image attachments from spotlight envelope', () => {
28-
fetchMock.mockOnce();
42+
it('should remove image attachments from spotlight envelope', async () => {
2943
const mockHub = createMockHub();
3044

3145
const spotlight = Spotlight();
@@ -40,8 +54,9 @@ describe('spotlight', () => {
4054

4155
spotlightBeforeEnvelope?.(createMockEnvelope());
4256

57+
const [{ request }] = requestListener.mock.calls[0];
4358
expect(spotlightBeforeEnvelope).toBeDefined();
44-
expect(fetchMock.mock.lastCall?.[1]?.body?.toString().includes('image/png')).toBe(false);
59+
expect((await request.text()).includes('image/png')).toBe(false);
4560
});
4661
});
4762

test/mockFetch.ts

-2
This file was deleted.

yarn.lock

+56-14
Original file line numberDiff line numberDiff line change
@@ -3258,6 +3258,18 @@
32583258
"@jridgewell/resolve-uri" "^3.1.0"
32593259
"@jridgewell/sourcemap-codec" "^1.4.14"
32603260

3261+
"@mswjs/interceptors@^0.25.15":
3262+
version "0.25.15"
3263+
resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.25.15.tgz#183c5761d3c20e07ac49a206df39a5b6df9e8242"
3264+
integrity sha512-s4jdyxmq1eeftfDXJ7MUiK/jlvYaU8Sr75+42hHCVBrYez0k51RHbMitKIKdmsF92Q6gwhp8Sm1MmvdA9llpcg==
3265+
dependencies:
3266+
"@open-draft/deferred-promise" "^2.2.0"
3267+
"@open-draft/logger" "^0.3.0"
3268+
"@open-draft/until" "^2.0.0"
3269+
is-node-process "^1.2.0"
3270+
outvariant "^1.2.1"
3271+
strict-event-emitter "^0.5.1"
3272+
32613273
"@nicolo-ribaudo/[email protected]":
32623274
version "2.1.8-no-fsevents.3"
32633275
resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b"
@@ -3300,6 +3312,24 @@
33003312
mkdirp "^1.0.4"
33013313
rimraf "^3.0.2"
33023314

3315+
"@open-draft/deferred-promise@^2.2.0":
3316+
version "2.2.0"
3317+
resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd"
3318+
integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==
3319+
3320+
"@open-draft/logger@^0.3.0":
3321+
version "0.3.0"
3322+
resolved "https://registry.yarnpkg.com/@open-draft/logger/-/logger-0.3.0.tgz#2b3ab1242b360aa0adb28b85f5d7da1c133a0954"
3323+
integrity sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==
3324+
dependencies:
3325+
is-node-process "^1.2.0"
3326+
outvariant "^1.4.0"
3327+
3328+
"@open-draft/until@^2.0.0":
3329+
version "2.1.0"
3330+
resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-2.1.0.tgz#0acf32f470af2ceaf47f095cdecd40d68666efda"
3331+
integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==
3332+
33033333
"@pkgr/utils@^2.3.1":
33043334
version "2.4.2"
33053335
resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc"
@@ -4254,6 +4284,11 @@
42544284
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.4.tgz#e884a59338da907bda8d2ed03e01c5c49d036f1c"
42554285
integrity sha512-zAuJWQflfx6dYJM62vna+Sn5aeSWhh3OB+wfUEACNcqUSc0AGc5JKl+ycL1vrH7frGTXhJchYjE1Hak8L819dA==
42564286

4287+
"@types/xmlhttprequest@^1.8.2":
4288+
version "1.8.2"
4289+
resolved "https://registry.yarnpkg.com/@types/xmlhttprequest/-/xmlhttprequest-1.8.2.tgz#0061fccb7a55b349d23f2381660ba2b124b8d197"
4290+
integrity sha512-PfIzIb4tiva9bL40mOmeAe23T3QkJS2AfZ+vqgJWEJ2bxn5KUnDkikizu6TVaZRzQeThOeAn/Zh4PMkfFwEMtg==
4291+
42574292
"@types/yargs-parser@*":
42584293
version "15.0.0"
42594294
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d"
@@ -5908,7 +5943,7 @@ cosmiconfig@^5.0.5, cosmiconfig@^5.1.0:
59085943
js-yaml "^3.13.1"
59095944
parse-json "^4.0.0"
59105945

5911-
cross-fetch@^3.0.4, cross-fetch@^3.1.5:
5946+
cross-fetch@^3.1.5:
59125947
version "3.1.8"
59135948
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82"
59145949
integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==
@@ -8542,6 +8577,11 @@ is-negative-zero@^2.0.2:
85428577
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
85438578
integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==
85448579

8580+
is-node-process@^1.2.0:
8581+
version "1.2.0"
8582+
resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134"
8583+
integrity sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==
8584+
85458585
is-number-object@^1.0.4:
85468586
version "1.0.7"
85478587
resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc"
@@ -9020,14 +9060,6 @@ jest-extended@^4.0.2:
90209060
jest-diff "^29.0.0"
90219061
jest-get-type "^29.0.0"
90229062

9023-
jest-fetch-mock@^3.0.3:
9024-
version "3.0.3"
9025-
resolved "https://registry.yarnpkg.com/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz#31749c456ae27b8919d69824f1c2bd85fe0a1f3b"
9026-
integrity sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==
9027-
dependencies:
9028-
cross-fetch "^3.0.4"
9029-
promise-polyfill "^8.1.3"
9030-
90319063
jest-get-type@^29.0.0, jest-get-type@^29.6.3:
90329064
version "29.6.3"
90339065
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1"
@@ -11141,6 +11173,11 @@ osenv@^0.1.5:
1114111173
os-homedir "^1.0.0"
1114211174
os-tmpdir "^1.0.0"
1114311175

11176+
outvariant@^1.2.1, outvariant@^1.4.0:
11177+
version "1.4.2"
11178+
resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.2.tgz#f54f19240eeb7f15b28263d5147405752d8e2066"
11179+
integrity sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==
11180+
1114411181
p-finally@^1.0.0:
1114511182
version "1.0.0"
1114611183
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
@@ -11570,11 +11607,6 @@ promise-inflight@^1.0.1:
1157011607
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
1157111608
integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==
1157211609

11573-
promise-polyfill@^8.1.3:
11574-
version "8.3.0"
11575-
resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.3.0.tgz#9284810268138d103807b11f4e23d5e945a4db63"
11576-
integrity sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==
11577-
1157811610
promise@^7.1.1:
1157911611
version "7.3.1"
1158011612
resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf"
@@ -12732,6 +12764,11 @@ stream-to-array@^2.3.0:
1273212764
dependencies:
1273312765
any-promise "^1.1.0"
1273412766

12767+
strict-event-emitter@^0.5.1:
12768+
version "0.5.1"
12769+
resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93"
12770+
integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==
12771+
1273512772
string-length@^4.0.1:
1273612773
version "4.0.2"
1273712774
resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"
@@ -14069,6 +14106,11 @@ xmlchars@^2.2.0:
1406914106
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
1407014107
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
1407114108

14109+
xmlhttprequest@^1.8.0:
14110+
version "1.8.0"
14111+
resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
14112+
integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==
14113+
1407214114
xtend@~4.0.1:
1407314115
version "4.0.2"
1407414116
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"

0 commit comments

Comments
 (0)