noibu-react-native 0.2.3 → 0.2.5
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/dist/api/clientConfig.js +20 -27
- package/dist/api/helpCode.js +61 -87
- package/dist/api/metroplexSocket.js +72 -65
- package/dist/api/storedPageVisit.js +150 -208
- package/dist/constants.js +3 -7
- package/dist/entry/init.js +13 -15
- package/dist/monitors/{appNavigationMonitor.js → AppNavigationMonitor.js} +10 -19
- package/dist/monitors/BaseMonitor.js +23 -0
- package/dist/monitors/ClickMonitor.js +198 -0
- package/dist/monitors/ErrorMonitor.js +206 -0
- package/dist/monitors/KeyboardInputMonitor.js +60 -0
- package/dist/monitors/PageMonitor.js +98 -0
- package/dist/monitors/RequestMonitor.js +390 -0
- package/dist/monitors/http-tools/GqlErrorValidator.js +259 -0
- package/dist/monitors/{httpDataBundler.js → http-tools/HTTPDataBundler.js} +23 -102
- package/dist/pageVisit/{eventDebouncer.js → EventDebouncer.js} +36 -47
- package/dist/pageVisit/pageVisitEventError.js +3 -3
- package/dist/pageVisit/pageVisitEventHTTP.js +5 -4
- package/dist/sessionRecorder/nativeSessionRecorderSubscription.js +22 -5
- package/dist/sessionRecorder/sessionRecorder.js +5 -2
- package/dist/src/api/clientConfig.d.ts +8 -13
- package/dist/src/api/clientConfig.test.d.ts +1 -0
- package/dist/src/api/helpCode.d.ts +10 -16
- package/dist/src/api/metroplexSocket.d.ts +52 -71
- package/dist/src/api/storedPageVisit.d.ts +12 -21
- package/dist/src/constants.d.ts +1 -0
- package/dist/src/monitors/AppNavigationMonitor.d.ts +18 -0
- package/dist/src/monitors/BaseMonitor.d.ts +13 -0
- package/dist/src/monitors/BaseMonitor.test.d.ts +1 -0
- package/dist/src/monitors/ClickMonitor.d.ts +31 -0
- package/dist/src/monitors/ErrorMonitor.d.ts +63 -0
- package/dist/src/monitors/{keyboardInputMonitor.d.ts → KeyboardInputMonitor.d.ts} +7 -4
- package/dist/src/monitors/{pageMonitor.d.ts → PageMonitor.d.ts} +6 -8
- package/dist/src/monitors/RequestMonitor.d.ts +94 -0
- package/dist/src/monitors/http-tools/GqlErrorValidator.d.ts +59 -0
- package/dist/src/monitors/{httpDataBundler.d.ts → http-tools/HTTPDataBundler.d.ts} +13 -28
- package/dist/src/monitors/integrations/react-native-navigation-integration.d.ts +3 -2
- package/dist/src/pageVisit/{eventDebouncer.d.ts → EventDebouncer.d.ts} +3 -10
- package/dist/src/pageVisit/pageVisit.d.ts +1 -1
- package/dist/src/pageVisit/pageVisitEventHTTP.d.ts +3 -3
- package/dist/src/sessionRecorder/nativeSessionRecorderSubscription.d.ts +15 -0
- package/dist/src/storage/rnStorageProvider.d.ts +1 -1
- package/dist/src/storage/storage.d.ts +1 -1
- package/dist/src/storage/storageProvider.d.ts +2 -2
- package/dist/src/utils/function.d.ts +4 -5
- package/dist/src/utils/object.d.ts +3 -5
- package/dist/src/utils/polyfills.d.ts +1 -4
- package/dist/types/Metroplex.types.d.ts +73 -0
- package/dist/types/PageVisit.types.d.ts +2 -145
- package/dist/types/PageVisitErrors.types.d.ts +114 -0
- package/dist/types/PageVisitEvents.types.d.ts +91 -0
- package/dist/types/Storage.d.ts +1 -1
- package/dist/types/StoredPageVisit.types.d.ts +4 -45
- package/dist/utils/function.js +0 -1
- package/dist/utils/object.js +1 -0
- package/package.json +11 -7
- package/dist/monitors/clickMonitor.js +0 -258
- package/dist/monitors/errorMonitor.js +0 -202
- package/dist/monitors/gqlErrorValidator.js +0 -306
- package/dist/monitors/inputMonitor.js +0 -138
- package/dist/monitors/keyboardInputMonitor.js +0 -66
- package/dist/monitors/pageMonitor.js +0 -122
- package/dist/monitors/requestMonitor.js +0 -386
- package/dist/src/monitors/appNavigationMonitor.d.ts +0 -22
- package/dist/src/monitors/clickMonitor.d.ts +0 -44
- package/dist/src/monitors/errorMonitor.d.ts +0 -28
- package/dist/src/monitors/gqlErrorValidator.d.ts +0 -82
- package/dist/src/monitors/inputMonitor.d.ts +0 -34
- package/dist/src/monitors/requestMonitor.d.ts +0 -10
- package/dist/types/RRWeb.d.ts +0 -48
- package/dist/types/ReactNative.d.ts +0 -4
package/dist/api/clientConfig.js
CHANGED
|
@@ -5,6 +5,7 @@ import { stringifyJSON, getMaxSubstringAllowed, getUserAgent, makeRequest } from
|
|
|
5
5
|
import Storage from '../storage/storage.js';
|
|
6
6
|
import { noibuLog } from '../utils/log.js';
|
|
7
7
|
import { unwrapNoibuWrapped } from '../utils/object.js';
|
|
8
|
+
import { Singleton } from '../monitors/BaseMonitor.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Singleton class to manage the client configuration
|
|
@@ -12,54 +13,46 @@ import { unwrapNoibuWrapped } from '../utils/object.js';
|
|
|
12
13
|
* status of the client script as well as managing all storage
|
|
13
14
|
* storing and retrieval.
|
|
14
15
|
*/
|
|
15
|
-
class ClientConfig {
|
|
16
|
+
class ClientConfig extends Singleton {
|
|
16
17
|
/**
|
|
17
18
|
* Creates a ClientConfig singleton instance
|
|
18
19
|
*/
|
|
19
20
|
constructor(noibuErrorURL, customerConfig) {
|
|
20
|
-
|
|
21
|
-
// sets up this.browserId, this.disabledStatus
|
|
21
|
+
super();
|
|
22
22
|
this.pageVisitId = uuid.v4();
|
|
23
|
-
// variables stored in storage
|
|
24
|
-
this.isClientDisabled = false;
|
|
25
23
|
this.browserId = '';
|
|
26
24
|
this.pageVisitSeq = null;
|
|
27
25
|
// This variable tracks the last time the user was active in this session.
|
|
28
26
|
// It is also written to storage. Initialized to now so the session can be
|
|
29
27
|
// timed out even if a PV is never sent.
|
|
30
28
|
this.lastActiveTime = new Date();
|
|
31
|
-
// error URL to send Noibu errors to
|
|
32
|
-
this.noibuErrorURL = noibuErrorURL;
|
|
33
29
|
// error sent to backend counter
|
|
34
30
|
this.cltErrorPostCounter = 0;
|
|
35
31
|
// variables for checking if the socket is inactive
|
|
36
32
|
// used a class variables in order to be changed in testing
|
|
37
33
|
this.maxSocketInactiveTime = MAX_METROPLEX_SOCKET_INNACTIVE_TIME;
|
|
34
|
+
this.locationBreadcrumbs = [];
|
|
35
|
+
this.isClientDisabled = false;
|
|
36
|
+
this.noibuErrorURL = noibuErrorURL;
|
|
38
37
|
this.customerDomain = customerConfig.domain;
|
|
39
38
|
this.listOfUrlsToCollectHttpDataFrom =
|
|
40
39
|
customerConfig.listOfUrlsToCollectHttpDataFrom;
|
|
41
40
|
this.enableHttpDataCollection = customerConfig.enableHttpDataCollection;
|
|
42
41
|
this.blockedElements = customerConfig.blockedElements;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
yield this.instance._setupStorageVars();
|
|
52
|
-
}
|
|
53
|
-
});
|
|
42
|
+
if (!noibuErrorURL || !this.hasAllNecessaryArgs()) {
|
|
43
|
+
const reason = Object.assign({ msg: 'ClientConfig was not properly configured' }, customerConfig);
|
|
44
|
+
void this.postNoibuErrorAndOptionallyDisableClient(reason, true, SEVERITY.error);
|
|
45
|
+
this.configurationPromise = Promise.reject(reason);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// sets up this.browserId, this.isClientDisabled, this.pageVisitSeq
|
|
49
|
+
this.configurationPromise = this._setupStorageVars();
|
|
54
50
|
}
|
|
55
51
|
/**
|
|
56
|
-
*
|
|
52
|
+
* Convenience method to check correct setup
|
|
57
53
|
*/
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
throw new Error('ClientConfig was not configured');
|
|
61
|
-
}
|
|
62
|
-
return this.instance;
|
|
54
|
+
hasAllNecessaryArgs() {
|
|
55
|
+
return (!!this.customerDomain && this.globalUrl.includes(this.customerDomain));
|
|
63
56
|
}
|
|
64
57
|
/** lockClient will disable the client script for a single pagevisit for
|
|
65
58
|
* duration given in minuntes */
|
|
@@ -285,7 +278,7 @@ class ClientConfig {
|
|
|
285
278
|
/** gets current global url */
|
|
286
279
|
get globalUrl() {
|
|
287
280
|
const globalUrl = new URL('https://localhost');
|
|
288
|
-
globalUrl.hostname =
|
|
281
|
+
globalUrl.hostname = this.customerDomain;
|
|
289
282
|
if (this.locationBreadcrumbs.length) {
|
|
290
283
|
globalUrl.pathname = this.locationBreadcrumbs.join('/');
|
|
291
284
|
}
|
|
@@ -296,8 +289,8 @@ class ClientConfig {
|
|
|
296
289
|
* and disable the client if required
|
|
297
290
|
* severity expects one of the SEVERITY_x level constants, or else error will be used
|
|
298
291
|
*/
|
|
299
|
-
postNoibuErrorAndOptionallyDisableClient(errorMsg_1
|
|
300
|
-
return __awaiter(this, arguments, void 0, function* (errorMsg, disableClient, severity, keepAlive = false) {
|
|
292
|
+
postNoibuErrorAndOptionallyDisableClient(errorMsg_1) {
|
|
293
|
+
return __awaiter(this, arguments, void 0, function* (errorMsg, disableClient = false, severity = SEVERITY.error, keepAlive = false) {
|
|
301
294
|
noibuLog('postNoibuErrorAndOptionallyDisableClient', {
|
|
302
295
|
errorMsg,
|
|
303
296
|
disableClient,
|
package/dist/api/helpCode.js
CHANGED
|
@@ -1,100 +1,74 @@
|
|
|
1
|
+
import { __awaiter } from 'tslib';
|
|
1
2
|
import MetroplexSocket from './metroplexSocket.js';
|
|
2
3
|
import { SEVERITY } from '../constants.js';
|
|
3
4
|
import ClientConfig from './clientConfig.js';
|
|
5
|
+
import { Singleton } from '../monitors/BaseMonitor.js';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* HelpCode class is responsible for help code feature related functionality
|
|
7
9
|
*/
|
|
8
|
-
class HelpCode {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
class HelpCode extends Singleton {
|
|
11
|
+
/**
|
|
12
|
+
* Constructs instance and sets up event listeners
|
|
13
|
+
*/
|
|
14
|
+
constructor() {
|
|
15
|
+
super();
|
|
16
|
+
this.requestContext = null;
|
|
17
|
+
this.receiveHelpCode = this.receiveHelpCode.bind(this);
|
|
16
18
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
context.promise = new Promise((resolve, reject) => {
|
|
48
|
-
context.resolve = resolve;
|
|
49
|
-
context.reject = reject;
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
this.requestContext = context;
|
|
53
|
-
|
|
54
|
-
const result = await MetroplexSocket.getInstance().requestHelpCode(
|
|
55
|
-
this.receiveHelpCode,
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
if (result === false) {
|
|
59
|
-
this.requestContext = null;
|
|
60
|
-
return Promise.reject(new Error('noibu connection is unavailable'));
|
|
19
|
+
/**
|
|
20
|
+
* Requests a help code and returns a Promise that resolves when the help code is obtained
|
|
21
|
+
* or rejects if the noibu connection is unavailable.
|
|
22
|
+
|
|
23
|
+
* @returns {Promise<string>} Promise object representing the help code request.
|
|
24
|
+
* @throws {string} Throws an error if the noibu connection is unavailable.
|
|
25
|
+
*/
|
|
26
|
+
requestHelpCode() {
|
|
27
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
+
if (this.requestContext !== null) {
|
|
29
|
+
return this.requestContext.promise;
|
|
30
|
+
}
|
|
31
|
+
const context = {
|
|
32
|
+
resolve: null,
|
|
33
|
+
reject: null,
|
|
34
|
+
promise: null,
|
|
35
|
+
};
|
|
36
|
+
context.promise = new Promise((resolve, reject) => {
|
|
37
|
+
context.resolve = resolve;
|
|
38
|
+
context.reject = reject;
|
|
39
|
+
});
|
|
40
|
+
this.requestContext = context;
|
|
41
|
+
const result = yield MetroplexSocket.getInstance().requestHelpCode(this.receiveHelpCode);
|
|
42
|
+
if (!result) {
|
|
43
|
+
this.requestContext = null;
|
|
44
|
+
return Promise.reject(new Error('noibu connection is unavailable'));
|
|
45
|
+
}
|
|
46
|
+
return this.requestContext.promise;
|
|
47
|
+
});
|
|
61
48
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const context = this.requestContext;
|
|
88
|
-
this.requestContext = null;
|
|
89
|
-
|
|
90
|
-
const { success, data } = event.detail;
|
|
91
|
-
|
|
92
|
-
if (success) {
|
|
93
|
-
context.resolve(data);
|
|
94
|
-
} else {
|
|
95
|
-
context.reject(new Error(data));
|
|
49
|
+
/**
|
|
50
|
+
* Handles the received help code event.
|
|
51
|
+
*/
|
|
52
|
+
receiveHelpCode(event) {
|
|
53
|
+
var _a, _b;
|
|
54
|
+
if (this.requestContext === null) {
|
|
55
|
+
const { success, data } = event.detail;
|
|
56
|
+
if (!success) {
|
|
57
|
+
const message = `Noibu help code is not available due to ${data}`;
|
|
58
|
+
ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(message, false, SEVERITY.error);
|
|
59
|
+
}
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const context = this.requestContext;
|
|
63
|
+
this.requestContext = null;
|
|
64
|
+
const { success, data } = event.detail;
|
|
65
|
+
if (success) {
|
|
66
|
+
(_a = context.resolve) === null || _a === void 0 ? void 0 : _a.call(context, data);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
(_b = context.reject) === null || _b === void 0 ? void 0 : _b.call(context, new Error(data));
|
|
70
|
+
}
|
|
96
71
|
}
|
|
97
|
-
}
|
|
98
72
|
}
|
|
99
73
|
|
|
100
74
|
export { HelpCode as default };
|
|
@@ -2,7 +2,7 @@ import { __awaiter } from 'tslib';
|
|
|
2
2
|
import uuid from 'react-native-uuid';
|
|
3
3
|
import { getUserAgent, stringifyJSON, getVideoRecorderType } from '../utils/function.js';
|
|
4
4
|
import { addSafeEventListener } from '../utils/eventlistener.js';
|
|
5
|
-
import { GET_METROPLEX_BASE_SOCKET_URL, METROPLEX_FRAG_ROUTE, GET_METROPLEX_POST_URL, METROPLEX_RETRY_FREQUENCY,
|
|
5
|
+
import { GET_METROPLEX_BASE_SOCKET_URL, METROPLEX_FRAG_ROUTE, GET_METROPLEX_POST_URL, METROPLEX_RETRY_FREQUENCY, SEQ_NUM_ATT_NAME, WORK_REQUEST_ATT_NAME, HELP_CODE_ATT_NAME, PV_METROPLEX_TYPE, PAGE_VISIT_PART_ATT_NAME, PV_EVENTS_ATT_NAME, TYPE_ATT_NAME, USERSTEP_EVENT_TYPE, GET_MAX_METROPLEX_RECONNECTION_NUMBER, MAX_METROPLEX_CONNECTION_COUNT, GET_METROPLEX_CONSECUTIVE_CONNECTION_DELAY, END_AT_ATT_NAME, SEVERITY, OK_SOCKET_MESSAGE, CLOSE_CONNECTION_FORCEFULLY, BLOCK_SOCKET_MESSAGE, STOP_STORING_PV_SOCKET_MESSAGE, STOP_STORING_VID_SOCKET_MESSAGE, VIDEO_METROPLEX_TYPE, PAGE_VISIT_VID_FRAG_ATT_NAME, MAX_BEACON_PAYLOAD_SIZE, PAGE_VISIT_INFORMATION_ATT_NAME, PAGE_VISIT_HTTP_DATA_ATT_NAME, VIDEO_PART_COUNT_ATT_NAME, IS_LAST_ATT_NAME, HTTP_DATA_METROPLEX_TYPE, BROWSER_ID_ATT_NAME, PV_ID_ATT_NAME, VER_ATT_NAME, CURRENT_PV_VERSION, PV_SEQ_ATT_NAME, ON_URL_ATT_NAME, REF_URL_ATT_NAME, STARTED_AT_ATT_NAME, CONN_COUNT_ATT_NAME, COLLECT_VER_ATT_NAME, CURRENT_NOIBUJS_VERSION, SCRIPT_ID_ATT_NAME, GET_SCRIPT_ID, SCRIPT_INSTANCE_ID_ATT_NAME, METROPLEX_SOCKET_INSTANCE_ID_ATT_NAME, SOCKET_INSTANCE_ID_ATT_NAME, VIDEO_RECORDER_ATT_NAME, META_DATA_METROPLEX_TYPE, PAGE_VISIT_META_DATA_ATT_NAME, MAX_RETRY_MSG_Q_SIZE } from '../constants.js';
|
|
6
6
|
import ClientConfig from './clientConfig.js';
|
|
7
7
|
import StoredMetrics from './storedMetrics.js';
|
|
8
8
|
import StoredPageVisit from './storedPageVisit.js';
|
|
@@ -10,15 +10,39 @@ import { safePerformanceNow } from '../utils/performance.js';
|
|
|
10
10
|
import { isDateOverwritten } from '../utils/date.js';
|
|
11
11
|
import { unwrapNoibuWrapped } from '../utils/object.js';
|
|
12
12
|
import { noibuLog } from '../utils/log.js';
|
|
13
|
+
import { Singleton } from '../monitors/BaseMonitor.js';
|
|
13
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Implements rolling window of specified size,
|
|
17
|
+
* but only makes a cut once array length exceeds 150%.
|
|
18
|
+
* During downsize deletes oldest (lowest indexes) elements.
|
|
19
|
+
*/
|
|
20
|
+
function createSlidingArrayOfSize(size, arraySource = [], downsizeThreshold = 1.5, downsizeFactor = 2) {
|
|
21
|
+
return new Proxy(arraySource, {
|
|
22
|
+
/**
|
|
23
|
+
* override push to implement sliding window
|
|
24
|
+
*/
|
|
25
|
+
get(target, p) {
|
|
26
|
+
if (p === 'push') {
|
|
27
|
+
return (...args) => {
|
|
28
|
+
target.push(...args);
|
|
29
|
+
if (target.length >= downsizeThreshold * size) {
|
|
30
|
+
target.splice(0, size / downsizeFactor);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return target[p];
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
14
38
|
/** Manages the socket to Metroplex */
|
|
15
|
-
class MetroplexSocket {
|
|
39
|
+
class MetroplexSocket extends Singleton {
|
|
16
40
|
/**
|
|
17
41
|
* Creates an instance of metroplex
|
|
18
42
|
* id of script, to make sure only a single socket is open
|
|
19
43
|
*/
|
|
20
44
|
constructor(scriptInstanceId) {
|
|
21
|
-
|
|
45
|
+
super();
|
|
22
46
|
// this flag is set to true when we manually need to close the
|
|
23
47
|
// socket. It happens currently during the pagehide event and
|
|
24
48
|
// if we havent sent a message to our backend in some time.
|
|
@@ -33,12 +57,13 @@ class MetroplexSocket {
|
|
|
33
57
|
this.currentConnectionAttempts = 0;
|
|
34
58
|
// how many successful connections to metroplex
|
|
35
59
|
this.connectionCount = 0;
|
|
36
|
-
//
|
|
60
|
+
// session start time, used to calculate accurate end time
|
|
37
61
|
this.sessionStartTime = safePerformanceNow();
|
|
62
|
+
this.connectionPromise = null;
|
|
38
63
|
// Whether or not we have sent the page visit information after connecting the socket
|
|
39
64
|
this.pageVisitInfoSent = false;
|
|
40
65
|
// socket connection url
|
|
41
|
-
this.connectionURL = `${
|
|
66
|
+
this.connectionURL = `${GET_METROPLEX_BASE_SOCKET_URL()}/${METROPLEX_FRAG_ROUTE}`;
|
|
42
67
|
// post endpoint for the same events we would send to the socket
|
|
43
68
|
this.postURL = GET_METROPLEX_POST_URL();
|
|
44
69
|
// sequence number of the message sent to metroplex
|
|
@@ -47,25 +72,20 @@ class MetroplexSocket {
|
|
|
47
72
|
this.latestReceivedSeqNumber = -1;
|
|
48
73
|
// set to true only when we start running behind on messages in metroplex
|
|
49
74
|
this.isRetryLoopDisabled = false;
|
|
50
|
-
|
|
51
|
-
this.retryMessageQueue =
|
|
75
|
+
/** messages that need to be resent to metroplex since they are lacking confirmation */
|
|
76
|
+
this.retryMessageQueue = createSlidingArrayOfSize(MAX_RETRY_MSG_Q_SIZE);
|
|
52
77
|
// this map will hold all types that noibujs should not send to metroplex
|
|
53
78
|
this.metroplexTypeLock = {};
|
|
54
79
|
// setting initial URL at the start in order to guarentee that the
|
|
55
80
|
// current page visit has the real initial onURL. Fragments and SPA's
|
|
56
81
|
// can change the URL without reloading the page.
|
|
57
|
-
this.
|
|
58
|
-
|
|
59
|
-
initialURL: this._initialURL,
|
|
60
|
-
});
|
|
61
|
-
this.initialReferingURL = '';
|
|
82
|
+
this.initialURL = ClientConfig.getInstance().globalUrl;
|
|
83
|
+
this.initialReferringURL = '';
|
|
62
84
|
this.sessionTimestamp = new Date();
|
|
63
85
|
// latest time that we received a confirmation message from metroplex
|
|
64
86
|
this.latestReceivedSeqNumStoredTime = new Date();
|
|
65
87
|
// unique instance id of Metroplex Socket
|
|
66
88
|
this.instanceId = uuid.v4();
|
|
67
|
-
// unique script instance id
|
|
68
|
-
this.scriptInstanceId = scriptInstanceId;
|
|
69
89
|
// length of the session based on page visit events
|
|
70
90
|
this.sessionLength = 0;
|
|
71
91
|
// track socket closure codes for debug
|
|
@@ -76,51 +96,30 @@ class MetroplexSocket {
|
|
|
76
96
|
this.ackedOnce = false;
|
|
77
97
|
// retry frequency in ms
|
|
78
98
|
this.metroRetryFrequencyMS = METROPLEX_RETRY_FREQUENCY;
|
|
79
|
-
this.helpCodeCb = null;
|
|
80
99
|
this.retryMetroplexInterval = null;
|
|
100
|
+
this.helpCodeCb = null;
|
|
101
|
+
noibuLog('Metroplex constructor', {
|
|
102
|
+
initialURL: this.initialURL,
|
|
103
|
+
scriptInstanceId,
|
|
104
|
+
});
|
|
105
|
+
this.scriptInstanceId = scriptInstanceId;
|
|
81
106
|
// Connect the WS
|
|
82
107
|
this.connectionPromise = this.connectSocket();
|
|
83
108
|
// Set up the offload events immediately
|
|
84
109
|
this._setupOffloadEvents();
|
|
85
110
|
}
|
|
86
|
-
/**
|
|
87
|
-
* gets the singleton instance
|
|
88
|
-
* @returns {MetroplexSocket}
|
|
89
|
-
*/
|
|
90
|
-
static getInstance(scriptInstanceId) {
|
|
91
|
-
if (!this.instance) {
|
|
92
|
-
this.instance = new MetroplexSocket(scriptInstanceId);
|
|
93
|
-
}
|
|
94
|
-
return this.instance;
|
|
95
|
-
}
|
|
96
111
|
/**
|
|
97
112
|
* Adds the seq num field to the given payload depending on whether its
|
|
98
113
|
* a page visit part or video frag
|
|
99
114
|
*/
|
|
100
115
|
_addSeqNumToPayload(type, payload) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
this._setSeqNumInPayloadAndIncrementSeqNum(PAGE_VISIT_VID_FRAG_ATT_NAME, payload);
|
|
107
|
-
break;
|
|
108
|
-
case HTTP_DATA_METROPLEX_TYPE:
|
|
109
|
-
this._setSeqNumInPayloadAndIncrementSeqNum(PAGE_VISIT_HTTP_DATA_ATT_NAME, payload);
|
|
110
|
-
break;
|
|
111
|
-
case META_DATA_METROPLEX_TYPE:
|
|
112
|
-
this._setSeqNumInPayloadAndIncrementSeqNum(PAGE_VISIT_META_DATA_ATT_NAME, payload);
|
|
113
|
-
break;
|
|
116
|
+
const newPayload = Object.assign({}, payload);
|
|
117
|
+
const key = MetroplexSocket.typeToPayloadPropMap[type];
|
|
118
|
+
if (key) {
|
|
119
|
+
newPayload[key][SEQ_NUM_ATT_NAME] = this.messageSequenceNum;
|
|
120
|
+
this.messageSequenceNum += 1;
|
|
114
121
|
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* sets the seq num in the payload for the given key and increments the
|
|
118
|
-
* global seq number
|
|
119
|
-
*/
|
|
120
|
-
_setSeqNumInPayloadAndIncrementSeqNum(payloadKey, payload) {
|
|
121
|
-
// eslint-disable-next-line no-param-reassign
|
|
122
|
-
payload[payloadKey][SEQ_NUM_ATT_NAME] = this.messageSequenceNum;
|
|
123
|
-
this.messageSequenceNum += 1;
|
|
122
|
+
return newPayload;
|
|
124
123
|
}
|
|
125
124
|
/** requests help code and saves a callback to be called on response */
|
|
126
125
|
requestHelpCode(cb) {
|
|
@@ -136,7 +135,7 @@ class MetroplexSocket {
|
|
|
136
135
|
*/
|
|
137
136
|
sendMessage(type, payload) {
|
|
138
137
|
return __awaiter(this, void 0, void 0, function* () {
|
|
139
|
-
noibuLog('sendMessage start', { type
|
|
138
|
+
noibuLog('sendMessage start', { type });
|
|
140
139
|
// if we have a lock on this specific type, we dont send it
|
|
141
140
|
if (type in this.metroplexTypeLock ||
|
|
142
141
|
ClientConfig.getInstance().isClientDisabled) {
|
|
@@ -146,19 +145,18 @@ class MetroplexSocket {
|
|
|
146
145
|
});
|
|
147
146
|
return false;
|
|
148
147
|
}
|
|
149
|
-
const payloadData = payload;
|
|
150
148
|
if (type !== WORK_REQUEST_ATT_NAME) {
|
|
151
149
|
// Increasing the message sequence number for every message we send to metroplex
|
|
152
150
|
// and move the data to the retry queue.
|
|
153
|
-
this._addSeqNumToPayload(type,
|
|
151
|
+
this._addSeqNumToPayload(type, payload);
|
|
154
152
|
// push the message to the retry queue immediately in case socket isnt connected
|
|
155
|
-
this.retryMessageQueue.push({ payload
|
|
153
|
+
this.retryMessageQueue.push({ payload, type });
|
|
156
154
|
StoredPageVisit.getInstance().checkAndStoreRetryQueue(this.retryMessageQueue, yield this.getPageInformation());
|
|
157
155
|
}
|
|
158
156
|
// send the socket message if we are connected and have sent page visit info
|
|
159
157
|
if (this.isConnected() && this.pageVisitInfoSent) {
|
|
160
158
|
// sending the data to metroplex
|
|
161
|
-
yield this._sendSocketMessage(
|
|
159
|
+
yield this._sendSocketMessage(payload);
|
|
162
160
|
}
|
|
163
161
|
this.previousMessageType = type;
|
|
164
162
|
// Only update the last message send if its a page visit with user action
|
|
@@ -256,7 +254,7 @@ class MetroplexSocket {
|
|
|
256
254
|
// if we tried reconnecting too many times we abandon
|
|
257
255
|
if (this.connectionCount >= MAX_METROPLEX_CONNECTION_COUNT) {
|
|
258
256
|
// if we tried beyond the threshold, we block ourselves a short
|
|
259
|
-
// while
|
|
257
|
+
// while fix the issue
|
|
260
258
|
yield ClientConfig.getInstance().lockClientUntilNextPage('Too many connections, locking until next page');
|
|
261
259
|
return;
|
|
262
260
|
}
|
|
@@ -355,6 +353,9 @@ class MetroplexSocket {
|
|
|
355
353
|
// we do nothing on an OK
|
|
356
354
|
break;
|
|
357
355
|
default:
|
|
356
|
+
if (!event.data) {
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
358
359
|
// we now need to check if we receive text that contains
|
|
359
360
|
// the text SEQ_NUM. if that is true, then its a seq num
|
|
360
361
|
// and we need to clear out the retry queue.
|
|
@@ -409,8 +410,9 @@ class MetroplexSocket {
|
|
|
409
410
|
*/
|
|
410
411
|
_clearRetryQueue(seqNum) {
|
|
411
412
|
this.latestReceivedSeqNumStoredTime = new Date();
|
|
412
|
-
|
|
413
|
+
const newQueue = this.retryMessageQueue.filter(message => this._messagePayloadHasLargerSeqNum(message, PAGE_VISIT_PART_ATT_NAME, seqNum) ||
|
|
413
414
|
this._messagePayloadHasLargerSeqNum(message, PAGE_VISIT_VID_FRAG_ATT_NAME, seqNum));
|
|
415
|
+
this.retryMessageQueue = createSlidingArrayOfSize(MAX_RETRY_MSG_Q_SIZE, newQueue);
|
|
414
416
|
}
|
|
415
417
|
/** will resend everything that is in the retry queue */
|
|
416
418
|
_sendUnconfirmedMessages(socketWasAlreadyOpen) {
|
|
@@ -622,7 +624,9 @@ class MetroplexSocket {
|
|
|
622
624
|
return;
|
|
623
625
|
}
|
|
624
626
|
const payloadJson = stringifyJSON(payload);
|
|
625
|
-
noibuLog(`_sendSocketMessage sending: ${
|
|
627
|
+
noibuLog(`_sendSocketMessage sending: ${PAGE_VISIT_VID_FRAG_ATT_NAME in payload
|
|
628
|
+
? PAGE_VISIT_VID_FRAG_ATT_NAME
|
|
629
|
+
: payloadJson}`);
|
|
626
630
|
if (this.socket) {
|
|
627
631
|
this.socket.send(payloadJson);
|
|
628
632
|
}
|
|
@@ -642,12 +646,10 @@ class MetroplexSocket {
|
|
|
642
646
|
// the next page is loaded.
|
|
643
647
|
yield ClientConfig.getInstance().lockClientUntilNextPage('Session is inactive, locking until next page');
|
|
644
648
|
this.close();
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
this.postFullPageVisit(MAX_BEACON_PAYLOAD_SIZE),
|
|
650
|
-
]);
|
|
649
|
+
// post metrics now so we don't include events after going inactive
|
|
650
|
+
StoredMetrics.getInstance().postMetrics();
|
|
651
|
+
// post retry queue now so we don't include event after going inactive
|
|
652
|
+
this.postFullPageVisit(MAX_BEACON_PAYLOAD_SIZE);
|
|
651
653
|
}
|
|
652
654
|
return inactive;
|
|
653
655
|
});
|
|
@@ -660,8 +662,8 @@ class MetroplexSocket {
|
|
|
660
662
|
[PV_ID_ATT_NAME]: ClientConfig.getInstance().pageVisitId,
|
|
661
663
|
[VER_ATT_NAME]: CURRENT_PV_VERSION,
|
|
662
664
|
[PV_SEQ_ATT_NAME]: yield ClientConfig.getInstance().getPageVisitSeq(),
|
|
663
|
-
[ON_URL_ATT_NAME]: this.
|
|
664
|
-
[REF_URL_ATT_NAME]: this.
|
|
665
|
+
[ON_URL_ATT_NAME]: this.initialURL,
|
|
666
|
+
[REF_URL_ATT_NAME]: this.initialReferringURL,
|
|
665
667
|
[STARTED_AT_ATT_NAME]: this.sessionTimestamp.toISOString(),
|
|
666
668
|
[CONN_COUNT_ATT_NAME]: this.connectionCount,
|
|
667
669
|
[COLLECT_VER_ATT_NAME]: CURRENT_NOIBUJS_VERSION,
|
|
@@ -676,7 +678,6 @@ class MetroplexSocket {
|
|
|
676
678
|
}
|
|
677
679
|
/**
|
|
678
680
|
* Try to parse help code response and fire custom event
|
|
679
|
-
* @param {String} response
|
|
680
681
|
*/
|
|
681
682
|
_tryProcessHelpCodeResponse(response) {
|
|
682
683
|
const prefix = `${HELP_CODE_ATT_NAME}:`;
|
|
@@ -691,5 +692,11 @@ class MetroplexSocket {
|
|
|
691
692
|
return true;
|
|
692
693
|
}
|
|
693
694
|
}
|
|
695
|
+
MetroplexSocket.typeToPayloadPropMap = {
|
|
696
|
+
[HTTP_DATA_METROPLEX_TYPE]: PAGE_VISIT_HTTP_DATA_ATT_NAME,
|
|
697
|
+
[META_DATA_METROPLEX_TYPE]: PAGE_VISIT_META_DATA_ATT_NAME,
|
|
698
|
+
[PV_METROPLEX_TYPE]: PAGE_VISIT_PART_ATT_NAME,
|
|
699
|
+
[VIDEO_METROPLEX_TYPE]: PAGE_VISIT_VID_FRAG_ATT_NAME,
|
|
700
|
+
};
|
|
694
701
|
|
|
695
|
-
export { MetroplexSocket as default };
|
|
702
|
+
export { createSlidingArrayOfSize, MetroplexSocket as default };
|