noibu-react-native 0.2.6 → 0.2.7
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/README.md +15 -15
- package/dist/api/{clientConfig.js → ClientConfig.js} +69 -52
- package/dist/api/{helpCode.js → HelpCode.js} +6 -13
- package/dist/api/InputManager.js +156 -0
- package/dist/api/{metroplexSocket.js → MetroplexSocket.js} +189 -178
- package/dist/api/StoredMetrics.js +158 -0
- package/dist/api/{storedPageVisit.js → StoredPageVisit.js} +61 -48
- package/dist/const_matchers.js +1 -5
- package/dist/constants.js +15 -390
- package/dist/entry/index.js +3 -4
- package/dist/entry/init.js +33 -19
- package/dist/monitors/AppNavigationMonitor.js +19 -19
- package/dist/monitors/BaseMonitor.js +9 -4
- package/dist/monitors/ClickMonitor.js +72 -76
- package/dist/monitors/ErrorMonitor.js +45 -55
- package/dist/monitors/KeyboardInputMonitor.js +13 -11
- package/dist/monitors/PageMonitor.js +25 -2
- package/dist/monitors/RequestMonitor.js +46 -57
- package/dist/monitors/http-tools/GqlErrorValidator.js +39 -69
- package/dist/monitors/http-tools/HTTPDataBundler.js +71 -66
- package/dist/monitors/integrations/{react-native-navigation-integration.js → ReactNativeNavigationIntegration.js} +15 -12
- package/dist/pageVisit/EventDebouncer.js +43 -74
- package/dist/pageVisit/HttpEventManager.js +88 -0
- package/dist/pageVisit/PageVisitManager.js +99 -0
- package/dist/pageVisit/pageVisitEventError.js +170 -280
- package/dist/react/ErrorBoundary.js +3 -6
- package/dist/sessionRecorder/{sessionRecorder.js → SessionRecorder.js} +58 -70
- package/dist/sessionRecorder/nativeSessionRecorderSubscription.js +3 -5
- package/dist/storage/{rnStorageProvider.js → RNStorageProvider.js} +3 -7
- package/dist/storage/{storage.js → Storage.js} +17 -30
- package/dist/storage/{storageProvider.js → StorageProvider.js} +7 -8
- package/dist/utils/date.js +39 -50
- package/dist/utils/eventlistener.js +5 -12
- package/dist/utils/function.js +42 -113
- package/dist/utils/log.js +5 -5
- package/dist/utils/object.js +12 -12
- package/dist/utils/piiRedactor.js +31 -3
- package/dist/utils/stacktrace-parser.js +29 -21
- package/package.json +14 -14
- package/dist/api/inputManager.js +0 -227
- package/dist/api/storedMetrics.js +0 -198
- package/dist/pageVisit/pageVisit.js +0 -181
- package/dist/pageVisit/pageVisitEventHTTP.js +0 -98
- package/dist/pageVisit/userStep.js +0 -20
- package/dist/src/api/clientConfig.d.ts +0 -100
- package/dist/src/api/clientConfig.test.d.ts +0 -1
- package/dist/src/api/helpCode.d.ts +0 -23
- package/dist/src/api/inputManager.d.ts +0 -87
- package/dist/src/api/metroplexSocket.d.ts +0 -137
- package/dist/src/api/storedMetrics.d.ts +0 -73
- package/dist/src/api/storedPageVisit.d.ts +0 -40
- package/dist/src/const_matchers.d.ts +0 -1
- package/dist/src/constants.d.ts +0 -290
- package/dist/src/entry/index.d.ts +0 -14
- package/dist/src/entry/init.d.ts +0 -5
- package/dist/src/monitors/AppNavigationMonitor.d.ts +0 -18
- package/dist/src/monitors/BaseMonitor.d.ts +0 -13
- package/dist/src/monitors/BaseMonitor.test.d.ts +0 -1
- package/dist/src/monitors/ClickMonitor.d.ts +0 -31
- package/dist/src/monitors/ErrorMonitor.d.ts +0 -63
- package/dist/src/monitors/KeyboardInputMonitor.d.ts +0 -20
- package/dist/src/monitors/PageMonitor.d.ts +0 -20
- package/dist/src/monitors/RequestMonitor.d.ts +0 -94
- package/dist/src/monitors/http-tools/GqlErrorValidator.d.ts +0 -59
- package/dist/src/monitors/http-tools/HTTPDataBundler.d.ts +0 -112
- package/dist/src/monitors/integrations/react-native-navigation-integration.d.ts +0 -20
- package/dist/src/pageVisit/EventDebouncer.d.ts +0 -24
- package/dist/src/pageVisit/pageVisit.d.ts +0 -52
- package/dist/src/pageVisit/pageVisitEventError.d.ts +0 -15
- package/dist/src/pageVisit/pageVisitEventHTTP.d.ts +0 -25
- package/dist/src/pageVisit/userStep.d.ts +0 -5
- package/dist/src/react/ErrorBoundary.d.ts +0 -72
- package/dist/src/sessionRecorder/nativeSessionRecorderSubscription.d.ts +0 -79
- package/dist/src/sessionRecorder/sessionRecorder.d.ts +0 -60
- package/dist/src/sessionRecorder/types.d.ts +0 -91
- package/dist/src/storage/rnStorageProvider.d.ts +0 -23
- package/dist/src/storage/storage.d.ts +0 -39
- package/dist/src/storage/storageProvider.d.ts +0 -26
- package/dist/src/utils/date.d.ts +0 -6
- package/dist/src/utils/eventlistener.d.ts +0 -8
- package/dist/src/utils/function.d.ts +0 -102
- package/dist/src/utils/log.d.ts +0 -4
- package/dist/src/utils/object.d.ts +0 -44
- package/dist/src/utils/performance.d.ts +0 -6
- package/dist/src/utils/piiRedactor.d.ts +0 -11
- package/dist/src/utils/polyfills.d.ts +0 -4
- package/dist/src/utils/stacktrace-parser.d.ts +0 -7
- package/dist/types/Config.d.ts +0 -31
- package/dist/types/Metroplex.types.d.ts +0 -73
- package/dist/types/NavigationIntegration.d.ts +0 -6
- package/dist/types/PageVisit.types.d.ts +0 -8
- package/dist/types/PageVisitErrors.types.d.ts +0 -114
- package/dist/types/PageVisitEvents.types.d.ts +0 -91
- package/dist/types/PageVisitMetrics.types.d.ts +0 -27
- package/dist/types/Storage.d.ts +0 -14
- package/dist/types/StoredPageVisit.types.d.ts +0 -11
- package/dist/types/WrappedObjects.d.ts +0 -6
|
@@ -1,17 +1,37 @@
|
|
|
1
1
|
import { __awaiter } from 'tslib';
|
|
2
2
|
import uuid from 'react-native-uuid';
|
|
3
|
-
import {
|
|
3
|
+
import { Platform } from 'react-native';
|
|
4
|
+
import { MetroplexRoute } from '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
|
|
5
|
+
import { getUserAgent, stringifyJSON } from '../utils/function.js';
|
|
4
6
|
import { addSafeEventListener } from '../utils/eventlistener.js';
|
|
5
|
-
import { GET_METROPLEX_BASE_SOCKET_URL,
|
|
6
|
-
import ClientConfig from './
|
|
7
|
-
import StoredMetrics from './
|
|
8
|
-
import StoredPageVisit from './
|
|
7
|
+
import { GET_METROPLEX_BASE_SOCKET_URL, GET_METROPLEX_POST_URL, GET_MAX_METROPLEX_RECONNECTION_NUMBER, GET_METROPLEX_CONSECUTIVE_CONNECTION_DELAY, SEVERITY, MAX_BEACON_PAYLOAD_SIZE, CURRENT_NOIBUJS_VERSION, GET_SCRIPT_ID } from '../constants.js';
|
|
8
|
+
import ClientConfig from './ClientConfig.js';
|
|
9
|
+
import StoredMetrics from './StoredMetrics.js';
|
|
10
|
+
import StoredPageVisit from './StoredPageVisit.js';
|
|
9
11
|
import { safePerformanceNow } from '../utils/performance.js';
|
|
10
12
|
import { isDateOverwritten } from '../utils/date.js';
|
|
11
13
|
import { unwrapNoibuWrapped } from '../utils/object.js';
|
|
12
14
|
import { noibuLog } from '../utils/log.js';
|
|
13
15
|
import { Singleton } from '../monitors/BaseMonitor.js';
|
|
16
|
+
import { WebsocketMessageType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/WebsocketMessageType.js';
|
|
17
|
+
import { WorkRequestMessageType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/WorkRequestMessageType.js';
|
|
18
|
+
import { EventType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/EventType.js';
|
|
19
|
+
import { InboundMessageType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/InboundMessageType.js';
|
|
14
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Grab the video recorder type based on the device we run the app on.
|
|
23
|
+
*/
|
|
24
|
+
function getVideoRecorderType() {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
if (Platform.OS === 'android') {
|
|
27
|
+
return 'AndroidNative';
|
|
28
|
+
}
|
|
29
|
+
if (Platform.OS === 'ios') {
|
|
30
|
+
return 'IOSNative';
|
|
31
|
+
}
|
|
32
|
+
return 'RRWeb'; // should never happen
|
|
33
|
+
});
|
|
34
|
+
}
|
|
15
35
|
/**
|
|
16
36
|
* Implements rolling window of specified size,
|
|
17
37
|
* but only makes a cut once array length exceeds 150%.
|
|
@@ -35,6 +55,13 @@ function createSlidingArrayOfSize(size, arraySource = [], downsizeThreshold = 1.
|
|
|
35
55
|
},
|
|
36
56
|
});
|
|
37
57
|
}
|
|
58
|
+
// gets the frequency at which the client resends the message that were not confirmed by metroplex
|
|
59
|
+
const METROPLEX_RETRY_FREQUENCY = 30000;
|
|
60
|
+
// current PageVisitManager version to be sent from front end services
|
|
61
|
+
const CURRENT_PV_VERSION = 5;
|
|
62
|
+
// maximum number of connection a single page visit can reach
|
|
63
|
+
const MAX_METROPLEX_CONNECTION_COUNT = 100;
|
|
64
|
+
const MAX_RETRY_MSG_Q_SIZE = 500;
|
|
38
65
|
/** Manages the socket to Metroplex */
|
|
39
66
|
class MetroplexSocket extends Singleton {
|
|
40
67
|
/**
|
|
@@ -59,11 +86,10 @@ class MetroplexSocket extends Singleton {
|
|
|
59
86
|
this.connectionCount = 0;
|
|
60
87
|
// session start time, used to calculate accurate end time
|
|
61
88
|
this.sessionStartTime = safePerformanceNow();
|
|
62
|
-
|
|
63
|
-
// Whether or not we have sent the page visit information after connecting the socket
|
|
89
|
+
// Whether we have sent the page visit information after connecting the socket
|
|
64
90
|
this.pageVisitInfoSent = false;
|
|
65
91
|
// socket connection url
|
|
66
|
-
this.connectionURL = `${GET_METROPLEX_BASE_SOCKET_URL()}/${
|
|
92
|
+
this.connectionURL = `${GET_METROPLEX_BASE_SOCKET_URL()}/${MetroplexRoute.PageVisitPart}`;
|
|
67
93
|
// post endpoint for the same events we would send to the socket
|
|
68
94
|
this.postURL = GET_METROPLEX_POST_URL();
|
|
69
95
|
// sequence number of the message sent to metroplex
|
|
@@ -98,75 +124,91 @@ class MetroplexSocket extends Singleton {
|
|
|
98
124
|
this.metroRetryFrequencyMS = METROPLEX_RETRY_FREQUENCY;
|
|
99
125
|
this.retryMetroplexInterval = null;
|
|
100
126
|
this.helpCodeCb = null;
|
|
101
|
-
noibuLog('Metroplex constructor', {
|
|
102
|
-
initialURL: this.initialURL,
|
|
103
|
-
scriptInstanceId,
|
|
104
|
-
});
|
|
127
|
+
noibuLog('Metroplex constructor', { initialURL: this.initialURL, scriptInstanceId });
|
|
105
128
|
this.scriptInstanceId = scriptInstanceId;
|
|
106
|
-
// Connect the WS
|
|
107
129
|
this.connectionPromise = this.connectSocket();
|
|
108
130
|
// Set up the offload events immediately
|
|
109
131
|
this._setupOffloadEvents();
|
|
110
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* connectSocket will establish a websocket connection to the metroplex
|
|
135
|
+
* service
|
|
136
|
+
*/
|
|
137
|
+
connectSocket() {
|
|
138
|
+
if (this.isConnected() || this.isConnecting()) {
|
|
139
|
+
// self resolving promise since we are already ready to send
|
|
140
|
+
// requests, if we did reach state 1, we already sent initial
|
|
141
|
+
// request, thus not sending it again.
|
|
142
|
+
return this.connectionPromise;
|
|
143
|
+
}
|
|
144
|
+
// we return a promisified socket resolver to be able to chain the
|
|
145
|
+
// opening of the socket
|
|
146
|
+
return this.handleConnect(false);
|
|
147
|
+
}
|
|
148
|
+
/** sets up events that will trigger the event queue to be emptied */
|
|
149
|
+
_setupOffloadEvents() {
|
|
150
|
+
// when the page hides we try getting all the events
|
|
151
|
+
// and empty the event and retry queue.
|
|
152
|
+
addSafeEventListener(window, 'pagehide', () => this._handleUnload(), false);
|
|
153
|
+
}
|
|
111
154
|
/**
|
|
112
155
|
* Adds the seq num field to the given payload depending on whether its
|
|
113
156
|
* a page visit part or video frag
|
|
114
157
|
*/
|
|
115
|
-
_addSeqNumToPayload(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
158
|
+
_addSeqNumToPayload(message) {
|
|
159
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
160
|
+
const { type, payload } = message;
|
|
161
|
+
/**
|
|
162
|
+
* Increasing the message sequence number for every message we send to metroplex
|
|
163
|
+
* and move the data to the retry queue.
|
|
164
|
+
*/
|
|
120
165
|
this.messageSequenceNum += 1;
|
|
121
|
-
|
|
122
|
-
|
|
166
|
+
const newMessage = {
|
|
167
|
+
type,
|
|
168
|
+
payload: Object.assign(Object.assign({}, payload), { seq_num: this.messageSequenceNum }),
|
|
169
|
+
};
|
|
170
|
+
/** push the message to the retry queue immediately in case socket isnt connected */
|
|
171
|
+
this.retryMessageQueue.push(newMessage);
|
|
172
|
+
StoredPageVisit.getInstance().checkAndStoreRetryQueue(this.retryMessageQueue, yield this.getPageInformation());
|
|
173
|
+
return newMessage;
|
|
174
|
+
});
|
|
123
175
|
}
|
|
124
176
|
/** requests help code and saves a callback to be called on response */
|
|
125
177
|
requestHelpCode(cb) {
|
|
126
178
|
this.helpCodeCb = cb;
|
|
127
|
-
return
|
|
128
|
-
[WORK_REQUEST_ATT_NAME]: HELP_CODE_ATT_NAME,
|
|
129
|
-
});
|
|
179
|
+
return this.sendMessage({ type: WebsocketMessageType.WorkRequest, payload: WorkRequestMessageType.HelpCode });
|
|
130
180
|
}
|
|
131
181
|
/**
|
|
132
182
|
* Immediately sends a message to Metroplex over the web socket
|
|
133
183
|
* Queues the message if the connection isn't open yet.
|
|
134
184
|
* returns true if message was sent succefully, false otherwise
|
|
135
185
|
*/
|
|
136
|
-
sendMessage(
|
|
186
|
+
sendMessage(message) {
|
|
137
187
|
return __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
const { type } = message;
|
|
138
189
|
noibuLog('sendMessage start', { type });
|
|
139
190
|
// if we have a lock on this specific type, we dont send it
|
|
140
|
-
if (type
|
|
141
|
-
ClientConfig.getInstance().isClientDisabled) {
|
|
191
|
+
if (this.metroplexTypeLock[type] || ClientConfig.getInstance().isClientDisabled) {
|
|
142
192
|
noibuLog('sendMessage quitting due to', {
|
|
143
|
-
typeInLock: type
|
|
193
|
+
typeInLock: this.metroplexTypeLock[type] ? `${type} locked` : false,
|
|
144
194
|
isClientDisabled: ClientConfig.getInstance().isClientDisabled,
|
|
145
195
|
});
|
|
146
196
|
return false;
|
|
147
197
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
this._addSeqNumToPayload(type, payload);
|
|
152
|
-
// push the message to the retry queue immediately in case socket isnt connected
|
|
153
|
-
this.retryMessageQueue.push({ payload, type });
|
|
154
|
-
StoredPageVisit.getInstance().checkAndStoreRetryQueue(this.retryMessageQueue, yield this.getPageInformation());
|
|
155
|
-
}
|
|
198
|
+
const withSeqNum = type === WebsocketMessageType.WorkRequest
|
|
199
|
+
? message
|
|
200
|
+
: yield this._addSeqNumToPayload(message);
|
|
156
201
|
// send the socket message if we are connected and have sent page visit info
|
|
157
202
|
if (this.isConnected() && this.pageVisitInfoSent) {
|
|
158
203
|
// sending the data to metroplex
|
|
159
|
-
yield this.
|
|
204
|
+
yield this.sendSocketMessage({ [withSeqNum.type]: withSeqNum.payload });
|
|
160
205
|
}
|
|
161
206
|
this.previousMessageType = type;
|
|
162
207
|
// Only update the last message send if its a page visit with user action
|
|
163
208
|
// ensure this is done regardless of whether socket is connected or not,
|
|
164
209
|
// so that pagehide will post PV if user is active but socket is not
|
|
165
|
-
if (type ===
|
|
166
|
-
|
|
167
|
-
? payload[PAGE_VISIT_PART_ATT_NAME][PV_EVENTS_ATT_NAME]
|
|
168
|
-
: [];
|
|
169
|
-
yield this._updateLatestPvTimestamp(events);
|
|
210
|
+
if (withSeqNum.type === WebsocketMessageType.PageVisitPart) {
|
|
211
|
+
yield this._updateLatestPvTimestamp(withSeqNum.payload.events || []);
|
|
170
212
|
}
|
|
171
213
|
return true;
|
|
172
214
|
});
|
|
@@ -175,7 +217,7 @@ class MetroplexSocket extends Singleton {
|
|
|
175
217
|
*/
|
|
176
218
|
_updateLatestPvTimestamp(events) {
|
|
177
219
|
return __awaiter(this, void 0, void 0, function* () {
|
|
178
|
-
const userstepsEvents = events.filter(ev => ev
|
|
220
|
+
const userstepsEvents = events.filter(ev => ev.type === EventType.UserStep);
|
|
179
221
|
if (userstepsEvents.length > 0) {
|
|
180
222
|
yield ClientConfig.getInstance().updateLastActiveTime(new Date());
|
|
181
223
|
}
|
|
@@ -244,18 +286,21 @@ class MetroplexSocket extends Singleton {
|
|
|
244
286
|
clearInterval(this.retryMetroplexInterval);
|
|
245
287
|
}
|
|
246
288
|
// if we tried reconnecting too many times we abandon
|
|
247
|
-
if (this.currentConnectionAttempts >=
|
|
248
|
-
GET_MAX_METROPLEX_RECONNECTION_NUMBER()) {
|
|
289
|
+
if (this.currentConnectionAttempts >= GET_MAX_METROPLEX_RECONNECTION_NUMBER()) {
|
|
249
290
|
// if we tried beyond the threshold, we block ourselves a short
|
|
250
291
|
// while fix the issue
|
|
251
|
-
yield ClientConfig.getInstance().lockClientUntilNextPage(
|
|
292
|
+
yield ClientConfig.getInstance().lockClientUntilNextPage({
|
|
293
|
+
msg: 'Too many reconnection attempts, locking until next page',
|
|
294
|
+
});
|
|
252
295
|
return;
|
|
253
296
|
}
|
|
254
297
|
// if we tried reconnecting too many times we abandon
|
|
255
298
|
if (this.connectionCount >= MAX_METROPLEX_CONNECTION_COUNT) {
|
|
256
299
|
// if we tried beyond the threshold, we block ourselves a short
|
|
257
300
|
// while fix the issue
|
|
258
|
-
yield ClientConfig.getInstance().lockClientUntilNextPage(
|
|
301
|
+
yield ClientConfig.getInstance().lockClientUntilNextPage({
|
|
302
|
+
msg: 'Too many connections, locking until next page',
|
|
303
|
+
});
|
|
259
304
|
return;
|
|
260
305
|
}
|
|
261
306
|
// try to reconnect on close but after a certain delay based off unsuccessful connections
|
|
@@ -265,7 +310,7 @@ class MetroplexSocket extends Singleton {
|
|
|
265
310
|
});
|
|
266
311
|
// everytime we get a message from the socket
|
|
267
312
|
this.socket.onmessage = event => {
|
|
268
|
-
noibuLog('metroplex handleConnect, onmessage',
|
|
313
|
+
noibuLog('metroplex handleConnect, onmessage', event);
|
|
269
314
|
this._onSocketMessage(event);
|
|
270
315
|
};
|
|
271
316
|
// the moment we open the socket
|
|
@@ -276,32 +321,14 @@ class MetroplexSocket extends Singleton {
|
|
|
276
321
|
};
|
|
277
322
|
});
|
|
278
323
|
}
|
|
279
|
-
/**
|
|
280
|
-
* connectSocket will establish a websocket connection to the metroplex
|
|
281
|
-
* service
|
|
282
|
-
*/
|
|
283
|
-
connectSocket() {
|
|
284
|
-
if (this.isConnected() || this.isConnecting()) {
|
|
285
|
-
// self resolving promise since we are already ready to send
|
|
286
|
-
// requests, if we did reach state 1, we already sent initial
|
|
287
|
-
// request, thus not sending it again.
|
|
288
|
-
return this.connectionPromise;
|
|
289
|
-
}
|
|
290
|
-
// we return a promisified socket resolver to be able to chain the
|
|
291
|
-
// opening of the socket
|
|
292
|
-
return this.handleConnect(false);
|
|
293
|
-
}
|
|
294
|
-
/** Calculates and sets the end_at field of the payload
|
|
295
|
-
* @param {} payload
|
|
296
|
-
* @param {} isPageVisit
|
|
297
|
-
*/
|
|
324
|
+
/** Calculates and sets the end_at field of the payload */
|
|
298
325
|
addEndTimeToPayload(payload, isPageVisit) {
|
|
299
326
|
const delta = Math.ceil(safePerformanceNow() - this.sessionStartTime);
|
|
300
327
|
// update session length if this is a page visit event
|
|
301
328
|
if (isPageVisit) {
|
|
302
329
|
this.sessionLength = delta;
|
|
303
330
|
}
|
|
304
|
-
return Object.assign(Object.assign({}, payload), {
|
|
331
|
+
return Object.assign(Object.assign({}, payload), { end_at: new Date(this.sessionTimestamp.getTime() + delta).toISOString() });
|
|
305
332
|
}
|
|
306
333
|
/** open handler for socket */
|
|
307
334
|
_onSocketOpen() {
|
|
@@ -310,7 +337,7 @@ class MetroplexSocket extends Singleton {
|
|
|
310
337
|
if (!this.isConnected() || ClientConfig.getInstance().isClientDisabled) {
|
|
311
338
|
return;
|
|
312
339
|
}
|
|
313
|
-
yield this.
|
|
340
|
+
yield this.sendSocketMessage(yield this.getPageInformation());
|
|
314
341
|
// Set this to allow normal page visit and video frag messages to be sent
|
|
315
342
|
this.pageVisitInfoSent = true;
|
|
316
343
|
this.currentConnectionAttempts = 0;
|
|
@@ -324,32 +351,30 @@ class MetroplexSocket extends Singleton {
|
|
|
324
351
|
this.connectionCount += 1;
|
|
325
352
|
});
|
|
326
353
|
}
|
|
327
|
-
/** message handler for socket
|
|
328
|
-
* @param {} event
|
|
329
|
-
*/
|
|
354
|
+
/** message handler for socket */
|
|
330
355
|
_onSocketMessage(event) {
|
|
331
356
|
return __awaiter(this, void 0, void 0, function* () {
|
|
332
357
|
switch (event.data) {
|
|
333
|
-
case
|
|
358
|
+
case InboundMessageType.VideoBlock:
|
|
334
359
|
// stopping vids from being sent
|
|
335
|
-
this.metroplexTypeLock
|
|
360
|
+
this.metroplexTypeLock.pvvf = true;
|
|
336
361
|
StoredMetrics.getInstance().setDidCutVideo();
|
|
337
362
|
break;
|
|
338
|
-
case
|
|
363
|
+
case InboundMessageType.PageVisitBlock:
|
|
339
364
|
// stopping pv from being sent
|
|
340
|
-
this.metroplexTypeLock
|
|
365
|
+
this.metroplexTypeLock.pvp = true;
|
|
341
366
|
StoredMetrics.getInstance().setDidCutPv();
|
|
342
367
|
break;
|
|
343
|
-
case
|
|
368
|
+
case InboundMessageType.FullBlock:
|
|
344
369
|
// we are disabling collect for 1 day if we get the
|
|
345
370
|
// block message from metroplex. We are probably on it
|
|
346
|
-
yield ClientConfig.getInstance().lockClient(1440, 'Metroplex blocked script');
|
|
371
|
+
yield ClientConfig.getInstance().lockClient(1440, { msg: 'Metroplex blocked script' });
|
|
347
372
|
this.close();
|
|
348
373
|
break;
|
|
349
|
-
case
|
|
374
|
+
case InboundMessageType.CloseConnection:
|
|
350
375
|
this.close();
|
|
351
376
|
break;
|
|
352
|
-
case
|
|
377
|
+
case InboundMessageType.OK:
|
|
353
378
|
// we do nothing on an OK
|
|
354
379
|
break;
|
|
355
380
|
default:
|
|
@@ -359,10 +384,10 @@ class MetroplexSocket extends Singleton {
|
|
|
359
384
|
// we now need to check if we receive text that contains
|
|
360
385
|
// the text SEQ_NUM. if that is true, then its a seq num
|
|
361
386
|
// and we need to clear out the retry queue.
|
|
362
|
-
if (event.data.includes(
|
|
363
|
-
const seqNumSplit = event.data.split(
|
|
387
|
+
if (event.data.includes('seq_num')) {
|
|
388
|
+
const seqNumSplit = event.data.split('seq_num:');
|
|
364
389
|
if (seqNumSplit.length < 2) {
|
|
365
|
-
ClientConfig.getInstance().
|
|
390
|
+
ClientConfig.getInstance().postInternalError({ msg: `Invalid message received from metroplex while clearing retry queue`, data: event.data }, false, SEVERITY.error);
|
|
366
391
|
break;
|
|
367
392
|
}
|
|
368
393
|
// the second element in the string split is the sequence number
|
|
@@ -399,10 +424,8 @@ class MetroplexSocket extends Singleton {
|
|
|
399
424
|
* Returns true if the message's payload has the payload type given and has a sequence
|
|
400
425
|
* number higher than seqNum
|
|
401
426
|
*/
|
|
402
|
-
_messagePayloadHasLargerSeqNum(message,
|
|
403
|
-
return
|
|
404
|
-
message.payload[payloadType][SEQ_NUM_ATT_NAME] &&
|
|
405
|
-
message.payload[payloadType][SEQ_NUM_ATT_NAME] > seqNum);
|
|
427
|
+
_messagePayloadHasLargerSeqNum(message, seqNum) {
|
|
428
|
+
return message.payload && message.payload.seq_num && message.payload.seq_num > seqNum;
|
|
406
429
|
}
|
|
407
430
|
/**
|
|
408
431
|
* removes messages from the retry queue that are smaller than the
|
|
@@ -410,8 +433,7 @@ class MetroplexSocket extends Singleton {
|
|
|
410
433
|
*/
|
|
411
434
|
_clearRetryQueue(seqNum) {
|
|
412
435
|
this.latestReceivedSeqNumStoredTime = new Date();
|
|
413
|
-
const newQueue = this.retryMessageQueue.filter(message => this._messagePayloadHasLargerSeqNum(message,
|
|
414
|
-
this._messagePayloadHasLargerSeqNum(message, PAGE_VISIT_VID_FRAG_ATT_NAME, seqNum));
|
|
436
|
+
const newQueue = this.retryMessageQueue.filter(message => this._messagePayloadHasLargerSeqNum(message, seqNum));
|
|
415
437
|
this.retryMessageQueue = createSlidingArrayOfSize(MAX_RETRY_MSG_Q_SIZE, newQueue);
|
|
416
438
|
}
|
|
417
439
|
/** will resend everything that is in the retry queue */
|
|
@@ -438,13 +460,12 @@ class MetroplexSocket extends Singleton {
|
|
|
438
460
|
}
|
|
439
461
|
}
|
|
440
462
|
// removing all the messages with a blocked type from the retry queue
|
|
441
|
-
this.retryMessageQueue = this.retryMessageQueue.filter(message => !
|
|
463
|
+
this.retryMessageQueue = this.retryMessageQueue.filter(message => !this.metroplexTypeLock[message.type]);
|
|
442
464
|
// we dont remove any items from this queue in this function
|
|
443
465
|
for (let i = 0; i < this.retryMessageQueue.length; i += 1) {
|
|
444
466
|
const { type, payload } = this.retryMessageQueue[i];
|
|
445
467
|
// sending the data to metroplex
|
|
446
|
-
|
|
447
|
-
yield this._sendSocketMessage(payload);
|
|
468
|
+
yield this.sendSocketMessage({ [type]: payload });
|
|
448
469
|
this.previousMessageType = type;
|
|
449
470
|
}
|
|
450
471
|
});
|
|
@@ -455,12 +476,6 @@ class MetroplexSocket extends Singleton {
|
|
|
455
476
|
this._sendUnconfirmedMessages(true);
|
|
456
477
|
}, METROPLEX_RETRY_FREQUENCY);
|
|
457
478
|
}
|
|
458
|
-
/** sets up events that will trigger the event queue to be emptied */
|
|
459
|
-
_setupOffloadEvents() {
|
|
460
|
-
// when the page hides we try getting all the events
|
|
461
|
-
// and empty the event and retry queue.
|
|
462
|
-
addSafeEventListener(window, 'pagehide', () => this._handleUnload(), false);
|
|
463
|
-
}
|
|
464
479
|
/**
|
|
465
480
|
* will handle the final moments of a page being active. It
|
|
466
481
|
* will try to empty both the queues with beacons.
|
|
@@ -488,26 +503,29 @@ class MetroplexSocket extends Singleton {
|
|
|
488
503
|
*/
|
|
489
504
|
postFullPageVisit(maxMessageSize) {
|
|
490
505
|
return __awaiter(this, void 0, void 0, function* () {
|
|
506
|
+
var _a;
|
|
491
507
|
if (this.retryMessageQueue.length === 0) {
|
|
492
508
|
return;
|
|
493
509
|
}
|
|
494
510
|
// debug counters
|
|
495
511
|
const postInfo = [];
|
|
496
512
|
const numDropped = {
|
|
497
|
-
|
|
498
|
-
|
|
513
|
+
pvvf: 0,
|
|
514
|
+
pvp: 0,
|
|
515
|
+
pvh: 0,
|
|
499
516
|
};
|
|
500
517
|
let currentMsgPayloadSize = 0;
|
|
501
518
|
let currentCompletePv = {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
519
|
+
pvi: yield this.getPageInformation(),
|
|
520
|
+
pvp: [],
|
|
521
|
+
pvvf: [],
|
|
522
|
+
pvh: [],
|
|
523
|
+
vpnum: this.connectionCount,
|
|
507
524
|
};
|
|
508
|
-
currentCompletePv
|
|
525
|
+
currentCompletePv.pvi.last = true;
|
|
509
526
|
const pageInfo = yield this.getPageInformation();
|
|
510
527
|
this.retryMessageQueue.forEach(msg => {
|
|
528
|
+
var _a, _b, _c;
|
|
511
529
|
// can't use two variables types in obj deconstruction
|
|
512
530
|
// eslint-disable-next-line prefer-const
|
|
513
531
|
let { type, payload } = msg;
|
|
@@ -522,81 +540,84 @@ class MetroplexSocket extends Singleton {
|
|
|
522
540
|
if (currentMsgPayloadSize >= maxMessageSize) {
|
|
523
541
|
this.postMessage(currentCompletePv);
|
|
524
542
|
// add to post info
|
|
525
|
-
let postInfoMessage = `Vid: ${currentCompletePv
|
|
526
|
-
postInfoMessage += ` PV: ${currentCompletePv
|
|
527
|
-
postInfoMessage += ` HTTP: ${currentCompletePv
|
|
543
|
+
let postInfoMessage = `Vid: ${currentCompletePv.pvvf.length}`;
|
|
544
|
+
postInfoMessage += ` PV: ${currentCompletePv.pvp.length}`;
|
|
545
|
+
postInfoMessage += ` HTTP: ${(_a = currentCompletePv.pvh) === null || _a === void 0 ? void 0 : _a.length},`;
|
|
528
546
|
postInfo.push(postInfoMessage);
|
|
529
547
|
// resetting currentCompletePv, since we need to keep adding
|
|
530
548
|
// events to a blank object to send to metroplex.
|
|
531
549
|
// retain the video part count, so we don't overwrite anything
|
|
532
550
|
currentCompletePv = {
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
551
|
+
pvi: pageInfo,
|
|
552
|
+
pvp: [],
|
|
553
|
+
pvvf: [],
|
|
554
|
+
pvh: [],
|
|
555
|
+
vpnum: currentCompletePv.vpnum,
|
|
538
556
|
};
|
|
539
|
-
currentCompletePv
|
|
540
|
-
true;
|
|
557
|
+
currentCompletePv.pvi.last = true;
|
|
541
558
|
// resetting the message size based on what is being added
|
|
542
559
|
currentMsgPayloadSize = currentPayloadSize;
|
|
543
560
|
}
|
|
544
|
-
switch (type) {
|
|
545
|
-
case
|
|
546
|
-
currentCompletePv
|
|
561
|
+
switch (msg.type) {
|
|
562
|
+
case WebsocketMessageType.PageVisitVideoFile:
|
|
563
|
+
currentCompletePv.pvvf.push(msg.payload);
|
|
547
564
|
break;
|
|
548
|
-
case
|
|
549
|
-
currentCompletePv
|
|
565
|
+
case WebsocketMessageType.PageVisitPart:
|
|
566
|
+
currentCompletePv.pvp.push(msg.payload);
|
|
550
567
|
break;
|
|
551
|
-
case
|
|
552
|
-
currentCompletePv
|
|
568
|
+
case WebsocketMessageType.PageVisitHttp:
|
|
569
|
+
(_c = (_b = currentCompletePv.pvh) === null || _b === void 0 ? void 0 : _b.push) === null || _c === void 0 ? void 0 : _c.call(_b, msg.payload);
|
|
553
570
|
break;
|
|
554
571
|
}
|
|
555
572
|
});
|
|
556
|
-
this.postMessage(currentCompletePv);
|
|
573
|
+
yield this.postMessage(currentCompletePv);
|
|
557
574
|
// debug log if large retry message queue
|
|
558
575
|
if (this.retryMessageQueue.length > 100) {
|
|
559
|
-
let postInfoMessage = `Vid: ${currentCompletePv
|
|
560
|
-
postInfoMessage += ` PV: ${currentCompletePv
|
|
561
|
-
postInfoMessage += ` HTTP: ${currentCompletePv
|
|
576
|
+
let postInfoMessage = `Vid: ${currentCompletePv.pvvf.length}`;
|
|
577
|
+
postInfoMessage += ` PV: ${currentCompletePv.pvp.length}`;
|
|
578
|
+
postInfoMessage += ` HTTP: ${(_a = currentCompletePv.pvh) === null || _a === void 0 ? void 0 : _a.length},`;
|
|
562
579
|
postInfo.push(postInfoMessage);
|
|
563
580
|
// we completed posted the full pv, send the confirmation debug logs
|
|
564
581
|
// build the debug message
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
582
|
+
const message = {
|
|
583
|
+
msg: `POST Full PV complete`,
|
|
584
|
+
postsCount: postInfo.length,
|
|
585
|
+
postsInfo: stringifyJSON(postInfo),
|
|
586
|
+
retryMessageQueueSize: this.retryMessageQueue.length,
|
|
587
|
+
};
|
|
571
588
|
// Num drops
|
|
572
|
-
if (numDropped
|
|
573
|
-
message
|
|
589
|
+
if (numDropped.pvvf > 0) {
|
|
590
|
+
message.videoPartsDropped = numDropped.pvvf;
|
|
574
591
|
}
|
|
575
|
-
if (numDropped
|
|
576
|
-
message
|
|
592
|
+
if (numDropped.pvp > 0) {
|
|
593
|
+
message.pvpPartsDropped = numDropped.pvp;
|
|
577
594
|
}
|
|
578
|
-
if (numDropped
|
|
579
|
-
message
|
|
595
|
+
if (numDropped.pvh > 0) {
|
|
596
|
+
message.httpPartsDropped = numDropped.pvh;
|
|
580
597
|
}
|
|
581
598
|
// Sequence info
|
|
582
|
-
message
|
|
583
|
-
|
|
599
|
+
message.sequenceInfo = {
|
|
600
|
+
Latest: this.messageSequenceNum,
|
|
601
|
+
acked: {
|
|
602
|
+
latestReceivedSeqNumStoredTime: this.latestReceivedSeqNumStoredTime,
|
|
603
|
+
latestReceivedSeqNumber: this.latestReceivedSeqNumber,
|
|
604
|
+
},
|
|
605
|
+
};
|
|
584
606
|
// if client was disabled (due to inactive or otherwise) enable briefly so the
|
|
585
607
|
// debug message gets through
|
|
586
608
|
const clientDisabled = ClientConfig.getInstance().isClientDisabled;
|
|
587
609
|
ClientConfig.getInstance().isClientDisabled = false;
|
|
588
|
-
ClientConfig.getInstance().
|
|
610
|
+
ClientConfig.getInstance().postInternalError(message, clientDisabled, SEVERITY.warn);
|
|
589
611
|
}
|
|
590
612
|
});
|
|
591
613
|
}
|
|
592
|
-
/**
|
|
593
|
-
* will send a message to metroplex via a post request that will outlive the current page
|
|
594
|
-
*/
|
|
614
|
+
/** will send a message to metroplex via a post request that will outlive the current page */
|
|
595
615
|
postMessage(msg) {
|
|
596
616
|
return __awaiter(this, void 0, void 0, function* () {
|
|
597
617
|
const updatedMsg = msg;
|
|
618
|
+
updatedMsg.vpnum || (updatedMsg.vpnum = 0);
|
|
598
619
|
// ensure a unique video part number each call
|
|
599
|
-
updatedMsg
|
|
620
|
+
updatedMsg.vpnum += 1;
|
|
600
621
|
// we send the remainder elements
|
|
601
622
|
unwrapNoibuWrapped(fetch)(this.postURL, {
|
|
602
623
|
method: 'POST',
|
|
@@ -615,18 +636,16 @@ class MetroplexSocket extends Singleton {
|
|
|
615
636
|
* is active and returns true. If inactive the session and socket are closed
|
|
616
637
|
* and this method returns false.
|
|
617
638
|
*/
|
|
618
|
-
|
|
639
|
+
sendSocketMessage(payload) {
|
|
619
640
|
return __awaiter(this, void 0, void 0, function* () {
|
|
620
|
-
noibuLog('
|
|
641
|
+
noibuLog('sendSocketMessage');
|
|
621
642
|
const closeIfInactive = yield this.closeIfInactive();
|
|
622
643
|
if (closeIfInactive) {
|
|
623
|
-
noibuLog('
|
|
644
|
+
noibuLog('sendSocketMessage dropped due to', { closeIfInactive });
|
|
624
645
|
return;
|
|
625
646
|
}
|
|
647
|
+
noibuLog(`_sendSocketMessage sending: `, payload);
|
|
626
648
|
const payloadJson = stringifyJSON(payload);
|
|
627
|
-
noibuLog(`_sendSocketMessage sending: ${PAGE_VISIT_VID_FRAG_ATT_NAME in payload
|
|
628
|
-
? PAGE_VISIT_VID_FRAG_ATT_NAME
|
|
629
|
-
: payloadJson}`);
|
|
630
649
|
if (this.socket) {
|
|
631
650
|
this.socket.send(payloadJson);
|
|
632
651
|
}
|
|
@@ -644,7 +663,7 @@ class MetroplexSocket extends Singleton {
|
|
|
644
663
|
// lock the client for 1 minute, since the lock expires
|
|
645
664
|
// only on new page loads this will lock the client until
|
|
646
665
|
// the next page is loaded.
|
|
647
|
-
yield ClientConfig.getInstance().lockClientUntilNextPage('Session is inactive, locking until next page');
|
|
666
|
+
yield ClientConfig.getInstance().lockClientUntilNextPage({ msg: 'Session is inactive, locking until next page' });
|
|
648
667
|
this.close();
|
|
649
668
|
// post metrics now so we don't include events after going inactive
|
|
650
669
|
StoredMetrics.getInstance().postMetrics();
|
|
@@ -658,29 +677,27 @@ class MetroplexSocket extends Singleton {
|
|
|
658
677
|
getPageInformation() {
|
|
659
678
|
return __awaiter(this, void 0, void 0, function* () {
|
|
660
679
|
return {
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
680
|
+
br_id: ClientConfig.getInstance().browserId,
|
|
681
|
+
pv_id: ClientConfig.getInstance().pageVisitId,
|
|
682
|
+
v: CURRENT_PV_VERSION,
|
|
683
|
+
seq: yield ClientConfig.getInstance().getPageVisitSeq(),
|
|
684
|
+
on_url: this.initialURL,
|
|
685
|
+
ref_url: this.initialReferringURL,
|
|
686
|
+
start_at: this.sessionTimestamp.toISOString(),
|
|
687
|
+
conc: this.connectionCount,
|
|
688
|
+
cv: CURRENT_NOIBUJS_VERSION,
|
|
689
|
+
last: false,
|
|
690
|
+
script_id: GET_SCRIPT_ID(),
|
|
691
|
+
script_inst_id: this.scriptInstanceId,
|
|
692
|
+
mp_sock_inst_id: this.instanceId,
|
|
693
|
+
sock_inst_id: this.socketInstanceId,
|
|
694
|
+
video_recorder: yield getVideoRecorderType(),
|
|
676
695
|
};
|
|
677
696
|
});
|
|
678
697
|
}
|
|
679
|
-
/**
|
|
680
|
-
* Try to parse help code response and fire custom event
|
|
681
|
-
*/
|
|
698
|
+
/** Try to parse help code response and fire custom event */
|
|
682
699
|
_tryProcessHelpCodeResponse(response) {
|
|
683
|
-
const prefix = `${
|
|
700
|
+
const prefix = `${WorkRequestMessageType.HelpCode}:`;
|
|
684
701
|
if (typeof response !== 'string' || !response.startsWith(prefix)) {
|
|
685
702
|
return false;
|
|
686
703
|
}
|
|
@@ -692,11 +709,5 @@ class MetroplexSocket extends Singleton {
|
|
|
692
709
|
return true;
|
|
693
710
|
}
|
|
694
711
|
}
|
|
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
|
-
};
|
|
701
712
|
|
|
702
|
-
export { createSlidingArrayOfSize, MetroplexSocket as default };
|
|
713
|
+
export { createSlidingArrayOfSize, MetroplexSocket as default, getVideoRecorderType };
|