@multiplayer-app/session-recorder-react-native 1.0.1-beta.4 → 1.0.1-beta.6
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/android/build.gradle +1 -1
- package/android/src/main/AndroidManifest.xml +2 -2
- package/android/src/main/java/com/{multiplayer/sessionrecordernative → sessionrecordernative}/SessionRecorderNativeConfig.kt +1 -1
- package/android/src/main/java/com/{multiplayer/sessionrecordernative → sessionrecordernative}/SessionRecorderNativeModule.kt +9 -9
- package/android/src/main/java/com/{multiplayer/sessionrecordernative → sessionrecordernative}/SessionRecorderNativePackage.kt +2 -2
- package/android/src/main/java/com/{multiplayer/sessionrecordernative → sessionrecordernative}/model/TargetInfo.kt +1 -1
- package/android/src/main/java/com/{multiplayer/sessionrecordernative → sessionrecordernative}/util/ViewUtils.kt +2 -2
- package/lib/module/SessionRecorderNativeSpec.js +5 -0
- package/lib/module/SessionRecorderNativeSpec.js.map +1 -0
- package/lib/module/components/SessionRecorderWidget/ErrorBanner.js.map +1 -1
- package/lib/module/components/SessionRecorderWidget/ModalHeader.js.map +1 -1
- package/lib/module/components/SessionRecorderWidget/SessionRecorderWidget.js.map +1 -1
- package/lib/module/components/SessionRecorderWidget/icons.js.map +1 -1
- package/lib/module/components/SessionRecorderWidget/styles.js.map +1 -1
- package/lib/module/config/constants.js.map +1 -1
- package/lib/module/config/defaults.js.map +1 -1
- package/lib/module/config/masking.js.map +1 -1
- package/lib/module/config/session-recorder.js.map +1 -1
- package/lib/module/config/validators.js.map +1 -1
- package/lib/module/config/widget.js.map +1 -1
- package/lib/module/context/SessionRecorderStore.js.map +1 -1
- package/lib/module/context/useSessionRecorderStore.js.map +1 -1
- package/lib/module/context/useStoreSelector.js.map +1 -1
- package/lib/module/native/SessionRecorderNative.js +16 -11
- package/lib/module/native/SessionRecorderNative.js.map +1 -1
- package/lib/module/native/index.js.map +1 -1
- package/lib/module/otel/helpers.js +1 -1
- package/lib/module/otel/helpers.js.map +1 -1
- package/lib/module/otel/index.js.map +1 -1
- package/lib/module/otel/instrumentations/index.js.map +1 -1
- package/lib/module/patch/xhr.js.map +1 -1
- package/lib/module/recorder/eventExporter.js.map +1 -1
- package/lib/module/recorder/gestureRecorder.js.map +1 -1
- package/lib/module/recorder/index.js.map +1 -1
- package/lib/module/recorder/navigationTracker.js.map +1 -1
- package/lib/module/recorder/screenRecorder.js.map +1 -1
- package/lib/module/services/api.service.js.map +1 -1
- package/lib/module/services/network.service.js.map +1 -1
- package/lib/module/services/screenMaskingService.js +1 -1
- package/lib/module/services/screenMaskingService.js.map +1 -1
- package/lib/module/services/storage.service.js.map +1 -1
- package/lib/module/session-recorder.js.map +1 -1
- package/lib/module/types/index.js.map +1 -1
- package/lib/module/types/session-recorder.js.map +1 -1
- package/lib/module/utils/app-metadata.js +2 -2
- package/lib/module/utils/constants.optional.js.map +1 -1
- package/lib/module/utils/createStore.js.map +1 -1
- package/lib/module/utils/logger.js +0 -8
- package/lib/module/utils/logger.js.map +1 -1
- package/lib/module/utils/platform.js +1 -1
- package/lib/module/utils/platform.js.map +1 -1
- package/lib/module/utils/rrweb-events.js.map +1 -1
- package/lib/module/utils/session.js.map +1 -1
- package/lib/module/utils/shallowEqual.js.map +1 -1
- package/lib/module/utils/time.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/typescript/src/SessionRecorderNativeSpec.d.ts +42 -0
- package/lib/typescript/src/SessionRecorderNativeSpec.d.ts.map +1 -0
- package/lib/typescript/src/components/ScreenRecorderView/index.d.ts +1 -1
- package/lib/typescript/src/components/SessionRecorderWidget/ErrorBanner.d.ts.map +1 -1
- package/lib/typescript/src/components/SessionRecorderWidget/ModalHeader.d.ts.map +1 -1
- package/lib/typescript/src/components/SessionRecorderWidget/SessionRecorderWidget.d.ts.map +1 -1
- package/lib/typescript/src/components/SessionRecorderWidget/icons.d.ts.map +1 -1
- package/lib/typescript/src/components/SessionRecorderWidget/index.d.ts +1 -1
- package/lib/typescript/src/components/SessionRecorderWidget/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/index.d.ts.map +1 -1
- package/lib/typescript/src/config/constants.d.ts.map +1 -1
- package/lib/typescript/src/config/defaults.d.ts.map +1 -1
- package/lib/typescript/src/config/index.d.ts.map +1 -1
- package/lib/typescript/src/config/masking.d.ts.map +1 -1
- package/lib/typescript/src/config/session-recorder.d.ts.map +1 -1
- package/lib/typescript/src/config/validators.d.ts.map +1 -1
- package/lib/typescript/src/config/widget.d.ts +1 -1
- package/lib/typescript/src/config/widget.d.ts.map +1 -1
- package/lib/typescript/src/context/SessionRecorderStore.d.ts.map +1 -1
- package/lib/typescript/src/context/useSessionRecorderStore.d.ts +3 -3
- package/lib/typescript/src/context/useSessionRecorderStore.d.ts.map +1 -1
- package/lib/typescript/src/context/useStoreSelector.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/native/SessionRecorderNative.d.ts +3 -54
- package/lib/typescript/src/native/SessionRecorderNative.d.ts.map +1 -1
- package/lib/typescript/src/native/index.d.ts +1 -1
- package/lib/typescript/src/native/index.d.ts.map +1 -1
- package/lib/typescript/src/otel/helpers.d.ts.map +1 -1
- package/lib/typescript/src/otel/index.d.ts.map +1 -1
- package/lib/typescript/src/otel/instrumentations/index.d.ts.map +1 -1
- package/lib/typescript/src/patch/index.d.ts.map +1 -1
- package/lib/typescript/src/patch/xhr.d.ts.map +1 -1
- package/lib/typescript/src/recorder/eventExporter.d.ts.map +1 -1
- package/lib/typescript/src/recorder/gestureRecorder.d.ts.map +1 -1
- package/lib/typescript/src/recorder/index.d.ts.map +1 -1
- package/lib/typescript/src/recorder/navigationTracker.d.ts.map +1 -1
- package/lib/typescript/src/recorder/screenRecorder.d.ts.map +1 -1
- package/lib/typescript/src/services/api.service.d.ts.map +1 -1
- package/lib/typescript/src/services/network.service.d.ts.map +1 -1
- package/lib/typescript/src/services/screenMaskingService.d.ts +1 -1
- package/lib/typescript/src/services/screenMaskingService.d.ts.map +1 -1
- package/lib/typescript/src/services/storage.service.d.ts.map +1 -1
- package/lib/typescript/src/session-recorder.d.ts.map +1 -1
- package/lib/typescript/src/types/configs.d.ts.map +1 -1
- package/lib/typescript/src/types/index.d.ts.map +1 -1
- package/lib/typescript/src/types/session-recorder.d.ts +4 -4
- package/lib/typescript/src/types/session-recorder.d.ts.map +1 -1
- package/lib/typescript/src/types/session.d.ts.map +1 -1
- package/lib/typescript/src/utils/app-metadata.d.ts.map +1 -1
- package/lib/typescript/src/utils/constants.optional.d.ts.map +1 -1
- package/lib/typescript/src/utils/constants.optional.expo.d.ts.map +1 -1
- package/lib/typescript/src/utils/createStore.d.ts.map +1 -1
- package/lib/typescript/src/utils/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/logger.d.ts +1 -1
- package/lib/typescript/src/utils/logger.d.ts.map +1 -1
- package/lib/typescript/src/utils/platform.d.ts.map +1 -1
- package/lib/typescript/src/utils/request-utils.d.ts.map +1 -1
- package/lib/typescript/src/utils/rrweb-events.d.ts.map +1 -1
- package/lib/typescript/src/utils/session.d.ts.map +1 -1
- package/lib/typescript/src/utils/shallowEqual.d.ts.map +1 -1
- package/lib/typescript/src/utils/time.d.ts.map +1 -1
- package/lib/typescript/src/utils/type-utils.d.ts.map +1 -1
- package/lib/typescript/src/version.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/SessionRecorderNativeSpec.ts +53 -0
- package/src/components/ScreenRecorderView/index.ts +1 -1
- package/src/components/SessionRecorderWidget/ErrorBanner.tsx +14 -14
- package/src/components/SessionRecorderWidget/ModalHeader.tsx +11 -9
- package/src/components/SessionRecorderWidget/SessionRecorderWidget.tsx +70 -56
- package/src/components/SessionRecorderWidget/icons.tsx +58 -30
- package/src/components/SessionRecorderWidget/index.ts +1 -1
- package/src/components/SessionRecorderWidget/styles.ts +17 -18
- package/src/components/index.ts +2 -2
- package/src/config/constants.ts +19 -20
- package/src/config/defaults.ts +35 -31
- package/src/config/index.ts +5 -5
- package/src/config/masking.ts +44 -18
- package/src/config/session-recorder.ts +54 -26
- package/src/config/validators.ts +43 -20
- package/src/config/widget.ts +24 -15
- package/src/context/SessionRecorderStore.ts +19 -18
- package/src/context/useSessionRecorderStore.ts +17 -10
- package/src/context/useStoreSelector.ts +20 -18
- package/src/index.ts +7 -7
- package/src/native/SessionRecorderNative.ts +68 -112
- package/src/native/index.ts +5 -1
- package/src/otel/helpers.ts +109 -93
- package/src/otel/index.ts +46 -49
- package/src/otel/instrumentations/index.ts +44 -41
- package/src/patch/index.ts +1 -1
- package/src/patch/xhr.ts +77 -78
- package/src/recorder/eventExporter.ts +63 -68
- package/src/recorder/gestureRecorder.ts +359 -212
- package/src/recorder/index.ts +75 -62
- package/src/recorder/navigationTracker.ts +120 -97
- package/src/recorder/screenRecorder.ts +214 -163
- package/src/services/api.service.ts +49 -48
- package/src/services/network.service.ts +67 -58
- package/src/services/screenMaskingService.ts +81 -50
- package/src/services/storage.service.ts +99 -70
- package/src/session-recorder.ts +270 -214
- package/src/types/configs.ts +53 -31
- package/src/types/expo-constants.d.ts +2 -2
- package/src/types/index.ts +16 -18
- package/src/types/session-recorder.ts +106 -111
- package/src/types/session.ts +45 -45
- package/src/utils/app-metadata.ts +9 -9
- package/src/utils/constants.optional.expo.ts +3 -3
- package/src/utils/constants.optional.ts +14 -12
- package/src/utils/createStore.ts +23 -20
- package/src/utils/index.ts +7 -7
- package/src/utils/logger.ts +87 -58
- package/src/utils/platform.ts +149 -118
- package/src/utils/request-utils.ts +15 -15
- package/src/utils/rrweb-events.ts +47 -34
- package/src/utils/session.ts +15 -12
- package/src/utils/shallowEqual.ts +16 -10
- package/src/utils/time.ts +7 -4
- package/src/utils/type-utils.ts +36 -36
- package/src/version.ts +1 -1
- package/android/src/main/java/com/multiplayer/sessionrecordernative/SessionRecorderNativeModuleSpec.kt +0 -51
- package/android/src/main/java/com/xxx/XxxModule.kt +0 -23
- package/ios/Xxx.h +0 -5
- package/ios/Xxx.mm +0 -21
|
@@ -1,42 +1,44 @@
|
|
|
1
|
-
import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch'
|
|
2
|
-
import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request'
|
|
3
|
-
|
|
4
|
-
import { logger } from '../../utils'
|
|
5
|
-
import { OTEL_IGNORE_URLS } from '../../config'
|
|
6
|
-
import { type TracerReactNativeConfig } from '../../types'
|
|
7
|
-
import {
|
|
1
|
+
import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
|
|
2
|
+
import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
|
|
3
|
+
|
|
4
|
+
import { logger } from '../../utils';
|
|
5
|
+
import { OTEL_IGNORE_URLS } from '../../config';
|
|
6
|
+
import { type TracerReactNativeConfig } from '../../types';
|
|
7
|
+
import {
|
|
8
|
+
extractResponseBody,
|
|
9
|
+
headersToObject,
|
|
10
|
+
processHttpPayload,
|
|
11
|
+
} from '../helpers';
|
|
8
12
|
|
|
9
13
|
export function getInstrumentations(config: TracerReactNativeConfig) {
|
|
10
|
-
|
|
11
|
-
const instrumentations = []
|
|
14
|
+
const instrumentations = [];
|
|
12
15
|
|
|
13
16
|
// Fetch instrumentation
|
|
14
17
|
try {
|
|
15
18
|
instrumentations.push(
|
|
16
19
|
new FetchInstrumentation({
|
|
17
20
|
clearTimingResources: false,
|
|
18
|
-
ignoreUrls: [
|
|
19
|
-
...OTEL_IGNORE_URLS,
|
|
20
|
-
...(config.ignoreUrls || []),
|
|
21
|
-
],
|
|
21
|
+
ignoreUrls: [...OTEL_IGNORE_URLS, ...(config.ignoreUrls || [])],
|
|
22
22
|
propagateTraceHeaderCorsUrls: config.propagateTraceHeaderCorsUrls,
|
|
23
23
|
applyCustomAttributesOnSpan: async (span, request, response) => {
|
|
24
|
-
if (!config) return
|
|
24
|
+
if (!config) return;
|
|
25
25
|
|
|
26
|
-
const { captureBody, captureHeaders } = config
|
|
26
|
+
const { captureBody, captureHeaders } = config;
|
|
27
27
|
|
|
28
28
|
try {
|
|
29
29
|
if (!captureBody && !captureHeaders) {
|
|
30
|
-
return
|
|
30
|
+
return;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
const requestBody = request.body
|
|
34
|
-
const requestHeaders = headersToObject(request.headers)
|
|
35
|
-
const responseHeaders = headersToObject(
|
|
33
|
+
const requestBody = request.body;
|
|
34
|
+
const requestHeaders = headersToObject(request.headers);
|
|
35
|
+
const responseHeaders = headersToObject(
|
|
36
|
+
response instanceof Response ? response.headers : undefined
|
|
37
|
+
);
|
|
36
38
|
|
|
37
|
-
let responseBody: string | null = null
|
|
39
|
+
let responseBody: string | null = null;
|
|
38
40
|
if (response instanceof Response && response.body) {
|
|
39
|
-
responseBody = await extractResponseBody(response)
|
|
41
|
+
responseBody = await extractResponseBody(response);
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
const payload = {
|
|
@@ -44,17 +46,17 @@ export function getInstrumentations(config: TracerReactNativeConfig) {
|
|
|
44
46
|
responseBody,
|
|
45
47
|
requestHeaders,
|
|
46
48
|
responseHeaders,
|
|
47
|
-
}
|
|
48
|
-
processHttpPayload(payload, config, span)
|
|
49
|
+
};
|
|
50
|
+
processHttpPayload(payload, config, span);
|
|
49
51
|
} catch (error) {
|
|
50
52
|
// eslint-disable-next-line
|
|
51
53
|
logger.error('DEBUGGER_LIB', 'Failed to capture fetch payload', error)
|
|
52
54
|
}
|
|
53
55
|
},
|
|
54
56
|
})
|
|
55
|
-
)
|
|
57
|
+
);
|
|
56
58
|
} catch (error) {
|
|
57
|
-
logger.warn('DEBUGGER_LIB', 'Fetch instrumentation not available', error)
|
|
59
|
+
logger.warn('DEBUGGER_LIB', 'Fetch instrumentation not available', error);
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
// XMLHttpRequest instrumentation
|
|
@@ -62,46 +64,47 @@ export function getInstrumentations(config: TracerReactNativeConfig) {
|
|
|
62
64
|
instrumentations.push(
|
|
63
65
|
new XMLHttpRequestInstrumentation({
|
|
64
66
|
clearTimingResources: false,
|
|
65
|
-
ignoreUrls: [
|
|
66
|
-
...OTEL_IGNORE_URLS,
|
|
67
|
-
...(config.ignoreUrls || []),
|
|
68
|
-
],
|
|
67
|
+
ignoreUrls: [...OTEL_IGNORE_URLS, ...(config.ignoreUrls || [])],
|
|
69
68
|
propagateTraceHeaderCorsUrls: config.propagateTraceHeaderCorsUrls,
|
|
70
69
|
applyCustomAttributesOnSpan: (span, xhr) => {
|
|
71
|
-
if (!config) return
|
|
70
|
+
if (!config) return;
|
|
72
71
|
|
|
73
|
-
const { captureBody, captureHeaders } = config
|
|
72
|
+
const { captureBody, captureHeaders } = config;
|
|
74
73
|
|
|
75
74
|
try {
|
|
76
75
|
if (!captureBody && !captureHeaders) {
|
|
77
|
-
return
|
|
76
|
+
return;
|
|
78
77
|
}
|
|
79
78
|
|
|
80
79
|
// @ts-ignore
|
|
81
|
-
const requestBody = xhr.networkRequest.requestBody
|
|
80
|
+
const requestBody = xhr.networkRequest.requestBody;
|
|
82
81
|
// @ts-ignore
|
|
83
|
-
const responseBody = xhr.networkRequest.responseBody
|
|
82
|
+
const responseBody = xhr.networkRequest.responseBody;
|
|
84
83
|
// @ts-ignore
|
|
85
|
-
const requestHeaders = xhr.networkRequest.requestHeaders || {}
|
|
84
|
+
const requestHeaders = xhr.networkRequest.requestHeaders || {};
|
|
86
85
|
// @ts-ignore
|
|
87
|
-
const responseHeaders = xhr.networkRequest.responseHeaders || {}
|
|
86
|
+
const responseHeaders = xhr.networkRequest.responseHeaders || {};
|
|
88
87
|
|
|
89
88
|
const payload = {
|
|
90
89
|
requestBody,
|
|
91
90
|
responseBody,
|
|
92
91
|
requestHeaders,
|
|
93
92
|
responseHeaders,
|
|
94
|
-
}
|
|
95
|
-
processHttpPayload(payload, config, span)
|
|
93
|
+
};
|
|
94
|
+
processHttpPayload(payload, config, span);
|
|
96
95
|
} catch (error) {
|
|
97
96
|
// eslint-disable-next-line
|
|
98
97
|
logger.error('DEBUGGER_LIB', 'Failed to capture xml-http payload', error)
|
|
99
98
|
}
|
|
100
99
|
},
|
|
101
100
|
})
|
|
102
|
-
)
|
|
101
|
+
);
|
|
103
102
|
} catch (error) {
|
|
104
|
-
logger.warn(
|
|
103
|
+
logger.warn(
|
|
104
|
+
'DEBUGGER_LIB',
|
|
105
|
+
'XMLHttpRequest instrumentation not available',
|
|
106
|
+
error
|
|
107
|
+
);
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
// Custom React Native instrumentations
|
|
@@ -111,5 +114,5 @@ export function getInstrumentations(config: TracerReactNativeConfig) {
|
|
|
111
114
|
// console.warn('React Native instrumentation not available:', error)
|
|
112
115
|
// }
|
|
113
116
|
|
|
114
|
-
return instrumentations
|
|
117
|
+
return instrumentations;
|
|
115
118
|
}
|
package/src/patch/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import './xhr'
|
|
1
|
+
import './xhr';
|
package/src/patch/xhr.ts
CHANGED
|
@@ -1,149 +1,148 @@
|
|
|
1
|
-
import { Platform } from 'react-native'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
isNullish,
|
|
6
|
-
isObject,
|
|
7
|
-
isString,
|
|
8
|
-
} from '../utils/type-utils'
|
|
9
|
-
import { formDataToQuery } from '../utils/request-utils'
|
|
10
|
-
import { DEFAULT_MAX_HTTP_CAPTURING_PAYLOAD_SIZE } from '../config'
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import { isFormData, isNullish, isObject, isString } from '../utils/type-utils';
|
|
3
|
+
import { formDataToQuery } from '../utils/request-utils';
|
|
4
|
+
import { DEFAULT_MAX_HTTP_CAPTURING_PAYLOAD_SIZE } from '../config';
|
|
11
5
|
|
|
12
6
|
// Check if we're on web platform
|
|
13
|
-
const isWeb = Platform.OS === 'web'
|
|
14
|
-
|
|
15
|
-
let recordRequestHeaders = true
|
|
16
|
-
let recordResponseHeaders = true
|
|
17
|
-
let shouldRecordBody = true
|
|
18
|
-
let maxCapturingHttpPayloadSize = DEFAULT_MAX_HTTP_CAPTURING_PAYLOAD_SIZE
|
|
19
|
-
|
|
20
|
-
export const setMaxCapturingHttpPayloadSize = (
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
shouldRecordBody
|
|
28
|
-
|
|
7
|
+
const isWeb = Platform.OS === 'web';
|
|
8
|
+
|
|
9
|
+
let recordRequestHeaders = true;
|
|
10
|
+
let recordResponseHeaders = true;
|
|
11
|
+
let shouldRecordBody = true;
|
|
12
|
+
let maxCapturingHttpPayloadSize = DEFAULT_MAX_HTTP_CAPTURING_PAYLOAD_SIZE;
|
|
13
|
+
|
|
14
|
+
export const setMaxCapturingHttpPayloadSize = (
|
|
15
|
+
_maxCapturingHttpPayloadSize: number
|
|
16
|
+
) => {
|
|
17
|
+
maxCapturingHttpPayloadSize = _maxCapturingHttpPayloadSize;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const setShouldRecordHttpData = (
|
|
21
|
+
shouldRecordBody: boolean,
|
|
22
|
+
shouldRecordHeaders: boolean
|
|
23
|
+
) => {
|
|
24
|
+
recordRequestHeaders = shouldRecordHeaders;
|
|
25
|
+
recordResponseHeaders = shouldRecordHeaders;
|
|
26
|
+
shouldRecordBody = shouldRecordBody;
|
|
27
|
+
};
|
|
29
28
|
|
|
30
29
|
function _tryReadXHRBody({
|
|
31
30
|
body,
|
|
32
31
|
}: {
|
|
33
|
-
body: any | null | undefined
|
|
34
|
-
url: string | URL | RequestInfo
|
|
32
|
+
body: any | null | undefined;
|
|
33
|
+
url: string | URL | RequestInfo;
|
|
35
34
|
}): string | null {
|
|
36
|
-
|
|
37
35
|
if (isNullish(body)) {
|
|
38
|
-
return null
|
|
36
|
+
return null;
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
if (isString(body)) {
|
|
42
|
-
return body
|
|
40
|
+
return body;
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
if (isFormData(body)) {
|
|
46
|
-
return formDataToQuery(body)
|
|
44
|
+
return formDataToQuery(body);
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
if (isObject(body)) {
|
|
50
48
|
try {
|
|
51
|
-
return JSON.stringify({ ...body })
|
|
49
|
+
return JSON.stringify({ ...body });
|
|
52
50
|
} catch {
|
|
53
|
-
return '[XHR] Failed to stringify response object'
|
|
51
|
+
return '[XHR] Failed to stringify response object';
|
|
54
52
|
}
|
|
55
53
|
}
|
|
56
54
|
|
|
57
|
-
return `[XHR] Cannot read body of type ${Object.prototype.toString.call(body)}
|
|
55
|
+
return `[XHR] Cannot read body of type ${Object.prototype.toString.call(body)}`;
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
// Only patch XMLHttpRequest if not on web platform or if XMLHttpRequest is available
|
|
61
59
|
if (!isWeb && typeof XMLHttpRequest !== 'undefined') {
|
|
62
60
|
(function (xhr) {
|
|
63
|
-
const originalOpen = XMLHttpRequest.prototype.open
|
|
61
|
+
const originalOpen = XMLHttpRequest.prototype.open;
|
|
64
62
|
|
|
65
63
|
xhr.open = function (
|
|
66
64
|
method: string,
|
|
67
65
|
url: string | URL,
|
|
68
66
|
async = true,
|
|
69
67
|
username?: string | null,
|
|
70
|
-
password?: string | null
|
|
68
|
+
password?: string | null
|
|
71
69
|
) {
|
|
72
|
-
const xhr = this as XMLHttpRequest
|
|
70
|
+
const xhr = this as XMLHttpRequest;
|
|
73
71
|
const networkRequest: {
|
|
74
|
-
requestHeaders?: any
|
|
75
|
-
requestBody?: any
|
|
76
|
-
responseHeaders?: any
|
|
77
|
-
responseBody?: any
|
|
78
|
-
} = {}
|
|
79
|
-
|
|
72
|
+
requestHeaders?: any;
|
|
73
|
+
requestBody?: any;
|
|
74
|
+
responseHeaders?: any;
|
|
75
|
+
responseBody?: any;
|
|
76
|
+
} = {};
|
|
80
77
|
|
|
81
78
|
// @ts-ignore
|
|
82
|
-
const requestHeaders: Record<string, string> = {}
|
|
83
|
-
const originalSetRequestHeader = xhr.setRequestHeader.bind(xhr)
|
|
79
|
+
const requestHeaders: Record<string, string> = {};
|
|
80
|
+
const originalSetRequestHeader = xhr.setRequestHeader.bind(xhr);
|
|
84
81
|
xhr.setRequestHeader = (header: string, value: string) => {
|
|
85
|
-
requestHeaders[header] = value
|
|
86
|
-
return originalSetRequestHeader(header, value)
|
|
87
|
-
}
|
|
82
|
+
requestHeaders[header] = value;
|
|
83
|
+
return originalSetRequestHeader(header, value);
|
|
84
|
+
};
|
|
88
85
|
if (recordRequestHeaders) {
|
|
89
|
-
networkRequest.requestHeaders = requestHeaders
|
|
86
|
+
networkRequest.requestHeaders = requestHeaders;
|
|
90
87
|
}
|
|
91
88
|
|
|
92
|
-
const originalSend = xhr.send.bind(xhr)
|
|
89
|
+
const originalSend = xhr.send.bind(xhr);
|
|
93
90
|
xhr.send = (body) => {
|
|
94
91
|
if (shouldRecordBody) {
|
|
95
|
-
const requestBody = _tryReadXHRBody({ body, url })
|
|
92
|
+
const requestBody = _tryReadXHRBody({ body, url });
|
|
96
93
|
|
|
97
94
|
if (
|
|
98
|
-
requestBody?.length
|
|
99
|
-
|
|
95
|
+
requestBody?.length &&
|
|
96
|
+
requestBody.length <= maxCapturingHttpPayloadSize
|
|
100
97
|
) {
|
|
101
|
-
networkRequest.requestBody = requestBody
|
|
98
|
+
networkRequest.requestBody = requestBody;
|
|
102
99
|
}
|
|
103
100
|
}
|
|
104
|
-
return originalSend(body)
|
|
105
|
-
}
|
|
101
|
+
return originalSend(body);
|
|
102
|
+
};
|
|
106
103
|
|
|
107
104
|
xhr.addEventListener('readystatechange', () => {
|
|
108
105
|
if (xhr.readyState !== xhr.DONE) {
|
|
109
|
-
return
|
|
106
|
+
return;
|
|
110
107
|
}
|
|
111
108
|
|
|
112
109
|
// @ts-ignore
|
|
113
|
-
const responseHeaders: Record<string, string> = {}
|
|
114
|
-
const rawHeaders = xhr.getAllResponseHeaders() || ''
|
|
115
|
-
const headers = rawHeaders
|
|
110
|
+
const responseHeaders: Record<string, string> = {};
|
|
111
|
+
const rawHeaders = xhr.getAllResponseHeaders() || '';
|
|
112
|
+
const headers = rawHeaders
|
|
113
|
+
.trim()
|
|
114
|
+
.split(/[\r\n]+/)
|
|
115
|
+
.filter(Boolean);
|
|
116
116
|
|
|
117
117
|
headers.forEach((line) => {
|
|
118
|
-
const parts = line.split(': ')
|
|
119
|
-
const header = parts.shift()
|
|
120
|
-
const value = parts.join(': ')
|
|
118
|
+
const parts = line.split(': ');
|
|
119
|
+
const header = parts.shift();
|
|
120
|
+
const value = parts.join(': ');
|
|
121
121
|
if (header) {
|
|
122
|
-
responseHeaders[header] = value
|
|
122
|
+
responseHeaders[header] = value;
|
|
123
123
|
}
|
|
124
|
-
})
|
|
124
|
+
});
|
|
125
125
|
if (recordResponseHeaders) {
|
|
126
|
-
networkRequest.responseHeaders = responseHeaders
|
|
126
|
+
networkRequest.responseHeaders = responseHeaders;
|
|
127
127
|
}
|
|
128
128
|
if (shouldRecordBody) {
|
|
129
|
-
const responseBody = _tryReadXHRBody({ body: xhr.response, url })
|
|
129
|
+
const responseBody = _tryReadXHRBody({ body: xhr.response, url });
|
|
130
130
|
|
|
131
131
|
if (
|
|
132
|
-
responseBody?.length
|
|
133
|
-
|
|
132
|
+
responseBody?.length &&
|
|
133
|
+
responseBody.length <= maxCapturingHttpPayloadSize
|
|
134
134
|
) {
|
|
135
|
-
networkRequest.responseBody = responseBody
|
|
135
|
+
networkRequest.responseBody = responseBody;
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
|
-
})
|
|
139
|
-
|
|
138
|
+
});
|
|
140
139
|
|
|
141
140
|
// @ts-ignore
|
|
142
|
-
xhr.networkRequest = networkRequest
|
|
141
|
+
xhr.networkRequest = networkRequest;
|
|
143
142
|
|
|
144
|
-
originalOpen.call(xhr, method, url as string, async, username, password)
|
|
145
|
-
}
|
|
146
|
-
})(XMLHttpRequest.prototype)
|
|
143
|
+
originalOpen.call(xhr, method, url as string, async, username, password);
|
|
144
|
+
};
|
|
145
|
+
})(XMLHttpRequest.prototype);
|
|
147
146
|
} else if (isWeb) {
|
|
148
|
-
console.info('XHR patch: Skipping XMLHttpRequest patching on web platform')
|
|
147
|
+
console.info('XHR patch: Skipping XMLHttpRequest patching on web platform');
|
|
149
148
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import io, { Socket } from 'socket.io-client'
|
|
1
|
+
import io, { Socket } from 'socket.io-client';
|
|
2
2
|
|
|
3
|
-
import { type ISession } from '../types'
|
|
4
|
-
import { logger } from '../utils'
|
|
3
|
+
import { type ISession } from '../types';
|
|
4
|
+
import { logger } from '../utils';
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
SESSION_ADD_EVENT,
|
|
@@ -9,30 +9,30 @@ import {
|
|
|
9
9
|
SESSION_STOPPED_EVENT,
|
|
10
10
|
SESSION_SUBSCRIBE_EVENT,
|
|
11
11
|
SESSION_UNSUBSCRIBE_EVENT,
|
|
12
|
-
} from '../config'
|
|
12
|
+
} from '../config';
|
|
13
13
|
|
|
14
|
-
const MAX_RECONNECTION_ATTEMPTS = 2
|
|
14
|
+
const MAX_RECONNECTION_ATTEMPTS = 2;
|
|
15
15
|
|
|
16
16
|
export class EventExporter {
|
|
17
|
-
private socket: Socket | null = null
|
|
18
|
-
private queue: any[] = []
|
|
19
|
-
private isConnecting: boolean = false
|
|
20
|
-
private isConnected: boolean = false
|
|
21
|
-
private attempts: number = 0
|
|
22
|
-
private sessionId: string | null = null
|
|
23
|
-
|
|
24
|
-
private socketUrl: string
|
|
25
|
-
private apiKey: string
|
|
26
|
-
|
|
27
|
-
constructor(options: { socketUrl: string
|
|
28
|
-
this.socketUrl = options.socketUrl
|
|
29
|
-
this.apiKey = options.apiKey
|
|
17
|
+
private socket: Socket | null = null;
|
|
18
|
+
private queue: any[] = [];
|
|
19
|
+
private isConnecting: boolean = false;
|
|
20
|
+
private isConnected: boolean = false;
|
|
21
|
+
private attempts: number = 0;
|
|
22
|
+
private sessionId: string | null = null;
|
|
23
|
+
|
|
24
|
+
private socketUrl: string;
|
|
25
|
+
private apiKey: string;
|
|
26
|
+
|
|
27
|
+
constructor(options: { socketUrl: string; apiKey: string }) {
|
|
28
|
+
this.socketUrl = options.socketUrl;
|
|
29
|
+
this.apiKey = options.apiKey;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
private init(): void {
|
|
33
|
-
if (this.isConnecting || this.isConnected) return
|
|
34
|
-
this.attempts
|
|
35
|
-
this.isConnecting = true
|
|
33
|
+
if (this.isConnecting || this.isConnected) return;
|
|
34
|
+
this.attempts++;
|
|
35
|
+
this.isConnecting = true;
|
|
36
36
|
this.socket = io(this.socketUrl, {
|
|
37
37
|
path: '/v0/radar/ws',
|
|
38
38
|
auth: {
|
|
@@ -40,7 +40,7 @@ export class EventExporter {
|
|
|
40
40
|
},
|
|
41
41
|
reconnectionAttempts: 2,
|
|
42
42
|
transports: ['websocket'],
|
|
43
|
-
})
|
|
43
|
+
});
|
|
44
44
|
|
|
45
45
|
// this.socket.on('connect', () => {
|
|
46
46
|
// this.isConnecting = false
|
|
@@ -50,58 +50,53 @@ export class EventExporter {
|
|
|
50
50
|
// })
|
|
51
51
|
|
|
52
52
|
this.socket.on('ready', () => {
|
|
53
|
-
this.isConnecting = false
|
|
54
|
-
this.isConnected = true
|
|
55
|
-
logger.info('EventExporter', 'Connected to server')
|
|
56
|
-
this.flushQueue()
|
|
57
|
-
})
|
|
53
|
+
this.isConnecting = false;
|
|
54
|
+
this.isConnected = true;
|
|
55
|
+
logger.info('EventExporter', 'Connected to server');
|
|
56
|
+
this.flushQueue();
|
|
57
|
+
});
|
|
58
58
|
|
|
59
59
|
this.socket.on('disconnect', (_err: any) => {
|
|
60
|
-
this.isConnecting = false
|
|
61
|
-
this.isConnected = false
|
|
62
|
-
logger.info('EventExporter', 'Disconnected from server')
|
|
63
|
-
})
|
|
60
|
+
this.isConnecting = false;
|
|
61
|
+
this.isConnected = false;
|
|
62
|
+
logger.info('EventExporter', 'Disconnected from server');
|
|
63
|
+
});
|
|
64
64
|
|
|
65
65
|
this.socket.on('connect_error', (err: any) => {
|
|
66
|
-
this.isConnecting = false
|
|
67
|
-
this.isConnected = false
|
|
68
|
-
this.checkReconnectionAttempts()
|
|
69
|
-
logger.error('EventExporter', 'Error connecting to server', err)
|
|
70
|
-
})
|
|
66
|
+
this.isConnecting = false;
|
|
67
|
+
this.isConnected = false;
|
|
68
|
+
this.checkReconnectionAttempts();
|
|
69
|
+
logger.error('EventExporter', 'Error connecting to server', err);
|
|
70
|
+
});
|
|
71
71
|
|
|
72
72
|
this.socket.on(SESSION_STOPPED_EVENT, (_: any) => {
|
|
73
|
+
this.unsubscribeFromSession();
|
|
74
|
+
});
|
|
73
75
|
|
|
74
|
-
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
this.socket.on(SESSION_AUTO_CREATED, (_: any) => {
|
|
78
|
-
|
|
79
|
-
})
|
|
76
|
+
this.socket.on(SESSION_AUTO_CREATED, (_: any) => {});
|
|
80
77
|
}
|
|
81
78
|
|
|
82
79
|
setApiKey(apiKey: string): void {
|
|
83
|
-
this.apiKey = apiKey
|
|
80
|
+
this.apiKey = apiKey;
|
|
84
81
|
}
|
|
85
82
|
|
|
86
83
|
setSocketUrl(socketUrl: string): void {
|
|
87
|
-
this.socketUrl = socketUrl
|
|
84
|
+
this.socketUrl = socketUrl;
|
|
88
85
|
}
|
|
89
86
|
|
|
90
87
|
private checkReconnectionAttempts(): void {
|
|
91
88
|
if (this.attempts >= MAX_RECONNECTION_ATTEMPTS) {
|
|
92
|
-
|
|
93
|
-
this.flushQueue()
|
|
89
|
+
this.flushQueue();
|
|
94
90
|
}
|
|
95
91
|
}
|
|
96
92
|
|
|
97
|
-
|
|
98
93
|
private flushQueue(): void {
|
|
99
|
-
while (this.queue.length > 0 &&
|
|
100
|
-
const event = this.queue.shift()
|
|
101
|
-
if (!event) continue
|
|
94
|
+
while (this.queue.length > 0 && this.socket?.connected) {
|
|
95
|
+
const event = this.queue.shift();
|
|
96
|
+
if (!event) continue;
|
|
102
97
|
|
|
103
98
|
if (this.socket?.connected) {
|
|
104
|
-
this.socket.emit(event.name, event.data)
|
|
99
|
+
this.socket.emit(event.name, event.data);
|
|
105
100
|
}
|
|
106
101
|
}
|
|
107
102
|
}
|
|
@@ -109,47 +104,47 @@ export class EventExporter {
|
|
|
109
104
|
private unsubscribeFromSession() {
|
|
110
105
|
const payload = {
|
|
111
106
|
debugSessionId: this.sessionId,
|
|
112
|
-
}
|
|
107
|
+
};
|
|
113
108
|
if (this.socket?.connected) {
|
|
114
|
-
this.socket.emit(SESSION_UNSUBSCRIBE_EVENT, payload)
|
|
109
|
+
this.socket.emit(SESSION_UNSUBSCRIBE_EVENT, payload);
|
|
115
110
|
}
|
|
116
111
|
}
|
|
117
112
|
|
|
118
113
|
public send(event: any): void {
|
|
119
114
|
if (this.socket?.connected) {
|
|
120
|
-
this.socket.emit(SESSION_ADD_EVENT, event)
|
|
115
|
+
this.socket.emit(SESSION_ADD_EVENT, event);
|
|
121
116
|
} else {
|
|
122
|
-
this.queue.push({ data: event, name: SESSION_ADD_EVENT })
|
|
123
|
-
this.init()
|
|
117
|
+
this.queue.push({ data: event, name: SESSION_ADD_EVENT });
|
|
118
|
+
this.init();
|
|
124
119
|
}
|
|
125
120
|
}
|
|
126
121
|
|
|
127
122
|
public subscribeToSession(session: ISession): void {
|
|
128
|
-
this.sessionId = session.shortId || session._id
|
|
123
|
+
this.sessionId = session.shortId || session._id;
|
|
129
124
|
const payload = {
|
|
130
125
|
projectId: session.project,
|
|
131
126
|
workspaceId: session.workspace,
|
|
132
127
|
debugSessionId: this.sessionId,
|
|
133
128
|
sessionType: session.creationType,
|
|
134
|
-
}
|
|
129
|
+
};
|
|
135
130
|
if (this.socket?.connected) {
|
|
136
|
-
this.socket.emit(SESSION_SUBSCRIBE_EVENT, payload)
|
|
131
|
+
this.socket.emit(SESSION_SUBSCRIBE_EVENT, payload);
|
|
137
132
|
} else {
|
|
138
|
-
this.queue.push({ data: payload, name: SESSION_SUBSCRIBE_EVENT })
|
|
139
|
-
this.init()
|
|
133
|
+
this.queue.push({ data: payload, name: SESSION_SUBSCRIBE_EVENT });
|
|
134
|
+
this.init();
|
|
140
135
|
}
|
|
141
136
|
}
|
|
142
137
|
|
|
143
138
|
public close(): void {
|
|
144
139
|
if (this.socket?.connected) {
|
|
145
140
|
setTimeout(() => {
|
|
146
|
-
this.unsubscribeFromSession()
|
|
147
|
-
this.attempts = 0
|
|
148
|
-
this.isConnected = false
|
|
149
|
-
this.isConnecting = false
|
|
150
|
-
this.socket?.disconnect()
|
|
151
|
-
this.socket = null
|
|
152
|
-
}, 500)
|
|
141
|
+
this.unsubscribeFromSession();
|
|
142
|
+
this.attempts = 0;
|
|
143
|
+
this.isConnected = false;
|
|
144
|
+
this.isConnecting = false;
|
|
145
|
+
this.socket?.disconnect();
|
|
146
|
+
this.socket = null;
|
|
147
|
+
}, 500);
|
|
153
148
|
}
|
|
154
149
|
}
|
|
155
150
|
}
|