@luciq/react-native 19.2.2 → 19.3.0-40271-SNAPSHOT
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/CHANGELOG.md +18 -0
- package/README.md +87 -0
- package/android/native.gradle +1 -1
- package/android/src/main/java/ai/luciq/reactlibrary/RNLuciqAPMModule.java +211 -117
- package/android/src/main/java/ai/luciq/reactlibrary/RNLuciqNetworkLoggerModule.java +29 -7
- package/android/src/main/java/ai/luciq/reactlibrary/RNLuciqReactnativeModule.java +51 -9
- package/android/src/main/java/ai/luciq/reactlibrary/utils/EventEmitterModule.java +7 -0
- package/dist/constants/Strings.d.ts +9 -0
- package/dist/constants/Strings.js +12 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/models/CustomSpan.d.ts +47 -0
- package/dist/models/CustomSpan.js +82 -0
- package/dist/modules/APM.d.ts +58 -0
- package/dist/modules/APM.js +62 -0
- package/dist/modules/Luciq.js +2 -1
- package/dist/modules/NetworkLogger.d.ts +0 -5
- package/dist/modules/NetworkLogger.js +9 -1
- package/dist/native/NativeAPM.d.ts +3 -0
- package/dist/native/NativeLuciq.d.ts +1 -0
- package/dist/utils/CustomSpansManager.d.ts +38 -0
- package/dist/utils/CustomSpansManager.js +173 -0
- package/dist/utils/FeatureFlags.d.ts +6 -0
- package/dist/utils/FeatureFlags.js +35 -0
- package/dist/utils/LuciqUtils.js +6 -0
- package/dist/utils/XhrNetworkInterceptor.js +85 -53
- package/ios/RNLuciq/LuciqAPMBridge.h +13 -0
- package/ios/RNLuciq/LuciqAPMBridge.m +55 -0
- package/ios/RNLuciq/LuciqReactBridge.m +12 -0
- package/ios/RNLuciq/Util/LCQAPM+PrivateAPIs.h +1 -0
- package/ios/native.rb +1 -1
- package/package.json +1 -2
- package/scripts/releases/changelog_to_slack_formatter.sh +9 -0
- package/scripts/releases/get_job_approver.sh +60 -0
- package/scripts/releases/get_release_notes.sh +22 -0
- package/scripts/releases/get_sdk_version.sh +5 -0
- package/scripts/releases/get_slack_id_from_username.sh +24 -0
- package/src/constants/Strings.ts +24 -0
- package/src/index.ts +2 -0
- package/src/models/CustomSpan.ts +102 -0
- package/src/modules/APM.ts +72 -0
- package/src/modules/Luciq.ts +3 -1
- package/src/modules/NetworkLogger.ts +26 -1
- package/src/native/NativeAPM.ts +7 -0
- package/src/native/NativeLuciq.ts +1 -0
- package/src/utils/CustomSpansManager.ts +202 -0
- package/src/utils/FeatureFlags.ts +44 -0
- package/src/utils/LuciqUtils.ts +15 -0
- package/src/utils/XhrNetworkInterceptor.ts +128 -55
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
import { NativeLuciq } from '../native/NativeLuciq';
|
|
2
2
|
import { _registerFeatureFlagsChangeListener } from '../modules/Luciq';
|
|
3
|
+
import { Logger } from './logger';
|
|
4
|
+
|
|
5
|
+
const TAG = 'LCQ-RN-NET:';
|
|
6
|
+
|
|
7
|
+
let cachedW3cFlags = {
|
|
8
|
+
isW3cExternalTraceIDEnabled: false,
|
|
9
|
+
isW3cExternalGeneratedHeaderEnabled: false,
|
|
10
|
+
isW3cCaughtHeaderEnabled: false,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export async function initFeatureFlagsCache() {
|
|
14
|
+
Logger.debug(TAG, '[FeatureFlags] Initializing W3C feature flags cache from native bridge...');
|
|
15
|
+
try {
|
|
16
|
+
const [traceID, generatedHeader, caughtHeader] = await Promise.all([
|
|
17
|
+
NativeLuciq.isW3ExternalTraceIDEnabled(),
|
|
18
|
+
NativeLuciq.isW3ExternalGeneratedHeaderEnabled(),
|
|
19
|
+
NativeLuciq.isW3CaughtHeaderEnabled(),
|
|
20
|
+
]);
|
|
21
|
+
cachedW3cFlags = {
|
|
22
|
+
isW3cExternalTraceIDEnabled: traceID,
|
|
23
|
+
isW3cExternalGeneratedHeaderEnabled: generatedHeader,
|
|
24
|
+
isW3cCaughtHeaderEnabled: caughtHeader,
|
|
25
|
+
};
|
|
26
|
+
Logger.debug(
|
|
27
|
+
TAG,
|
|
28
|
+
`[FeatureFlags] Cache initialized: traceID=${traceID}, generatedHeader=${generatedHeader}, caughtHeader=${caughtHeader}`,
|
|
29
|
+
);
|
|
30
|
+
} catch (e) {
|
|
31
|
+
Logger.debug(TAG, '[FeatureFlags] Failed to initialize cache, using defaults (all false):', e);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function getCachedW3cFlags() {
|
|
36
|
+
return cachedW3cFlags;
|
|
37
|
+
}
|
|
3
38
|
|
|
4
39
|
export const FeatureFlags = {
|
|
5
40
|
isW3ExternalTraceID: () => NativeLuciq.isW3ExternalTraceIDEnabled(),
|
|
@@ -16,6 +51,15 @@ export const registerFeatureFlagsListener = () => {
|
|
|
16
51
|
isW3CaughtHeaderEnabled: boolean;
|
|
17
52
|
networkBodyLimit: number;
|
|
18
53
|
}) => {
|
|
54
|
+
Logger.debug(
|
|
55
|
+
TAG,
|
|
56
|
+
`[FeatureFlags] Flags updated from native listener: traceID=${res.isW3ExternalTraceIDEnabled}, generatedHeader=${res.isW3ExternalGeneratedHeaderEnabled}, caughtHeader=${res.isW3CaughtHeaderEnabled}, bodyLimit=${res.networkBodyLimit}`,
|
|
57
|
+
);
|
|
58
|
+
cachedW3cFlags = {
|
|
59
|
+
isW3cExternalTraceIDEnabled: res.isW3ExternalTraceIDEnabled,
|
|
60
|
+
isW3cExternalGeneratedHeaderEnabled: res.isW3ExternalGeneratedHeaderEnabled,
|
|
61
|
+
isW3cCaughtHeaderEnabled: res.isW3CaughtHeaderEnabled,
|
|
62
|
+
};
|
|
19
63
|
FeatureFlags.isW3ExternalTraceID = async () => {
|
|
20
64
|
return res.isW3ExternalTraceIDEnabled;
|
|
21
65
|
};
|
package/src/utils/LuciqUtils.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { NativeCrashReporting } from '../native/NativeCrashReporting';
|
|
|
12
12
|
import type { NetworkData } from './XhrNetworkInterceptor';
|
|
13
13
|
import { NativeLuciq } from '../native/NativeLuciq';
|
|
14
14
|
import { NativeAPM } from '../native/NativeAPM';
|
|
15
|
+
import { Logger } from './logger';
|
|
15
16
|
import * as NetworkLogger from '../modules/NetworkLogger';
|
|
16
17
|
import {
|
|
17
18
|
NativeNetworkLogger,
|
|
@@ -231,6 +232,11 @@ export const reportNetworkLog = (network: NetworkData) => {
|
|
|
231
232
|
const requestHeaders = JSON.stringify(network.requestHeaders);
|
|
232
233
|
const responseHeaders = JSON.stringify(network.responseHeaders);
|
|
233
234
|
|
|
235
|
+
Logger.debug(
|
|
236
|
+
'LCQ-RN-NET:',
|
|
237
|
+
`[reportNetworkLog] Sending to NativeLuciq.networkLogAndroid: ${network.method} ${network.url}, status=${network.responseCode}, duration=${network.duration}ms, error=${network.errorDomain || 'none'}`,
|
|
238
|
+
);
|
|
239
|
+
|
|
234
240
|
NativeLuciq.networkLogAndroid(
|
|
235
241
|
network.url,
|
|
236
242
|
network.requestBody,
|
|
@@ -246,6 +252,10 @@ export const reportNetworkLog = (network: NetworkData) => {
|
|
|
246
252
|
!apmFlags.hasAPMNetworkPlugin ||
|
|
247
253
|
!apmFlags.shouldEnableNativeInterception
|
|
248
254
|
) {
|
|
255
|
+
Logger.debug(
|
|
256
|
+
'LCQ-RN-NET:',
|
|
257
|
+
`[reportNetworkLog] Also sending to NativeAPM.networkLogAndroid (native interception disabled): ${network.method} ${network.url}`,
|
|
258
|
+
);
|
|
249
259
|
NativeAPM.networkLogAndroid(
|
|
250
260
|
network.startTime,
|
|
251
261
|
network.duration,
|
|
@@ -271,6 +281,11 @@ export const reportNetworkLog = (network: NetworkData) => {
|
|
|
271
281
|
network.gqlQueryName,
|
|
272
282
|
network.serverErrorMessage,
|
|
273
283
|
);
|
|
284
|
+
} else {
|
|
285
|
+
Logger.debug(
|
|
286
|
+
'LCQ-RN-NET:',
|
|
287
|
+
`[reportNetworkLog] Skipping NativeAPM.networkLogAndroid (native interception enabled): nativeFeature=${apmFlags.isNativeInterceptionFeatureEnabled}, hasPlugin=${apmFlags.hasAPMNetworkPlugin}, shouldEnable=${apmFlags.shouldEnableNativeInterception}`,
|
|
288
|
+
);
|
|
274
289
|
}
|
|
275
290
|
} else {
|
|
276
291
|
NativeLuciq.networkLogIOS(
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import LuciqConstants from './LuciqConstants';
|
|
2
2
|
import { stringifyIfNotString, generateW3CHeader } from './LuciqUtils';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { getCachedW3cFlags } from './FeatureFlags';
|
|
5
|
+
import { Logger } from './logger';
|
|
6
|
+
|
|
7
|
+
const TAG = 'LCQ-RN-NET:';
|
|
5
8
|
|
|
6
9
|
export type ProgressCallback = (totalBytesSent: number, totalBytesExpectedToSend: number) => void;
|
|
7
10
|
export type NetworkDataCallback = (data: NetworkData) => void;
|
|
@@ -40,45 +43,41 @@ let originalXHRSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
|
|
|
40
43
|
let onProgressCallback: ProgressCallback | null;
|
|
41
44
|
let onDoneCallback: NetworkDataCallback | null;
|
|
42
45
|
let isInterceptorEnabled = false;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const getTraceparentHeader =
|
|
73
|
-
const
|
|
46
|
+
|
|
47
|
+
const networkMap = new WeakMap<XMLHttpRequest, NetworkData>();
|
|
48
|
+
|
|
49
|
+
const createNetworkData = (): NetworkData => ({
|
|
50
|
+
id: '',
|
|
51
|
+
url: '',
|
|
52
|
+
method: '',
|
|
53
|
+
requestBody: '',
|
|
54
|
+
requestBodySize: 0,
|
|
55
|
+
responseBody: '',
|
|
56
|
+
responseBodySize: 0,
|
|
57
|
+
responseCode: 0,
|
|
58
|
+
requestHeaders: {},
|
|
59
|
+
responseHeaders: {},
|
|
60
|
+
contentType: '',
|
|
61
|
+
errorDomain: '',
|
|
62
|
+
errorCode: 0,
|
|
63
|
+
startTime: 0,
|
|
64
|
+
duration: 0,
|
|
65
|
+
gqlQueryName: '',
|
|
66
|
+
serverErrorMessage: '',
|
|
67
|
+
requestContentType: '',
|
|
68
|
+
isW3cHeaderFound: null,
|
|
69
|
+
partialId: null,
|
|
70
|
+
networkStartTimeInSeconds: null,
|
|
71
|
+
w3cGeneratedHeader: null,
|
|
72
|
+
w3cCaughtHeader: null,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const getTraceparentHeader = (networkData: NetworkData) => {
|
|
76
|
+
const {
|
|
74
77
|
isW3cExternalTraceIDEnabled,
|
|
75
78
|
isW3cExternalGeneratedHeaderEnabled,
|
|
76
79
|
isW3cCaughtHeaderEnabled,
|
|
77
|
-
|
|
78
|
-
FeatureFlags.isW3ExternalTraceID(),
|
|
79
|
-
FeatureFlags.isW3ExternalGeneratedHeader(),
|
|
80
|
-
FeatureFlags.isW3CaughtHeader(),
|
|
81
|
-
]);
|
|
80
|
+
} = getCachedW3cFlags();
|
|
82
81
|
|
|
83
82
|
return injectHeaders(networkData, {
|
|
84
83
|
isW3cExternalTraceIDEnabled,
|
|
@@ -147,44 +146,77 @@ export default {
|
|
|
147
146
|
onProgressCallback = callback;
|
|
148
147
|
},
|
|
149
148
|
enableInterception() {
|
|
150
|
-
// Prevents infinite calls to XMLHttpRequest.open when enabling interception multiple times
|
|
151
149
|
if (isInterceptorEnabled) {
|
|
150
|
+
Logger.debug(TAG, 'enableInterception called but already enabled, skipping');
|
|
152
151
|
return;
|
|
153
152
|
}
|
|
154
153
|
|
|
154
|
+
Logger.debug(TAG, 'Enabling XHR network interception');
|
|
155
|
+
|
|
155
156
|
originalXHROpen = XMLHttpRequest.prototype.open;
|
|
156
157
|
originalXHRSend = XMLHttpRequest.prototype.send;
|
|
157
158
|
originalXHRSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
|
|
158
159
|
// An error code that signifies an issue with the RN client.
|
|
159
160
|
const clientErrorCode = 9876;
|
|
160
161
|
XMLHttpRequest.prototype.open = function (method, url, ...args) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
162
|
+
const networkData = createNetworkData();
|
|
163
|
+
networkData.url = url;
|
|
164
|
+
networkData.method = method;
|
|
165
|
+
networkMap.set(this, networkData);
|
|
166
|
+
Logger.debug(TAG, `[open] ${method} ${url}`);
|
|
164
167
|
originalXHROpen.apply(this, [method, url, ...args]);
|
|
165
168
|
};
|
|
166
169
|
|
|
167
170
|
XMLHttpRequest.prototype.setRequestHeader = function (header, value) {
|
|
168
|
-
// According to the HTTP RFC, headers are case-insensitive, so we convert
|
|
169
|
-
// them to lower-case to make accessing headers predictable.
|
|
170
|
-
// This avoid issues like failing to get the Content-Type header for a request
|
|
171
|
-
// because the header is set as 'Content-Type' instead of 'content-type'.
|
|
172
171
|
const key = header.toLowerCase();
|
|
173
|
-
|
|
172
|
+
const networkData = networkMap.get(this);
|
|
173
|
+
if (networkData) {
|
|
174
|
+
networkData.requestHeaders[key] = stringifyIfNotString(value);
|
|
175
|
+
} else {
|
|
176
|
+
Logger.debug(
|
|
177
|
+
TAG,
|
|
178
|
+
`[setRequestHeader] No networkData found in WeakMap for header "${key}" — request may have been GC'd or open() was not called`,
|
|
179
|
+
);
|
|
180
|
+
}
|
|
174
181
|
originalXHRSetRequestHeader.apply(this, [header, value]);
|
|
175
182
|
};
|
|
176
183
|
|
|
177
|
-
XMLHttpRequest.prototype.send =
|
|
178
|
-
const
|
|
184
|
+
XMLHttpRequest.prototype.send = function (data) {
|
|
185
|
+
const networkData = networkMap.get(this);
|
|
186
|
+
if (!networkData) {
|
|
187
|
+
Logger.debug(
|
|
188
|
+
TAG,
|
|
189
|
+
'[send] No networkData found in WeakMap — falling back to original send (open() was not intercepted)',
|
|
190
|
+
);
|
|
191
|
+
originalXHRSend.apply(this, [data]);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
Logger.debug(TAG, `[send] ${networkData.method} ${networkData.url}`);
|
|
196
|
+
|
|
197
|
+
const cloneNetwork = JSON.parse(JSON.stringify(networkData));
|
|
179
198
|
cloneNetwork.requestBody = data ? data : '';
|
|
180
199
|
|
|
181
200
|
if (typeof cloneNetwork.requestBody !== 'string') {
|
|
182
201
|
cloneNetwork.requestBody = JSON.stringify(cloneNetwork.requestBody);
|
|
183
202
|
}
|
|
184
203
|
|
|
204
|
+
let isReported = false;
|
|
205
|
+
|
|
185
206
|
if (this.addEventListener) {
|
|
186
207
|
this.addEventListener('readystatechange', async () => {
|
|
187
208
|
if (!isInterceptorEnabled) {
|
|
209
|
+
Logger.debug(
|
|
210
|
+
TAG,
|
|
211
|
+
`[readystatechange] Interceptor disabled, ignoring state=${this.readyState} for ${cloneNetwork.url}`,
|
|
212
|
+
);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (isReported) {
|
|
216
|
+
Logger.debug(
|
|
217
|
+
TAG,
|
|
218
|
+
`[readystatechange] Already reported, ignoring state=${this.readyState} for ${cloneNetwork.url}`,
|
|
219
|
+
);
|
|
188
220
|
return;
|
|
189
221
|
}
|
|
190
222
|
if (this.readyState === this.HEADERS_RECEIVED) {
|
|
@@ -217,6 +249,11 @@ export default {
|
|
|
217
249
|
cloneNetwork.requestContentType =
|
|
218
250
|
cloneNetwork.requestHeaders['content-type'].split(';')[0];
|
|
219
251
|
}
|
|
252
|
+
|
|
253
|
+
Logger.debug(
|
|
254
|
+
TAG,
|
|
255
|
+
`[readystatechange] HEADERS_RECEIVED for ${cloneNetwork.url}, contentType=${cloneNetwork.contentType}`,
|
|
256
|
+
);
|
|
220
257
|
}
|
|
221
258
|
|
|
222
259
|
if (this.readyState === this.DONE) {
|
|
@@ -239,12 +276,15 @@ export default {
|
|
|
239
276
|
typeof _response === 'string' ? _response : JSON.stringify(_response);
|
|
240
277
|
cloneNetwork.responseBody = '';
|
|
241
278
|
|
|
242
|
-
// Detect a more descriptive error message.
|
|
243
279
|
if (typeof _response === 'string' && _response.length > 0) {
|
|
244
280
|
cloneNetwork.errorDomain = _response;
|
|
245
281
|
}
|
|
246
282
|
|
|
247
283
|
cloneNetwork.responseBody = `ERROR: ${cloneNetwork.errorDomain}`;
|
|
284
|
+
Logger.debug(
|
|
285
|
+
TAG,
|
|
286
|
+
`[readystatechange] DONE with client error for ${cloneNetwork.url}, errorDomain=${cloneNetwork.errorDomain}`,
|
|
287
|
+
);
|
|
248
288
|
|
|
249
289
|
// @ts-ignore
|
|
250
290
|
} else if (this._timedOut) {
|
|
@@ -253,6 +293,7 @@ export default {
|
|
|
253
293
|
cloneNetwork.responseCode = 0;
|
|
254
294
|
cloneNetwork.contentType = 'text/plain';
|
|
255
295
|
cloneNetwork.responseBody = `ERROR: ${cloneNetwork.errorDomain}`;
|
|
296
|
+
Logger.debug(TAG, `[readystatechange] DONE with timeout for ${cloneNetwork.url}`);
|
|
256
297
|
}
|
|
257
298
|
|
|
258
299
|
// Only set response body if not already set by error handlers
|
|
@@ -300,8 +341,18 @@ export default {
|
|
|
300
341
|
delete cloneNetwork.gqlQueryName;
|
|
301
342
|
}
|
|
302
343
|
|
|
344
|
+
isReported = true;
|
|
345
|
+
Logger.debug(
|
|
346
|
+
TAG,
|
|
347
|
+
`[readystatechange] DONE for ${cloneNetwork.method} ${cloneNetwork.url} — status=${cloneNetwork.responseCode}, duration=${cloneNetwork.duration}ms, hasCallback=${!!onDoneCallback}`,
|
|
348
|
+
);
|
|
303
349
|
if (onDoneCallback) {
|
|
304
350
|
onDoneCallback(cloneNetwork);
|
|
351
|
+
} else {
|
|
352
|
+
Logger.debug(
|
|
353
|
+
TAG,
|
|
354
|
+
`[readystatechange] WARNING: onDoneCallback is null, network log for ${cloneNetwork.url} will be LOST`,
|
|
355
|
+
);
|
|
305
356
|
}
|
|
306
357
|
}
|
|
307
358
|
});
|
|
@@ -310,7 +361,6 @@ export default {
|
|
|
310
361
|
if (!isInterceptorEnabled) {
|
|
311
362
|
return;
|
|
312
363
|
}
|
|
313
|
-
// check if will be able to compute progress
|
|
314
364
|
if (event.lengthComputable && onProgressCallback) {
|
|
315
365
|
const totalBytesSent = event.loaded;
|
|
316
366
|
const totalBytesExpectedToSend = event.total - event.loaded;
|
|
@@ -320,34 +370,57 @@ export default {
|
|
|
320
370
|
this.addEventListener('progress', downloadUploadProgressCallback);
|
|
321
371
|
this.upload.addEventListener('progress', downloadUploadProgressCallback);
|
|
322
372
|
|
|
323
|
-
// Handler for abort events (works with fetch, Axios, and any XHR-based requests)
|
|
324
373
|
this.addEventListener('abort', () => {
|
|
325
374
|
if (!isInterceptorEnabled) {
|
|
375
|
+
Logger.debug(
|
|
376
|
+
TAG,
|
|
377
|
+
`[abort] Interceptor disabled, ignoring abort for ${cloneNetwork.url}`,
|
|
378
|
+
);
|
|
326
379
|
return;
|
|
327
380
|
}
|
|
381
|
+
if (isReported) {
|
|
382
|
+
Logger.debug(
|
|
383
|
+
TAG,
|
|
384
|
+
`[abort] Already reported via readystatechange DONE, ignoring duplicate abort for ${cloneNetwork.url}`,
|
|
385
|
+
);
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
isReported = true;
|
|
328
389
|
cloneNetwork.duration = Date.now() - cloneNetwork.startTime;
|
|
329
390
|
cloneNetwork.responseCode = 0;
|
|
330
391
|
cloneNetwork.errorCode = clientErrorCode;
|
|
331
392
|
cloneNetwork.errorDomain = 'cancelled';
|
|
332
393
|
cloneNetwork.responseBody = `ERROR: ${cloneNetwork.errorDomain}`;
|
|
394
|
+
Logger.debug(
|
|
395
|
+
TAG,
|
|
396
|
+
`[abort] Request cancelled: ${cloneNetwork.method} ${cloneNetwork.url}, duration=${cloneNetwork.duration}ms, hasCallback=${!!onDoneCallback}`,
|
|
397
|
+
);
|
|
398
|
+
if (onDoneCallback) {
|
|
399
|
+
onDoneCallback(cloneNetwork);
|
|
400
|
+
} else {
|
|
401
|
+
Logger.debug(
|
|
402
|
+
TAG,
|
|
403
|
+
`[abort] WARNING: onDoneCallback is null, cancelled log for ${cloneNetwork.url} will be LOST`,
|
|
404
|
+
);
|
|
405
|
+
}
|
|
333
406
|
});
|
|
334
407
|
}
|
|
335
408
|
|
|
336
409
|
cloneNetwork.startTime = Date.now();
|
|
337
|
-
const traceparent =
|
|
410
|
+
const traceparent = getTraceparentHeader(cloneNetwork);
|
|
338
411
|
if (traceparent) {
|
|
339
412
|
this.setRequestHeader('Traceparent', traceparent);
|
|
340
|
-
|
|
341
|
-
if (this.readyState === this.UNSENT) {
|
|
342
|
-
return; // Prevent sending the request if not opened
|
|
413
|
+
Logger.debug(TAG, `[send] Injected traceparent header for ${cloneNetwork.url}`);
|
|
343
414
|
}
|
|
344
415
|
|
|
345
416
|
originalXHRSend.apply(this, [data]);
|
|
346
417
|
};
|
|
347
418
|
isInterceptorEnabled = true;
|
|
419
|
+
Logger.debug(TAG, 'XHR network interception enabled');
|
|
348
420
|
},
|
|
349
421
|
|
|
350
422
|
disableInterception() {
|
|
423
|
+
Logger.debug(TAG, 'Disabling XHR network interception');
|
|
351
424
|
isInterceptorEnabled = false;
|
|
352
425
|
XMLHttpRequest.prototype.send = originalXHRSend;
|
|
353
426
|
XMLHttpRequest.prototype.open = originalXHROpen;
|