noibu-react-native 0.0.1 → 0.0.3
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 +9 -7
- package/dist/api/clientConfig.js +50 -48
- package/dist/api/helpCode.js +3 -3
- package/dist/api/inputManager.js +5 -5
- package/dist/api/metroplexSocket.js +31 -43
- package/dist/api/storedMetrics.js +18 -22
- package/dist/api/storedPageVisit.js +27 -29
- package/dist/constants.d.ts +2 -2
- package/dist/constants.js +7 -48
- package/dist/entry/index.d.ts +8 -1
- package/dist/entry/index.js +8 -2
- package/dist/entry/init.js +6 -5
- package/dist/monitors/clickMonitor.js +1 -2
- package/dist/monitors/elementMonitor.js +4 -1
- package/dist/monitors/errorMonitor.d.ts +25 -0
- package/dist/monitors/errorMonitor.js +109 -262
- package/dist/monitors/httpDataBundler.js +11 -12
- package/dist/monitors/inputMonitor.js +4 -1
- package/dist/monitors/locationChangeMonitor.js +4 -16
- package/dist/monitors/pageMonitor.js +4 -1
- package/dist/monitors/requestMonitor.js +5 -19
- package/dist/pageVisit/pageVisit.js +3 -1
- package/dist/pageVisit/pageVisitEventError/blacklistedDomains.js +9 -0
- package/dist/pageVisit/pageVisitEventError/pageVisitEventError.js +9 -14
- package/dist/pageVisit/pageVisitEventHTTP/pageVisitEventHTTP.js +3 -14
- package/dist/storage/rnStorageProvider.d.ts +23 -0
- package/dist/storage/rnStorageProvider.js +23 -52
- package/dist/storage/storage.d.ts +38 -0
- package/dist/storage/storage.js +69 -104
- package/dist/storage/storageProvider.d.ts +25 -0
- package/dist/storage/storageProvider.js +38 -71
- package/dist/utils/function.js +80 -53
- package/dist/utils/performance.js +0 -7
- package/dist/utils/stacktrace-parser.d.ts +9 -0
- package/dist/utils/stacktrace-parser.js +156 -0
- package/package.json +4 -4
- package/dist/storage/localStorageProvider.js +0 -23
- package/dist/storage/sessionStorageProvider.js +0 -23
package/README.md
CHANGED
|
@@ -29,12 +29,14 @@ npm install noibu-react-native --save
|
|
|
29
29
|
|
|
30
30
|
## Usage
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
Call a setup method and wrap your root App component into SDK ErrorBoundary:
|
|
33
33
|
|
|
34
34
|
```jsx
|
|
35
35
|
import React from 'react';
|
|
36
36
|
import { View, Text } from 'react-native';
|
|
37
|
-
import { ErrorBoundary } from 'noibu-react-native';
|
|
37
|
+
import { ErrorBoundary, setupNoibu } from 'noibu-react-native';
|
|
38
|
+
|
|
39
|
+
setupNoibu({ domain: 'react-native-app.myshop.com' })
|
|
38
40
|
|
|
39
41
|
export default function App() {
|
|
40
42
|
return (
|
|
@@ -53,7 +55,7 @@ export default function App() {
|
|
|
53
55
|
}
|
|
54
56
|
```
|
|
55
57
|
|
|
56
|
-
That's it! First time the module is
|
|
58
|
+
That's it! First time the module is set up, it runs an init and starts listening to errors.
|
|
57
59
|
|
|
58
60
|
## Configuration
|
|
59
61
|
|
|
@@ -95,19 +97,19 @@ const AlertHelpCode = () => {
|
|
|
95
97
|
};
|
|
96
98
|
```
|
|
97
99
|
|
|
98
|
-
#### `addCustomAttribute(name: string, value: string) => string
|
|
100
|
+
#### `addCustomAttribute(name: string, value: string) => Promise<string>`
|
|
99
101
|
|
|
100
102
|
Adds a custom attribute to the session.
|
|
101
103
|
|
|
102
104
|
- `@param {string} name` - Name of a custom attribute.
|
|
103
105
|
- `@param {any} value` - It's value, should be a JSON.stringify-able type.
|
|
104
|
-
- `@returns {string}` - A success message, or validation failure cause.
|
|
106
|
+
- `@returns {Promise<string>}` - A success message, or validation failure cause.
|
|
105
107
|
|
|
106
108
|
```js
|
|
107
109
|
import { NoibuJS } from 'noibu-react-native';
|
|
108
110
|
|
|
109
|
-
NoibuJS.addCustomAttribute('myNameIs', 'Jeff'); // SUCCESS
|
|
110
|
-
NoibuJS.addCustomAttribute('veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLong', 'Jeff'); // NAME_TOO_LONG
|
|
111
|
+
NoibuJS.addCustomAttribute('myNameIs', 'Jeff'); // Promise<SUCCESS>
|
|
112
|
+
NoibuJS.addCustomAttribute('veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLong', 'Jeff'); // Promise<NAME_TOO_LONG>
|
|
111
113
|
```
|
|
112
114
|
|
|
113
115
|
#### `addError(customError: Error) => string`
|
package/dist/api/clientConfig.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import uuid from 'react-native-uuid';
|
|
2
2
|
import { MAX_METROPLEX_SOCKET_INNACTIVE_TIME, DISABLED_STATUS_KEY, CLIENT_UNLOCK_TIME_KEY, SEVERITY_WARN, LAST_ACTIVE_TIME_KEY, CURRENT_PAGE_VISIT_COUNT_KEY, NOIBU_BROWSER_ID_KYWRD, BROWSER_ID_KEY, PV_SEQ_NUM_RESET_TIME_MINUTES, SEVERITY_ERROR, JS_ENV, PAGE_VISIT_ID_KEY, MAX_PAGEVISIT_VISITED, CLIENT_LOCK_TIME_MINUTES, GET_SCRIPT_ID, MAX_COLLECT_ERROR_LOG } from '../constants.js';
|
|
3
|
-
import { stringifyJSON, getUserAgent, asString, makeRequest } from '../utils/function.js';
|
|
3
|
+
import { stringifyJSON, getUserAgent, asString, getProperGlobalUrl, makeRequest } from '../utils/function.js';
|
|
4
4
|
import Storage from '../storage/storage.js';
|
|
5
5
|
|
|
6
6
|
/** @module ClientConfig */
|
|
@@ -14,9 +14,10 @@ import Storage from '../storage/storage.js';
|
|
|
14
14
|
class ClientConfig {
|
|
15
15
|
/**
|
|
16
16
|
* Creates a ClientConfig singleton instance
|
|
17
|
-
* @param
|
|
17
|
+
* @param {string} noibuErrorURL
|
|
18
|
+
* @param {string} customerDomain
|
|
18
19
|
*/
|
|
19
|
-
constructor(noibuErrorURL) {
|
|
20
|
+
constructor(noibuErrorURL, customerDomain) {
|
|
20
21
|
// sets up this.browserId, this.disabledStatus
|
|
21
22
|
this.pageVisitId = uuid.v4();
|
|
22
23
|
// variables stored in storage
|
|
@@ -36,16 +37,18 @@ class ClientConfig {
|
|
|
36
37
|
// variables for checking if the socket is inactive
|
|
37
38
|
// used a class variables in order to be changed in testing
|
|
38
39
|
this.maxSocketInactiveTime = MAX_METROPLEX_SOCKET_INNACTIVE_TIME;
|
|
40
|
+
|
|
41
|
+
this.customerDomain = customerDomain;
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
/** Configures the singleton instance */
|
|
42
|
-
static configureInstance(noibuErrorURL) {
|
|
45
|
+
static configureInstance({ noibuErrorURL, customerDomain }) {
|
|
43
46
|
if (!this.instance) {
|
|
44
47
|
// Set this.noibuErrorURL preemptively in case ClientConfig isn't able to be
|
|
45
48
|
// configured properly and throws an error.
|
|
46
49
|
// This will ensure we get the expected error POST request at the correct URL.
|
|
47
50
|
this.noibuErrorURL = noibuErrorURL;
|
|
48
|
-
this.instance = new ClientConfig(noibuErrorURL);
|
|
51
|
+
this.instance = new ClientConfig(noibuErrorURL, customerDomain);
|
|
49
52
|
this.instance.noibuErrorURL = noibuErrorURL;
|
|
50
53
|
}
|
|
51
54
|
}
|
|
@@ -64,14 +67,14 @@ class ClientConfig {
|
|
|
64
67
|
|
|
65
68
|
/** lockClient will disable the client script for a single pagevisit for
|
|
66
69
|
* duration given in minuntes */
|
|
67
|
-
lockClient(duration, msg) {
|
|
70
|
+
async lockClient(duration, msg) {
|
|
68
71
|
const expiryTime = new Date();
|
|
69
72
|
expiryTime.setMinutes(expiryTime.getMinutes() + duration);
|
|
70
73
|
|
|
71
|
-
const noibuLSObject = this._getClientState();
|
|
74
|
+
const noibuLSObject = await this._getClientState();
|
|
72
75
|
noibuLSObject[DISABLED_STATUS_KEY] = true;
|
|
73
76
|
noibuLSObject[CLIENT_UNLOCK_TIME_KEY] = expiryTime;
|
|
74
|
-
this._storeBrowserData(noibuLSObject);
|
|
77
|
+
await this._storeBrowserData(noibuLSObject);
|
|
75
78
|
this.postNoibuErrorAndOptionallyDisableClient(msg, true, SEVERITY_WARN);
|
|
76
79
|
}
|
|
77
80
|
|
|
@@ -81,23 +84,23 @@ class ClientConfig {
|
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
/** Updates the config object to store the given last active time */
|
|
84
|
-
updateLastActiveTime(lastActiveTime) {
|
|
87
|
+
async updateLastActiveTime(lastActiveTime) {
|
|
85
88
|
this.lastActiveTime = lastActiveTime;
|
|
86
|
-
const newConfigData = this._getLsObject();
|
|
89
|
+
const newConfigData = await this._getLsObject();
|
|
87
90
|
newConfigData[LAST_ACTIVE_TIME_KEY] = lastActiveTime;
|
|
88
|
-
this._storeBrowserData(newConfigData);
|
|
91
|
+
await this._storeBrowserData(newConfigData);
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
/** Gets the current page visit sequence number that should be used */
|
|
92
|
-
getPageVisitSeq() {
|
|
93
|
-
if (this._pageVisitSeqNeedsReset()) {
|
|
95
|
+
async getPageVisitSeq() {
|
|
96
|
+
if (await this._pageVisitSeqNeedsReset()) {
|
|
94
97
|
// Reset the page visit sequence number to zero and store the next seq number in storage
|
|
95
98
|
this.pageVisitSeq = 0;
|
|
96
|
-
const newConfigData = this._getLsObject();
|
|
99
|
+
const newConfigData = await this._getLsObject();
|
|
97
100
|
newConfigData[CURRENT_PAGE_VISIT_COUNT_KEY] = this.pageVisitSeq + 1;
|
|
98
101
|
// Update the last active time since we are actively requesting the seq
|
|
99
102
|
newConfigData[LAST_ACTIVE_TIME_KEY] = new Date();
|
|
100
|
-
this._storeBrowserData(newConfigData);
|
|
103
|
+
await this._storeBrowserData(newConfigData);
|
|
101
104
|
}
|
|
102
105
|
|
|
103
106
|
return this.pageVisitSeq;
|
|
@@ -115,9 +118,9 @@ class ClientConfig {
|
|
|
115
118
|
* LastActiveTime: DATE OBJ
|
|
116
119
|
* }
|
|
117
120
|
*/
|
|
118
|
-
_getLsObject() {
|
|
121
|
+
async _getLsObject() {
|
|
119
122
|
const storage = Storage.getInstance();
|
|
120
|
-
const storedConfig = storage.load(NOIBU_BROWSER_ID_KYWRD);
|
|
123
|
+
const storedConfig = await storage.load(NOIBU_BROWSER_ID_KYWRD);
|
|
121
124
|
|
|
122
125
|
// first time browsing since noibu was installed
|
|
123
126
|
if (!storedConfig) {
|
|
@@ -148,8 +151,8 @@ class ClientConfig {
|
|
|
148
151
|
/**
|
|
149
152
|
* Check if we have surpased the last active time and the page visit seq number needs resetting
|
|
150
153
|
*/
|
|
151
|
-
_pageVisitSeqNeedsReset() {
|
|
152
|
-
const noibuLSObject = this._getClientState();
|
|
154
|
+
async _pageVisitSeqNeedsReset() {
|
|
155
|
+
const noibuLSObject = await this._getClientState();
|
|
153
156
|
const someTimeAgo = new Date();
|
|
154
157
|
someTimeAgo.setMinutes(
|
|
155
158
|
someTimeAgo.getMinutes() - PV_SEQ_NUM_RESET_TIME_MINUTES,
|
|
@@ -161,11 +164,11 @@ class ClientConfig {
|
|
|
161
164
|
* _setupStorageVars will set all class variables that depend
|
|
162
165
|
* on the storage's value.
|
|
163
166
|
*/
|
|
164
|
-
_setupStorageVars() {
|
|
167
|
+
async _setupStorageVars() {
|
|
165
168
|
const storage = Storage.getInstance();
|
|
166
|
-
if (!storage.isAvailable()) {
|
|
169
|
+
if (!(await storage.isAvailable())) {
|
|
167
170
|
this.postNoibuErrorAndOptionallyDisableClient(
|
|
168
|
-
`Storage is unavailable, disabling client. ${storage.getDiagnoseInfo()}`,
|
|
171
|
+
`Storage is unavailable, disabling client. ${await storage.getDiagnoseInfo()}`,
|
|
169
172
|
true,
|
|
170
173
|
SEVERITY_ERROR,
|
|
171
174
|
);
|
|
@@ -173,10 +176,10 @@ class ClientConfig {
|
|
|
173
176
|
}
|
|
174
177
|
|
|
175
178
|
// getting the current content of the storage
|
|
176
|
-
const noibuLSObject = this._getClientState();
|
|
179
|
+
const noibuLSObject = await this._getClientState();
|
|
177
180
|
|
|
178
181
|
// Check if we have surpased the last active time and reset the sequence number if so
|
|
179
|
-
if (this._pageVisitSeqNeedsReset()) {
|
|
182
|
+
if (await this._pageVisitSeqNeedsReset()) {
|
|
180
183
|
noibuLSObject[CURRENT_PAGE_VISIT_COUNT_KEY] = 0;
|
|
181
184
|
}
|
|
182
185
|
|
|
@@ -216,7 +219,7 @@ class ClientConfig {
|
|
|
216
219
|
}
|
|
217
220
|
|
|
218
221
|
// we now check if we successfully saved the data
|
|
219
|
-
const savedData = this._storeBrowserData(noibuLSObject);
|
|
222
|
+
const savedData = await this._storeBrowserData(noibuLSObject);
|
|
220
223
|
|
|
221
224
|
// if the browser is null, we cannot access the storage or an
|
|
222
225
|
// error happened, thus we disable collect.
|
|
@@ -237,8 +240,8 @@ class ClientConfig {
|
|
|
237
240
|
* Get it from storage if the expiry date is not in the past
|
|
238
241
|
* Generate a brand new one if the expiry date is in the past
|
|
239
242
|
*/
|
|
240
|
-
_getClientState() {
|
|
241
|
-
const newConfigData = this._getLsObject();
|
|
243
|
+
async _getClientState() {
|
|
244
|
+
const newConfigData = await this._getLsObject();
|
|
242
245
|
|
|
243
246
|
// if the lock expired, we remove the lock period and enable the client
|
|
244
247
|
if (
|
|
@@ -247,7 +250,7 @@ class ClientConfig {
|
|
|
247
250
|
) {
|
|
248
251
|
newConfigData[CLIENT_UNLOCK_TIME_KEY] = null;
|
|
249
252
|
newConfigData[DISABLED_STATUS_KEY] = false;
|
|
250
|
-
this._storeBrowserData(newConfigData);
|
|
253
|
+
await this._storeBrowserData(newConfigData);
|
|
251
254
|
}
|
|
252
255
|
// return the stored browserId
|
|
253
256
|
return newConfigData;
|
|
@@ -257,9 +260,8 @@ class ClientConfig {
|
|
|
257
260
|
* _generateAndStoreData generates brand new data and then proceeds to store
|
|
258
261
|
* it.
|
|
259
262
|
*/
|
|
260
|
-
_generateAndStoreData() {
|
|
261
|
-
|
|
262
|
-
return data;
|
|
263
|
+
async _generateAndStoreData() {
|
|
264
|
+
return this._storeBrowserData(this._generateNewBrowserData());
|
|
263
265
|
}
|
|
264
266
|
|
|
265
267
|
/**
|
|
@@ -288,25 +290,24 @@ class ClientConfig {
|
|
|
288
290
|
* _storeBrowserData will store the passed object in storage.
|
|
289
291
|
* @param {} data the data to be stored
|
|
290
292
|
*/
|
|
291
|
-
_storeBrowserData(data) {
|
|
293
|
+
async _storeBrowserData(data) {
|
|
292
294
|
const storage = Storage.getInstance();
|
|
293
295
|
try {
|
|
294
|
-
storage.save(NOIBU_BROWSER_ID_KYWRD, stringifyJSON(data));
|
|
296
|
+
await storage.save(NOIBU_BROWSER_ID_KYWRD, stringifyJSON(data));
|
|
295
297
|
return data;
|
|
296
298
|
} catch (e) {
|
|
297
299
|
this.postNoibuErrorAndOptionallyDisableClient(
|
|
298
300
|
`Error writing browser data to storage, disabling client: ${e.message}, ` +
|
|
299
|
-
`${storage.getDiagnoseInfo()}`,
|
|
301
|
+
`${await storage.getDiagnoseInfo()}`,
|
|
300
302
|
true,
|
|
301
303
|
SEVERITY_ERROR,
|
|
302
304
|
);
|
|
303
305
|
// sending empty fields if we encountered errors while storing in the LS
|
|
304
|
-
|
|
306
|
+
return {
|
|
305
307
|
[DISABLED_STATUS_KEY]: true,
|
|
306
308
|
[BROWSER_ID_KEY]: null,
|
|
307
309
|
[CURRENT_PAGE_VISIT_COUNT_KEY]: 0,
|
|
308
310
|
};
|
|
309
|
-
return invalidData;
|
|
310
311
|
}
|
|
311
312
|
}
|
|
312
313
|
|
|
@@ -352,10 +353,10 @@ class ClientConfig {
|
|
|
352
353
|
const expiryTime = new Date();
|
|
353
354
|
expiryTime.setMinutes(expiryTime.getMinutes() + 10); // 10 minutes lock
|
|
354
355
|
|
|
355
|
-
const noibuLSObject = this._getClientState();
|
|
356
|
+
const noibuLSObject = await this._getClientState();
|
|
356
357
|
noibuLSObject[DISABLED_STATUS_KEY] = true;
|
|
357
358
|
noibuLSObject[CLIENT_UNLOCK_TIME_KEY] = expiryTime;
|
|
358
|
-
this._storeBrowserData(noibuLSObject);
|
|
359
|
+
await this._storeBrowserData(noibuLSObject);
|
|
359
360
|
this.isClientDisabled = true;
|
|
360
361
|
// end of lock
|
|
361
362
|
// overriding the message to be an alert that we are shutting collect off.
|
|
@@ -365,15 +366,24 @@ class ClientConfig {
|
|
|
365
366
|
}
|
|
366
367
|
|
|
367
368
|
const errorContent = {
|
|
368
|
-
url: (
|
|
369
|
+
url: getProperGlobalUrl(),
|
|
369
370
|
err_msg: errMsg,
|
|
370
371
|
sev: severity,
|
|
371
372
|
};
|
|
372
373
|
const headers = {
|
|
373
374
|
'content-type': 'application/json',
|
|
375
|
+
'User-Agent': await getUserAgent(),
|
|
374
376
|
};
|
|
375
377
|
|
|
376
|
-
if (
|
|
378
|
+
if (keepAlive) {
|
|
379
|
+
global.fetch(this.noibuErrorURL, {
|
|
380
|
+
method: 'POST',
|
|
381
|
+
headers,
|
|
382
|
+
body: stringifyJSON(errorContent),
|
|
383
|
+
// keep alive outlives the current page, its the same as beacon
|
|
384
|
+
keepalive: true,
|
|
385
|
+
});
|
|
386
|
+
} else {
|
|
377
387
|
makeRequest(
|
|
378
388
|
'POST',
|
|
379
389
|
this.noibuErrorURL,
|
|
@@ -384,14 +394,6 @@ class ClientConfig {
|
|
|
384
394
|
).catch(() => {
|
|
385
395
|
// we do nothing and let this error silently fail
|
|
386
396
|
});
|
|
387
|
-
} else {
|
|
388
|
-
fetch(this.noibuErrorURL, {
|
|
389
|
-
method: 'POST',
|
|
390
|
-
headers,
|
|
391
|
-
body: stringifyJSON(errorContent),
|
|
392
|
-
// keep alive outlives the current page, its the same as beacon
|
|
393
|
-
keepalive: true,
|
|
394
|
-
});
|
|
395
397
|
}
|
|
396
398
|
|
|
397
399
|
// only increment if this was an actual error, not a warning or otherwise
|
package/dist/api/helpCode.js
CHANGED
|
@@ -32,8 +32,8 @@ class HelpCode {
|
|
|
32
32
|
* @returns {Promise<string>} Promise object representing the help code request.
|
|
33
33
|
* @throws {string} Throws an error if the noibu connection is unavailable.
|
|
34
34
|
*/
|
|
35
|
-
requestHelpCode() {
|
|
36
|
-
if (this.requestContext
|
|
35
|
+
async requestHelpCode() {
|
|
36
|
+
if (this.requestContext !== null) {
|
|
37
37
|
return this.requestContext.promise;
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -50,7 +50,7 @@ class HelpCode {
|
|
|
50
50
|
|
|
51
51
|
this.requestContext = context;
|
|
52
52
|
|
|
53
|
-
const result = this._sendRequest();
|
|
53
|
+
const result = await this._sendRequest();
|
|
54
54
|
|
|
55
55
|
if (result === false) {
|
|
56
56
|
this.requestContext = null;
|
package/dist/api/inputManager.js
CHANGED
|
@@ -54,7 +54,7 @@ class InputManager {
|
|
|
54
54
|
* gets the sdk object that will be assigned to a window variable
|
|
55
55
|
* @returns {{
|
|
56
56
|
* requestHelpCode: (alert?: boolean) => Promise<string>,
|
|
57
|
-
* addCustomAttribute: (name: string, value: string) => string
|
|
57
|
+
* addCustomAttribute: (name: string, value: string) => Promise<string>,
|
|
58
58
|
* addError: (customError: Error) => string,
|
|
59
59
|
* addJsSdkError: (customError: string, errorSource: string) => string
|
|
60
60
|
* }}
|
|
@@ -157,7 +157,7 @@ class InputManager {
|
|
|
157
157
|
* @param {} name
|
|
158
158
|
* @param {} value
|
|
159
159
|
*/
|
|
160
|
-
_addCustomAttribute(name, value) {
|
|
160
|
+
async _addCustomAttribute(name, value) {
|
|
161
161
|
// we return if we are over the limit of ids
|
|
162
162
|
if (Object.keys(this.customIDs).length >= MAX_CUSTOM_IDS_PER_PAGEVISIT) {
|
|
163
163
|
return this.TOO_MANY_IDS_ADDED_MSG;
|
|
@@ -176,7 +176,7 @@ class InputManager {
|
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
this.customIDs[name] = value;
|
|
179
|
-
MetroplexSocket.getInstance().sendMessage(META_DATA_METROPLEX_TYPE, {
|
|
179
|
+
await MetroplexSocket.getInstance().sendMessage(META_DATA_METROPLEX_TYPE, {
|
|
180
180
|
[PAGE_VISIT_META_DATA_ATT_NAME]: {
|
|
181
181
|
[CUSTOM_ID_NAME_TYPE]: name,
|
|
182
182
|
[CUSTOM_ID_VALUE_TYPE]: value,
|
|
@@ -225,8 +225,8 @@ class InputManager {
|
|
|
225
225
|
* @param {boolean} [alertUser=true] - Whether to alert the user about the help code request.
|
|
226
226
|
* @returns {Promise<string>} A promise that resolves with the requested help code.
|
|
227
227
|
*/
|
|
228
|
-
_requestHelpCode(
|
|
229
|
-
return HelpCode.getInstance().requestHelpCode(
|
|
228
|
+
_requestHelpCode() {
|
|
229
|
+
return HelpCode.getInstance().requestHelpCode();
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
232
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import uuid from 'react-native-uuid';
|
|
2
|
-
import { getProperGlobalUrl,
|
|
2
|
+
import { getProperGlobalUrl, getUserAgent, stringifyJSON, getUserLanguage } from '../utils/function.js';
|
|
3
3
|
import { addSafeEventListener } from '../utils/eventlistener.js';
|
|
4
|
-
import { GET_METROPLEX_BASE_SOCKET_URL, METROPLEX_FRAG_ROUTE, GET_METROPLEX_POST_URL, METROPLEX_RETRY_FREQUENCY, META_DATA_METROPLEX_TYPE, PAGE_VISIT_META_DATA_ATT_NAME, HTTP_DATA_METROPLEX_TYPE, PAGE_VISIT_HTTP_DATA_ATT_NAME, VIDEO_METROPLEX_TYPE, PAGE_VISIT_VID_FRAG_ATT_NAME, PV_METROPLEX_TYPE, PAGE_VISIT_PART_ATT_NAME, SEQ_NUM_ATT_NAME, WORK_REQUEST_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_ERROR, OK_SOCKET_MESSAGE, CLOSE_CONNECTION_FORCEFULLY, BLOCK_SOCKET_MESSAGE, STOP_STORING_PV_SOCKET_MESSAGE, STOP_STORING_VID_SOCKET_MESSAGE, MAX_BEACON_PAYLOAD_SIZE, PAGE_VISIT_INFORMATION_ATT_NAME, VIDEO_PART_COUNT_ATT_NAME, IS_LAST_ATT_NAME, SEVERITY_WARN,
|
|
4
|
+
import { GET_METROPLEX_BASE_SOCKET_URL, METROPLEX_FRAG_ROUTE, GET_METROPLEX_POST_URL, METROPLEX_RETRY_FREQUENCY, META_DATA_METROPLEX_TYPE, PAGE_VISIT_META_DATA_ATT_NAME, HTTP_DATA_METROPLEX_TYPE, PAGE_VISIT_HTTP_DATA_ATT_NAME, VIDEO_METROPLEX_TYPE, PAGE_VISIT_VID_FRAG_ATT_NAME, PV_METROPLEX_TYPE, PAGE_VISIT_PART_ATT_NAME, SEQ_NUM_ATT_NAME, WORK_REQUEST_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_ERROR, OK_SOCKET_MESSAGE, CLOSE_CONNECTION_FORCEFULLY, BLOCK_SOCKET_MESSAGE, STOP_STORING_PV_SOCKET_MESSAGE, STOP_STORING_VID_SOCKET_MESSAGE, MAX_BEACON_PAYLOAD_SIZE, PAGE_VISIT_INFORMATION_ATT_NAME, VIDEO_PART_COUNT_ATT_NAME, IS_LAST_ATT_NAME, SEVERITY_WARN, 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, LANG_ATT_NAME, HELP_CODE_ATT_NAME } from '../constants.js';
|
|
5
5
|
import ClientConfig from './clientConfig.js';
|
|
6
6
|
import StoredMetrics from './storedMetrics.js';
|
|
7
7
|
import StoredPageVisit from './storedPageVisit.js';
|
|
@@ -59,10 +59,7 @@ class MetroplexSocket {
|
|
|
59
59
|
// current page visit has the real initial onURL. Fragments and SPA's
|
|
60
60
|
// can change the URL without reloading the page.
|
|
61
61
|
this.initialURL = getProperGlobalUrl();
|
|
62
|
-
this.initialReferingURL =
|
|
63
|
-
global.document && global.document.referrer
|
|
64
|
-
? getMaxSubstringAllowed(global.document.referrer)
|
|
65
|
-
: '';
|
|
62
|
+
this.initialReferingURL = '';
|
|
66
63
|
this.sessionTimestamp = new Date();
|
|
67
64
|
|
|
68
65
|
// latest time that we received a confirmation message from metroplex
|
|
@@ -164,9 +161,9 @@ class MetroplexSocket {
|
|
|
164
161
|
* Queues the message if the connection isn't open yet.
|
|
165
162
|
* @param {} type
|
|
166
163
|
* @param {} payload
|
|
167
|
-
* @returns {boolean} true if message was sent succefully, false otherwise
|
|
164
|
+
* @returns {Promise<boolean>} true if message was sent succefully, false otherwise
|
|
168
165
|
*/
|
|
169
|
-
sendMessage(type, payload) {
|
|
166
|
+
async sendMessage(type, payload) {
|
|
170
167
|
// if we have a lock on this specific type, we dont send it
|
|
171
168
|
if (
|
|
172
169
|
type in this.metroplexTypeLock ||
|
|
@@ -186,7 +183,7 @@ class MetroplexSocket {
|
|
|
186
183
|
this.retryMessageQueue.push({ payload: payloadData, type });
|
|
187
184
|
StoredPageVisit.getInstance().checkAndStoreRetryQueue(
|
|
188
185
|
this.retryMessageQueue,
|
|
189
|
-
this.getPageInformation(),
|
|
186
|
+
await this.getPageInformation(),
|
|
190
187
|
);
|
|
191
188
|
}
|
|
192
189
|
|
|
@@ -264,7 +261,7 @@ class MetroplexSocket {
|
|
|
264
261
|
});
|
|
265
262
|
this.socketInstanceId = uuid.v4();
|
|
266
263
|
|
|
267
|
-
this.socket.onerror =
|
|
264
|
+
this.socket.onerror = e => {
|
|
268
265
|
// use for metrics
|
|
269
266
|
// there is no useful error message/description from this event
|
|
270
267
|
};
|
|
@@ -395,23 +392,21 @@ class MetroplexSocket {
|
|
|
395
392
|
this.sessionLength = delta;
|
|
396
393
|
}
|
|
397
394
|
|
|
398
|
-
const endTime = new Date(
|
|
399
|
-
this.sessionTimestamp.getTime() + delta,
|
|
400
|
-
).toISOString();
|
|
401
|
-
|
|
402
395
|
// Assigning this value here is much better than copying the whole object.
|
|
403
396
|
// eslint-disable-next-line no-param-reassign
|
|
404
|
-
payload[END_AT_ATT_NAME] =
|
|
397
|
+
payload[END_AT_ATT_NAME] = new Date(
|
|
398
|
+
this.sessionTimestamp.getTime() + delta,
|
|
399
|
+
).toISOString();
|
|
405
400
|
}
|
|
406
401
|
|
|
407
402
|
/** open handler for socket */
|
|
408
|
-
_onSocketOpen() {
|
|
403
|
+
async _onSocketOpen() {
|
|
409
404
|
// if we are not connected, we do not send any messages
|
|
410
405
|
if (!this.isConnected() || ClientConfig.getInstance().isClientDisabled) {
|
|
411
406
|
return;
|
|
412
407
|
}
|
|
413
408
|
|
|
414
|
-
this._sendSocketMessage(this.getPageInformation());
|
|
409
|
+
this._sendSocketMessage(await this.getPageInformation());
|
|
415
410
|
// Set this to allow normal page visit and video frag messages to be sent
|
|
416
411
|
this.pageVisitInfoSent = true;
|
|
417
412
|
this.currentConnectionAttempts = 0;
|
|
@@ -631,7 +626,7 @@ class MetroplexSocket {
|
|
|
631
626
|
* will try to empty both the queues with beacons.
|
|
632
627
|
* @param {} maxMessageSize
|
|
633
628
|
*/
|
|
634
|
-
postFullPageVisit(maxMessageSize) {
|
|
629
|
+
async postFullPageVisit(maxMessageSize) {
|
|
635
630
|
if (this.retryMessageQueue.length === 0) {
|
|
636
631
|
return;
|
|
637
632
|
}
|
|
@@ -645,14 +640,14 @@ class MetroplexSocket {
|
|
|
645
640
|
|
|
646
641
|
let currentMsgPayloadSize = 0;
|
|
647
642
|
let currentCompletePv = {
|
|
648
|
-
[PAGE_VISIT_INFORMATION_ATT_NAME]: this.getPageInformation(),
|
|
643
|
+
[PAGE_VISIT_INFORMATION_ATT_NAME]: await this.getPageInformation(),
|
|
649
644
|
[PAGE_VISIT_PART_ATT_NAME]: [],
|
|
650
645
|
[PAGE_VISIT_VID_FRAG_ATT_NAME]: [],
|
|
651
646
|
[PAGE_VISIT_HTTP_DATA_ATT_NAME]: [],
|
|
652
647
|
[VIDEO_PART_COUNT_ATT_NAME]: this.connectionCount,
|
|
653
648
|
};
|
|
654
649
|
currentCompletePv[PAGE_VISIT_INFORMATION_ATT_NAME][IS_LAST_ATT_NAME] = true;
|
|
655
|
-
|
|
650
|
+
const pageInfo = await this.getPageInformation();
|
|
656
651
|
this.retryMessageQueue.forEach(msg => {
|
|
657
652
|
// can't use two variables types in obj deconstruction
|
|
658
653
|
// eslint-disable-next-line prefer-const
|
|
@@ -677,9 +672,9 @@ class MetroplexSocket {
|
|
|
677
672
|
|
|
678
673
|
// resetting currentCompletePv, since we need to keep adding
|
|
679
674
|
// events to a blank object to send to metroplex.
|
|
680
|
-
// retain the video part count so we don't overwrite anything
|
|
675
|
+
// retain the video part count, so we don't overwrite anything
|
|
681
676
|
currentCompletePv = {
|
|
682
|
-
[PAGE_VISIT_INFORMATION_ATT_NAME]:
|
|
677
|
+
[PAGE_VISIT_INFORMATION_ATT_NAME]: pageInfo,
|
|
683
678
|
[PAGE_VISIT_PART_ATT_NAME]: [],
|
|
684
679
|
[PAGE_VISIT_VID_FRAG_ATT_NAME]: [],
|
|
685
680
|
[PAGE_VISIT_HTTP_DATA_ATT_NAME]: [],
|
|
@@ -765,30 +760,23 @@ class MetroplexSocket {
|
|
|
765
760
|
* will send a message to metroplex via a post request that will outlive the current page
|
|
766
761
|
* @param {} msg
|
|
767
762
|
*/
|
|
768
|
-
postMessage(msg) {
|
|
763
|
+
async postMessage(msg) {
|
|
769
764
|
const updatedMsg = msg;
|
|
770
765
|
|
|
771
766
|
// ensure a unique video part number each call
|
|
772
767
|
updatedMsg[VIDEO_PART_COUNT_ATT_NAME] += 1;
|
|
773
768
|
|
|
774
|
-
// we
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
'content-type': 'application/json',
|
|
786
|
-
},
|
|
787
|
-
body: stringifyJSON(updatedMsg),
|
|
788
|
-
// keep alive outlives the current page, its the same as beacon
|
|
789
|
-
keepalive: true,
|
|
790
|
-
});
|
|
791
|
-
}
|
|
769
|
+
// we send the remainder elements
|
|
770
|
+
global.fetch(this.postURL, {
|
|
771
|
+
method: 'POST',
|
|
772
|
+
headers: {
|
|
773
|
+
'content-type': 'application/json',
|
|
774
|
+
'User-Agent': await getUserAgent(),
|
|
775
|
+
},
|
|
776
|
+
body: stringifyJSON(updatedMsg),
|
|
777
|
+
// keep alive outlives the current page, its the same as beacon
|
|
778
|
+
keepalive: true,
|
|
779
|
+
});
|
|
792
780
|
}
|
|
793
781
|
|
|
794
782
|
/**
|
|
@@ -832,12 +820,12 @@ class MetroplexSocket {
|
|
|
832
820
|
}
|
|
833
821
|
|
|
834
822
|
/** will get page information, calling this will increase the connection count */
|
|
835
|
-
getPageInformation() {
|
|
823
|
+
async getPageInformation() {
|
|
836
824
|
const pvi = {
|
|
837
825
|
[BROWSER_ID_ATT_NAME]: ClientConfig.getInstance().browserId,
|
|
838
826
|
[PV_ID_ATT_NAME]: ClientConfig.getInstance().pageVisitId,
|
|
839
827
|
[VER_ATT_NAME]: CURRENT_PV_VERSION,
|
|
840
|
-
[PV_SEQ_ATT_NAME]: ClientConfig.getInstance().getPageVisitSeq(),
|
|
828
|
+
[PV_SEQ_ATT_NAME]: await ClientConfig.getInstance().getPageVisitSeq(),
|
|
841
829
|
[ON_URL_ATT_NAME]: this.initialURL,
|
|
842
830
|
[REF_URL_ATT_NAME]: this.initialReferingURL,
|
|
843
831
|
[STARTED_AT_ATT_NAME]: this.sessionTimestamp.toISOString(),
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { BROWSER_ID_ATT_NAME, PV_ID_ATT_NAME, COLLECT_VER_ATT_NAME, CURRENT_NOIBUJS_VERSION, VER_ATT_NAME, CURRENT_METRICS_VERSION, EXP_VIDEO_LENGTH_ATT_NAME, PV_EXP_VF_SEQ_ATT_NAME, PV_EXP_PART_COUNTER_ATT_NAME, PV_EXP_HTTP_DATA_SEQ_ATT_NAME, PV_HTTP_PAYLOADS_COLLECTED_ATT_NAME, PV_HTTP_PAYLOADS_DROPPED_OVERSIZE_ATT_NAME, PV_HTTP_PAYLOADS_DROPPED_TYPE_ATT_NAME, PV_HTTP_REQUESTS_DROPPED_OVER_LIMIT, VIDEO_CLICKS_ATT_NAME, PV_CLICKS_ATT_NAME, DID_CUT_PV_ATT_NAME, DID_CUT_VID_ATT_NAME, DID_START_VID_ATT_NAME, HTTP_COUNT_EXPECTED_ATT_NAME, ERR_COUNT_EXPECTED_ATT_NAME, ON_URL_ATT_NAME, GET_METROPLEX_METRICS_URL } from '../constants.js';
|
|
2
2
|
import ClientConfig from './clientConfig.js';
|
|
3
|
-
import { stringifyJSON } from '../utils/function.js';
|
|
3
|
+
import { getProperGlobalUrl, getUserAgent, stringifyJSON } from '../utils/function.js';
|
|
4
4
|
import { addSafeEventListener } from '../utils/eventlistener.js';
|
|
5
5
|
|
|
6
6
|
/** @module StoredMetrics */
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* This class holds the final page visit and video frag metrics. It flushes
|
|
10
|
-
* them to
|
|
10
|
+
* them to storage and then finally sends them to Metroplex via the post
|
|
11
11
|
* route when the next page is loaded
|
|
12
12
|
*/
|
|
13
13
|
class StoredMetrics {
|
|
@@ -35,7 +35,10 @@ class StoredMetrics {
|
|
|
35
35
|
this._setupListeners();
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* gets the singleton instance
|
|
40
|
+
* @returns {StoredMetrics}
|
|
41
|
+
*/
|
|
39
42
|
static getInstance() {
|
|
40
43
|
if (!this.instance) {
|
|
41
44
|
this.instance = new StoredMetrics();
|
|
@@ -148,9 +151,8 @@ class StoredMetrics {
|
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
/** posts the metrics to metroplex using the beacon API
|
|
151
|
-
* @param {} eventName
|
|
152
154
|
*/
|
|
153
|
-
postMetrics(
|
|
155
|
+
async postMetrics() {
|
|
154
156
|
// Create a new object to write to local storage that doesnt have the timeout and flush members.
|
|
155
157
|
const lsMetrics = {
|
|
156
158
|
// metadata
|
|
@@ -177,24 +179,18 @@ class StoredMetrics {
|
|
|
177
179
|
[DID_START_VID_ATT_NAME]: this.didStartVideo,
|
|
178
180
|
[HTTP_COUNT_EXPECTED_ATT_NAME]: this.httpCount,
|
|
179
181
|
[ERR_COUNT_EXPECTED_ATT_NAME]: this.errCount,
|
|
180
|
-
[ON_URL_ATT_NAME]:
|
|
181
|
-
(global.document &&
|
|
182
|
-
global.document.location &&
|
|
183
|
-
global.document.location.href) ||
|
|
184
|
-
'http://localhost',
|
|
182
|
+
[ON_URL_ATT_NAME]: getProperGlobalUrl(), // todo implement navigation
|
|
185
183
|
};
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
});
|
|
197
|
-
}
|
|
184
|
+
global.fetch(GET_METROPLEX_METRICS_URL(), {
|
|
185
|
+
method: 'POST',
|
|
186
|
+
headers: {
|
|
187
|
+
'content-type': 'application/json',
|
|
188
|
+
'User-Agent': await getUserAgent(),
|
|
189
|
+
},
|
|
190
|
+
body: stringifyJSON(lsMetrics),
|
|
191
|
+
// keep alive outlives the current page, its the same as beacon
|
|
192
|
+
keepalive: true,
|
|
193
|
+
});
|
|
198
194
|
}
|
|
199
195
|
}
|
|
200
196
|
|