Skip to content

Commit c84c37f

Browse files
ahmedAlaaInstabugabdelhamid-f-nassera7medevkholood-ea
authored
feat: capture client error in the network interceptor (#1257)
* feat/support-capture-client-error-in-xhr-requests --------- Co-authored-by: Abdelhamid Nasser <[email protected]> Co-authored-by: Ahmed Elrefaey <[email protected]> Co-authored-by: kholood <[email protected]>
1 parent 2f49a3e commit c84c37f

File tree

6 files changed

+99
-5
lines changed

6 files changed

+99
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Added
66

77
- Add support for Expo Router navigation tracking ([#1270](https://github.com/Instabug/Instabug-React-Native/pull/1270)).
8+
- Enhance the network interceptor to capture more client error messages ([#1257](https://github.com/Instabug/Instabug-React-Native/pull/1257)).
89

910
### Fixed
1011

examples/default/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"@react-navigation/native": "^6.1.6",
1717
"@react-navigation/native-stack": "^6.9.12",
1818
"graphql": "^16.8.1",
19+
"axios": "^1.7.4",
1920
"graphql-request": "^6.1.0",
2021
"instabug-reactnative": "link:../..",
2122
"instabug-reactnative-ndk": "github:https://github.com/Instabug/Instabug-React-Native-NDK",

examples/default/src/screens/apm/NetworkScreen.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { useQuery } from 'react-query';
77
import { HStack, VStack } from 'native-base';
88
import { gql, request } from 'graphql-request';
99
import { CustomButton } from '../../components/CustomButton';
10+
import axios from 'axios';
1011

1112
export const NetworkScreen: React.FC = () => {
1213
const [endpointUrl, setEndpointUrl] = useState('');
@@ -45,6 +46,32 @@ export const NetworkScreen: React.FC = () => {
4546
}
4647
}
4748

49+
async function sendRequestToUrlUsingAxios() {
50+
let urlToSend = '';
51+
52+
if (endpointUrl.trim() !== '') {
53+
urlToSend = endpointUrl;
54+
console.log('Sending request to: ', endpointUrl);
55+
} else {
56+
// Use json placeholder URL as a default if endpointUrl is empty
57+
console.log('sending request to default json placeholder');
58+
urlToSend = defaultRequestUrl;
59+
}
60+
61+
try {
62+
// Perform the request using the urlToSend
63+
const response = await axios.get(urlToSend);
64+
// Format the JSON response for better logging
65+
const formattedData = JSON.stringify(response.data, null, 2);
66+
67+
// Log the formatted response
68+
console.log('Response:', formattedData);
69+
} catch (error) {
70+
// Handle errors appropriately
71+
console.error('Error:', error);
72+
}
73+
}
74+
4875
const fetchGraphQlData = async () => {
4976
const document = gql`
5077
query {
@@ -75,6 +102,11 @@ export const NetworkScreen: React.FC = () => {
75102
value={endpointUrl}
76103
/>
77104
<CustomButton onPress={sendRequestToUrl} title="Send Request To Url" />
105+
<CustomButton
106+
onPress={sendRequestToUrlUsingAxios}
107+
title="Send Request To Url Using Axios"
108+
/>
109+
78110
<CustomButton onPress={() => refetch} title="Reload GraphQL" />
79111
<View>
80112
{isLoading && <Text>Loading...</Text>}

examples/default/yarn.lock

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3239,11 +3239,25 @@ async@^3.2.2:
32393239
resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
32403240
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
32413241

3242+
asynckit@^0.4.0:
3243+
version "0.4.0"
3244+
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
3245+
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
3246+
32423247
at-least-node@^1.0.0:
32433248
version "1.0.0"
32443249
resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
32453250
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
32463251

3252+
axios@^1.7.4:
3253+
version "1.7.4"
3254+
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.4.tgz#4c8ded1b43683c8dd362973c393f3ede24052aa2"
3255+
integrity sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==
3256+
dependencies:
3257+
follow-redirects "^1.15.6"
3258+
form-data "^4.0.0"
3259+
proxy-from-env "^1.1.0"
3260+
32473261
babel-core@^7.0.0-bridge.0:
32483262
version "7.0.0-bridge.0"
32493263
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece"
@@ -3729,6 +3743,13 @@ colorette@^1.0.7:
37293743
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40"
37303744
integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==
37313745

3746+
combined-stream@^1.0.8:
3747+
version "1.0.8"
3748+
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
3749+
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
3750+
dependencies:
3751+
delayed-stream "~1.0.0"
3752+
37323753
command-exists@^1.2.8:
37333754
version "1.2.9"
37343755
resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69"
@@ -3941,6 +3962,11 @@ define-data-property@^1.1.1:
39413962
gopd "^1.0.1"
39423963
has-property-descriptors "^1.0.0"
39433964

3965+
delayed-stream@~1.0.0:
3966+
version "1.0.0"
3967+
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
3968+
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
3969+
39443970
denodeify@^1.2.1:
39453971
version "1.2.1"
39463972
resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631"
@@ -4329,6 +4355,20 @@ flow-parser@^0.206.0:
43294355
resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.206.0.tgz#f4f794f8026535278393308e01ea72f31000bfef"
43304356
integrity sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==
43314357

4358+
follow-redirects@^1.15.6:
4359+
version "1.15.6"
4360+
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
4361+
integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
4362+
4363+
form-data@^4.0.0:
4364+
version "4.0.0"
4365+
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
4366+
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
4367+
dependencies:
4368+
asynckit "^0.4.0"
4369+
combined-stream "^1.0.8"
4370+
mime-types "^2.1.12"
4371+
43324372
43334373
version "0.5.2"
43344374
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
@@ -4650,7 +4690,8 @@ inline-style-prefixer@^6.0.1:
46504690
resolved "https://codeload.github.com/Instabug/Instabug-React-Native-NDK/tar.gz/3b0bac281253133852d32f52aa50cc805dd0b570"
46514691

46524692
"instabug-reactnative@link:../..":
4653-
version "13.0.5"
4693+
version "0.0.0"
4694+
uid ""
46544695

46554696
intl-messageformat@^10.1.0:
46564697
version "10.5.0"
@@ -6105,7 +6146,7 @@ [email protected], "mime-db@>= 1.43.0 < 2":
61056146
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
61066147
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
61076148

6108-
mime-types@^2.1.27, mime-types@~2.1.34:
6149+
mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.34:
61096150
version "2.1.35"
61106151
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
61116152
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
@@ -6664,6 +6705,11 @@ proper-lockfile@^3.0.2:
66646705
retry "^0.12.0"
66656706
signal-exit "^3.0.2"
66666707

6708+
proxy-from-env@^1.1.0:
6709+
version "1.1.0"
6710+
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
6711+
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
6712+
66676713
pseudomap@^1.0.2:
66686714
version "1.0.2"
66696715
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"

src/utils/XhrNetworkInterceptor.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ export default {
7272
originalXHROpen = XMLHttpRequest.prototype.open;
7373
originalXHRSend = XMLHttpRequest.prototype.send;
7474
originalXHRSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
75-
75+
// An error code that signifies an issue with the RN client.
76+
const clientErrorCode = 9876;
7677
XMLHttpRequest.prototype.open = function (method, url, ...args) {
7778
_reset();
7879
network.url = url;
@@ -145,14 +146,24 @@ export default {
145146

146147
// @ts-ignore
147148
if (this._hasError) {
148-
cloneNetwork.errorCode = 0;
149+
cloneNetwork.errorCode = clientErrorCode;
149150
cloneNetwork.errorDomain = 'ClientError';
150151

151152
// @ts-ignore
152153
const _response = this._response;
153154
cloneNetwork.requestBody =
154155
typeof _response === 'string' ? _response : JSON.stringify(_response);
155156
cloneNetwork.responseBody = '';
157+
158+
// Detect a more descriptive error message.
159+
if (typeof _response === 'string' && _response.length > 0) {
160+
cloneNetwork.errorDomain = _response;
161+
}
162+
163+
// @ts-ignore
164+
} else if (this._timedOut) {
165+
cloneNetwork.errorCode = clientErrorCode;
166+
cloneNetwork.errorDomain = 'TimeOutError';
156167
}
157168

158169
if (this.response) {
@@ -162,6 +173,9 @@ export default {
162173
} else if (['text', '', 'json'].includes(this.responseType)) {
163174
cloneNetwork.responseBody = JSON.stringify(this.response);
164175
}
176+
} else {
177+
cloneNetwork.responseBody = '';
178+
cloneNetwork.contentType = 'text/plain';
165179
}
166180

167181
cloneNetwork.requestBodySize = cloneNetwork.requestBody.length;

test/utils/XhrNetworkInterceptor.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ describe('Network Interceptor', () => {
235235
expect(callback).toBeCalledWith(
236236
expect.objectContaining({
237237
errorDomain: 'ClientError',
238-
errorCode: 0,
238+
errorCode: 9876,
239239
responseBody: '',
240240
}),
241241
);

0 commit comments

Comments
 (0)