@webex/internal-plugin-metrics 3.0.0-beta.8 → 3.0.0-beta.81
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 +1 -3
- package/dist/batcher.js +3 -22
- package/dist/batcher.js.map +1 -1
- package/dist/call-diagnostic-events-batcher.js +2 -12
- package/dist/call-diagnostic-events-batcher.js.map +1 -1
- package/dist/client-metrics-batcher.js +1 -7
- package/dist/client-metrics-batcher.js.map +1 -1
- package/dist/config.js +21 -5
- package/dist/config.js.map +1 -1
- package/dist/index.js +13 -10
- package/dist/index.js.map +1 -1
- package/dist/metrics.js +25 -63
- package/dist/metrics.js.map +1 -1
- package/package.json +8 -8
- package/src/batcher.js +33 -26
- package/src/call-diagnostic-events-batcher.js +5 -5
- package/src/client-metrics-batcher.js +3 -4
- package/src/config.js +25 -5
- package/src/index.js +2 -2
- package/src/metrics.js +30 -45
- package/test/unit/spec/batcher.js +26 -15
- package/test/unit/spec/call-diagnostic-events-batcher.js +39 -24
- package/test/unit/spec/client-metrics-batcher.js +26 -15
- package/test/unit/spec/metrics.js +23 -24
package/dist/metrics.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["BrowserDetection","getOSName","getOSVersion","getBrowserName","getBrowserVersion","getSparkUserAgent","webex","config","appName","appVersion","appPlatform","sparkUserAgent","CLIENT_NAME","Metrics","WebexPlugin","extend","children","batcher","Batcher","clientMetricsBatcher","ClientMetricsBatcher","callDiagnosticEventsBatcher","CallDiagnosticEventsBatcher","namespace","submit","key","value","request","submitClientMetrics","eventName","props","preLoginId","Error","payload","metricName","tags","browser","os","domain","window","location","hostname","
|
|
1
|
+
{"version":3,"names":["BrowserDetection","getOSName","getOSVersion","getBrowserName","getBrowserVersion","getOSNameInternal","OSMap","OS_NAME","OTHERS","getSparkUserAgent","webex","config","appName","appVersion","appPlatform","sparkUserAgent","CLIENT_NAME","Metrics","WebexPlugin","extend","children","batcher","Batcher","clientMetricsBatcher","ClientMetricsBatcher","callDiagnosticEventsBatcher","CallDiagnosticEventsBatcher","namespace","submit","key","value","request","submitClientMetrics","eventName","props","preLoginId","Error","payload","metricName","tags","browser","os","domain","window","location","hostname","fields","browser_version","os_version","sdk_version","version","platform","spark_user_agent","client_id","credentials","type","metrics","context","app","locale","name","eventPayload","timestamp","Date","valueOf","_payload","postPreLoginMetric","aliasUser","method","api","resource","headers","body","qs","alias","getClientToken","then","token","authorization","toString","submitCallDiagnosticEvents","event"],"sources":["metrics.js"],"sourcesContent":["/* eslint-disable default-param-last */\n\n/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {WebexPlugin} from '@webex/webex-core';\nimport {BrowserDetection} from '@webex/common';\nimport {OS_NAME, OSMap, CLIENT_NAME} from './config';\n\nimport Batcher from './batcher';\nimport ClientMetricsBatcher from './client-metrics-batcher';\nimport CallDiagnosticEventsBatcher from './call-diagnostic-events-batcher';\n\nconst {getOSName, getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();\n\nexport function getOSNameInternal() {\n return OSMap[getOSName()] ?? OS_NAME.OTHERS;\n}\n\nfunction getSparkUserAgent(webex) {\n const {appName, appVersion, appPlatform} = webex?.config ?? {};\n\n let sparkUserAgent = CLIENT_NAME;\n\n if (appName) {\n sparkUserAgent += ` ${appName}/${appVersion ?? '0.0'}`;\n }\n\n if (appPlatform) {\n sparkUserAgent += ` ${appPlatform}`;\n }\n\n return sparkUserAgent;\n}\n\nconst Metrics = WebexPlugin.extend({\n children: {\n batcher: Batcher,\n clientMetricsBatcher: ClientMetricsBatcher,\n callDiagnosticEventsBatcher: CallDiagnosticEventsBatcher,\n },\n\n namespace: 'Metrics',\n\n submit(key, value) {\n return this.batcher.request({key, ...value});\n },\n\n /**\n * This corresponds to #sendSemiStructured() in the deprecated metrics handler\n * @param {string} eventName\n * @param {Object} props\n * @param {string} preLoginId\n * @returns {Object} HttpResponse object\n */\n submitClientMetrics(eventName, props = {}, preLoginId) {\n if (!eventName) {\n throw Error('Missing behavioral metric name. Please provide one');\n }\n const payload = {metricName: eventName};\n\n payload.tags = {\n ...props.tags,\n browser: getBrowserName(),\n os: getOSNameInternal(),\n\n // Node does not like this so we need to check if it exists or not\n // eslint-disable-next-line no-undef\n domain:\n typeof window !== 'undefined' ? window.location.hostname || 'non-browser' : 'non-browser', // Check what else we could measure\n };\n\n payload.fields = {\n ...props.fields,\n browser_version: getBrowserVersion(),\n os_version: getOSVersion(),\n sdk_version: this.webex.version,\n platform: 'Web',\n spark_user_agent: getSparkUserAgent(this.webex),\n client_id: this.webex.credentials.config.client_id,\n };\n\n payload.type = props.type || this.webex.config.metrics.type;\n\n payload.context = {\n ...props.context,\n app: {\n version: this.webex.version,\n },\n locale: 'en-US',\n os: {\n name: getOSNameInternal(),\n version: getOSVersion(),\n },\n };\n\n if (props.eventPayload) {\n payload.eventPayload = props.eventPayload;\n }\n\n // Mocking the time in tests when running in node\n // is impossible so unable to use Date.now()\n payload.timestamp = new Date().valueOf();\n\n if (preLoginId) {\n const _payload = {\n metrics: [payload],\n };\n\n // Do not batch these because pre-login events occur during onboarding, so we will be partially blind\n // to users' progress through the reg flow if we wait to persist pre-login metrics for people who drop off because\n // their metrics will not post from a queue flush in time\n return this.postPreLoginMetric(_payload, preLoginId);\n }\n\n return this.clientMetricsBatcher.request(payload);\n },\n\n /**\n * Issue request to alias a user's pre-login ID with their CI UUID\n * @param {string} preLoginId\n * @returns {Object} HttpResponse object\n */\n aliasUser(preLoginId) {\n return this.request({\n method: 'POST',\n api: 'metrics',\n resource: 'clientmetrics',\n headers: {\n 'x-prelogin-userid': preLoginId,\n },\n body: {},\n qs: {\n alias: true,\n },\n });\n },\n\n postPreLoginMetric(payload, preLoginId) {\n return this.webex.credentials.getClientToken().then((token) =>\n this.request({\n method: 'POST',\n api: 'metrics',\n resource: 'clientmetrics-prelogin',\n headers: {\n authorization: token.toString(),\n 'x-prelogin-userid': preLoginId,\n },\n body: payload,\n })\n );\n },\n\n submitCallDiagnosticEvents(payload) {\n const event = {\n type: 'diagnostic-event',\n eventPayload: payload,\n };\n\n return this.callDiagnosticEventsBatcher.request(event);\n },\n});\n\nexport default Metrics;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/internal-plugin-metrics",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.81",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
"sinon": "^9.2.4"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@webex/common": "3.0.0-beta.
|
|
28
|
-
"@webex/common-timers": "3.0.0-beta.
|
|
29
|
-
"@webex/internal-plugin-device": "3.0.0-beta.
|
|
30
|
-
"@webex/internal-plugin-metrics": "3.0.0-beta.
|
|
31
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
32
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
33
|
-
"@webex/webex-core": "3.0.0-beta.
|
|
27
|
+
"@webex/common": "3.0.0-beta.81",
|
|
28
|
+
"@webex/common-timers": "3.0.0-beta.81",
|
|
29
|
+
"@webex/internal-plugin-device": "3.0.0-beta.81",
|
|
30
|
+
"@webex/internal-plugin-metrics": "3.0.0-beta.81",
|
|
31
|
+
"@webex/test-helper-chai": "3.0.0-beta.81",
|
|
32
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.81",
|
|
33
|
+
"@webex/webex-core": "3.0.0-beta.81"
|
|
34
34
|
}
|
|
35
35
|
}
|
package/src/batcher.js
CHANGED
|
@@ -23,11 +23,13 @@ const MetricsBatcher = Batcher.extend({
|
|
|
23
23
|
},
|
|
24
24
|
|
|
25
25
|
prepareRequest(queue) {
|
|
26
|
-
return Promise.resolve(
|
|
27
|
-
|
|
26
|
+
return Promise.resolve(
|
|
27
|
+
queue.map((item) => {
|
|
28
|
+
item.postTime = item.postTime || Date.now();
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
return item;
|
|
31
|
+
})
|
|
32
|
+
);
|
|
31
33
|
},
|
|
32
34
|
|
|
33
35
|
submitHttpRequest(payload) {
|
|
@@ -36,8 +38,8 @@ const MetricsBatcher = Batcher.extend({
|
|
|
36
38
|
service: 'metrics',
|
|
37
39
|
resource: 'metrics',
|
|
38
40
|
body: {
|
|
39
|
-
metrics: payload
|
|
40
|
-
}
|
|
41
|
+
metrics: payload,
|
|
42
|
+
},
|
|
41
43
|
});
|
|
42
44
|
},
|
|
43
45
|
|
|
@@ -47,38 +49,43 @@ const MetricsBatcher = Batcher.extend({
|
|
|
47
49
|
|
|
48
50
|
handleHttpError(reason) {
|
|
49
51
|
if (reason instanceof WebexHttpError.NetworkOrCORSError) {
|
|
50
|
-
this.logger.warn(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
item
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
this.logger.warn(
|
|
53
|
+
'metrics-batcher: received network error submitting metrics, reenqueuing payload'
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
return Promise.all(
|
|
57
|
+
reason.options.body.metrics.map(
|
|
58
|
+
(item) =>
|
|
59
|
+
new Promise((resolve) => {
|
|
60
|
+
const delay = item[sym].nextDelay;
|
|
61
|
+
|
|
62
|
+
if (delay < this.config.batcherRetryPlateau) {
|
|
63
|
+
item[sym].nextDelay *= 2;
|
|
64
|
+
}
|
|
65
|
+
safeSetTimeout(() => {
|
|
66
|
+
resolve(this.rerequest(item));
|
|
67
|
+
}, delay);
|
|
68
|
+
})
|
|
69
|
+
)
|
|
70
|
+
);
|
|
62
71
|
}
|
|
63
72
|
|
|
64
73
|
return Reflect.apply(Batcher.prototype.handleHttpError, this, [reason]);
|
|
65
74
|
},
|
|
66
75
|
|
|
67
76
|
rerequest(item) {
|
|
68
|
-
return Promise.all([
|
|
69
|
-
|
|
70
|
-
this.prepareItem(item)
|
|
71
|
-
])
|
|
72
|
-
.then(([defer, req]) => {
|
|
77
|
+
return Promise.all([this.getDeferredForRequest(item), this.prepareItem(item)]).then(
|
|
78
|
+
([defer, req]) => {
|
|
73
79
|
this.enqueue(req)
|
|
74
80
|
.then(() => this.bounce())
|
|
75
81
|
.catch((reason) => defer.reject(reason));
|
|
76
|
-
}
|
|
82
|
+
}
|
|
83
|
+
);
|
|
77
84
|
},
|
|
78
85
|
|
|
79
86
|
fingerprintRequest(item) {
|
|
80
87
|
item[sym] = item[sym] || {
|
|
81
|
-
nextDelay: 1000
|
|
88
|
+
nextDelay: 1000,
|
|
82
89
|
};
|
|
83
90
|
|
|
84
91
|
return Promise.resolve(item[sym]);
|
|
@@ -86,7 +93,7 @@ const MetricsBatcher = Batcher.extend({
|
|
|
86
93
|
|
|
87
94
|
fingerprintResponse(item) {
|
|
88
95
|
return Promise.resolve(item[sym]);
|
|
89
|
-
}
|
|
96
|
+
},
|
|
90
97
|
});
|
|
91
98
|
|
|
92
99
|
export default MetricsBatcher;
|
|
@@ -10,7 +10,7 @@ const CallDiagnosticEventsBatcher = Batcher.extend({
|
|
|
10
10
|
/**
|
|
11
11
|
* @param {string} webClientDomain
|
|
12
12
|
* @returns {string}
|
|
13
|
-
|
|
13
|
+
*/
|
|
14
14
|
getBuildType(webClientDomain) {
|
|
15
15
|
if (
|
|
16
16
|
webClientDomain?.includes('teams.webex.com') ||
|
|
@@ -29,7 +29,7 @@ const CallDiagnosticEventsBatcher = Batcher.extend({
|
|
|
29
29
|
// Browsers cannot provide such information right now. However, it is a required field.
|
|
30
30
|
const origin = {
|
|
31
31
|
buildType: this.getBuildType(item.event?.eventData?.webClientDomain),
|
|
32
|
-
networkType: 'unknown'
|
|
32
|
+
networkType: 'unknown',
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
item.eventPayload.origin = Object.assign(origin, item.eventPayload.origin);
|
|
@@ -53,10 +53,10 @@ const CallDiagnosticEventsBatcher = Batcher.extend({
|
|
|
53
53
|
service: 'metrics',
|
|
54
54
|
resource: 'clientmetrics',
|
|
55
55
|
body: {
|
|
56
|
-
metrics: payload
|
|
57
|
-
}
|
|
56
|
+
metrics: payload,
|
|
57
|
+
},
|
|
58
58
|
});
|
|
59
|
-
}
|
|
59
|
+
},
|
|
60
60
|
});
|
|
61
61
|
|
|
62
62
|
export default CallDiagnosticEventsBatcher;
|
package/src/config.js
CHANGED
|
@@ -8,15 +8,35 @@ export const CLIENT_NAME = 'webex-js-sdk';
|
|
|
8
8
|
export default {
|
|
9
9
|
device: {
|
|
10
10
|
preDiscoveryServices: {
|
|
11
|
-
metricsServiceUrl:
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
metricsServiceUrl:
|
|
12
|
+
process.env.METRICS_SERVICE_URL || 'https://metrics-a.wbx2.com/metrics/api/v1',
|
|
13
|
+
metrics: process.env.METRICS_SERVICE_URL || 'https://metrics-a.wbx2.com/metrics/api/v1',
|
|
14
|
+
},
|
|
14
15
|
},
|
|
15
16
|
metrics: {
|
|
16
17
|
appType: inBrowser ? 'browser' : 'nodejs',
|
|
17
18
|
batcherWait: 500,
|
|
18
19
|
batcherMaxCalls: 50,
|
|
19
20
|
batcherMaxWait: 1500,
|
|
20
|
-
batcherRetryPlateau: 32000
|
|
21
|
-
}
|
|
21
|
+
batcherRetryPlateau: 32000,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const OS_NAME = {
|
|
26
|
+
WINDOWS: 'windows',
|
|
27
|
+
MAC: 'mac',
|
|
28
|
+
IOS: 'ios',
|
|
29
|
+
ANDROID: 'android',
|
|
30
|
+
CHROME: 'chrome',
|
|
31
|
+
LINUX: 'linux',
|
|
32
|
+
OTHERS: 'other',
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const OSMap = {
|
|
36
|
+
'Chrome OS': OS_NAME.CHROME,
|
|
37
|
+
macOS: OS_NAME.MAC,
|
|
38
|
+
Windows: OS_NAME.WINDOWS,
|
|
39
|
+
iOS: OS_NAME.IOS,
|
|
40
|
+
Android: OS_NAME.ANDROID,
|
|
41
|
+
Linux: OS_NAME.LINUX,
|
|
22
42
|
};
|
package/src/index.js
CHANGED
|
@@ -10,8 +10,8 @@ import Metrics from './metrics';
|
|
|
10
10
|
import config from './config';
|
|
11
11
|
|
|
12
12
|
registerInternalPlugin('metrics', Metrics, {
|
|
13
|
-
config
|
|
13
|
+
config,
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
-
export {default} from './metrics';
|
|
16
|
+
export {default, getOSNameInternal} from './metrics';
|
|
17
17
|
export {config};
|
package/src/metrics.js
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
|
+
/* eslint-disable default-param-last */
|
|
2
|
+
|
|
1
3
|
/*!
|
|
2
4
|
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
5
|
*/
|
|
4
6
|
|
|
5
7
|
import {WebexPlugin} from '@webex/webex-core';
|
|
6
8
|
import {BrowserDetection} from '@webex/common';
|
|
9
|
+
import {OS_NAME, OSMap, CLIENT_NAME} from './config';
|
|
7
10
|
|
|
8
|
-
import {CLIENT_NAME} from './config';
|
|
9
11
|
import Batcher from './batcher';
|
|
10
12
|
import ClientMetricsBatcher from './client-metrics-batcher';
|
|
11
13
|
import CallDiagnosticEventsBatcher from './call-diagnostic-events-batcher';
|
|
12
14
|
|
|
13
|
-
const {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
} = BrowserDetection();
|
|
15
|
+
const {getOSName, getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
|
|
16
|
+
|
|
17
|
+
export function getOSNameInternal() {
|
|
18
|
+
return OSMap[getOSName()] ?? OS_NAME.OTHERS;
|
|
19
|
+
}
|
|
19
20
|
|
|
20
21
|
function getSparkUserAgent(webex) {
|
|
21
|
-
const {
|
|
22
|
-
appName,
|
|
23
|
-
appVersion,
|
|
24
|
-
appPlatform
|
|
25
|
-
} = webex?.config ?? {};
|
|
22
|
+
const {appName, appVersion, appPlatform} = webex?.config ?? {};
|
|
26
23
|
|
|
27
24
|
let sparkUserAgent = CLIENT_NAME;
|
|
28
25
|
|
|
@@ -37,21 +34,19 @@ function getSparkUserAgent(webex) {
|
|
|
37
34
|
return sparkUserAgent;
|
|
38
35
|
}
|
|
39
36
|
|
|
40
|
-
|
|
41
37
|
const Metrics = WebexPlugin.extend({
|
|
42
38
|
children: {
|
|
43
39
|
batcher: Batcher,
|
|
44
40
|
clientMetricsBatcher: ClientMetricsBatcher,
|
|
45
|
-
callDiagnosticEventsBatcher: CallDiagnosticEventsBatcher
|
|
41
|
+
callDiagnosticEventsBatcher: CallDiagnosticEventsBatcher,
|
|
46
42
|
},
|
|
47
43
|
|
|
48
44
|
namespace: 'Metrics',
|
|
49
45
|
|
|
50
46
|
submit(key, value) {
|
|
51
|
-
return this.batcher.request(
|
|
47
|
+
return this.batcher.request({key, ...value});
|
|
52
48
|
},
|
|
53
49
|
|
|
54
|
-
|
|
55
50
|
/**
|
|
56
51
|
* This corresponds to #sendSemiStructured() in the deprecated metrics handler
|
|
57
52
|
* @param {string} eventName
|
|
@@ -68,49 +63,38 @@ const Metrics = WebexPlugin.extend({
|
|
|
68
63
|
payload.tags = {
|
|
69
64
|
...props.tags,
|
|
70
65
|
browser: getBrowserName(),
|
|
71
|
-
os:
|
|
66
|
+
os: getOSNameInternal(),
|
|
72
67
|
|
|
73
68
|
// Node does not like this so we need to check if it exists or not
|
|
74
69
|
// eslint-disable-next-line no-undef
|
|
75
|
-
domain:
|
|
76
|
-
|
|
77
|
-
user_id: this.webex.internal.device.userId
|
|
70
|
+
domain:
|
|
71
|
+
typeof window !== 'undefined' ? window.location.hostname || 'non-browser' : 'non-browser', // Check what else we could measure
|
|
78
72
|
};
|
|
79
73
|
|
|
80
|
-
try {
|
|
81
|
-
payload.tags.org_id = this.webex.credentials.getOrgId();
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
this.logger.info('metrics: unable to get orgId');
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
74
|
payload.fields = {
|
|
89
75
|
...props.fields,
|
|
90
76
|
browser_version: getBrowserVersion(),
|
|
91
77
|
os_version: getOSVersion(),
|
|
92
78
|
sdk_version: this.webex.version,
|
|
93
79
|
platform: 'Web',
|
|
94
|
-
spark_user_agent: getSparkUserAgent(this.webex)
|
|
80
|
+
spark_user_agent: getSparkUserAgent(this.webex),
|
|
81
|
+
client_id: this.webex.credentials.config.client_id,
|
|
95
82
|
};
|
|
96
83
|
|
|
97
|
-
|
|
98
84
|
payload.type = props.type || this.webex.config.metrics.type;
|
|
99
85
|
|
|
100
|
-
|
|
101
86
|
payload.context = {
|
|
102
87
|
...props.context,
|
|
103
88
|
app: {
|
|
104
|
-
version: this.webex.version
|
|
89
|
+
version: this.webex.version,
|
|
105
90
|
},
|
|
106
91
|
locale: 'en-US',
|
|
107
92
|
os: {
|
|
108
|
-
name:
|
|
109
|
-
version: getOSVersion()
|
|
110
|
-
}
|
|
93
|
+
name: getOSNameInternal(),
|
|
94
|
+
version: getOSVersion(),
|
|
95
|
+
},
|
|
111
96
|
};
|
|
112
97
|
|
|
113
|
-
|
|
114
98
|
if (props.eventPayload) {
|
|
115
99
|
payload.eventPayload = props.eventPayload;
|
|
116
100
|
}
|
|
@@ -121,7 +105,7 @@ const Metrics = WebexPlugin.extend({
|
|
|
121
105
|
|
|
122
106
|
if (preLoginId) {
|
|
123
107
|
const _payload = {
|
|
124
|
-
metrics: [payload]
|
|
108
|
+
metrics: [payload],
|
|
125
109
|
};
|
|
126
110
|
|
|
127
111
|
// Do not batch these because pre-login events occur during onboarding, so we will be partially blind
|
|
@@ -144,12 +128,12 @@ const Metrics = WebexPlugin.extend({
|
|
|
144
128
|
api: 'metrics',
|
|
145
129
|
resource: 'clientmetrics',
|
|
146
130
|
headers: {
|
|
147
|
-
'x-prelogin-userid': preLoginId
|
|
131
|
+
'x-prelogin-userid': preLoginId,
|
|
148
132
|
},
|
|
149
133
|
body: {},
|
|
150
134
|
qs: {
|
|
151
|
-
alias: true
|
|
152
|
-
}
|
|
135
|
+
alias: true,
|
|
136
|
+
},
|
|
153
137
|
});
|
|
154
138
|
},
|
|
155
139
|
|
|
@@ -161,20 +145,21 @@ const Metrics = WebexPlugin.extend({
|
|
|
161
145
|
resource: 'clientmetrics-prelogin',
|
|
162
146
|
headers: {
|
|
163
147
|
authorization: token.toString(),
|
|
164
|
-
'x-prelogin-userid': preLoginId
|
|
148
|
+
'x-prelogin-userid': preLoginId,
|
|
165
149
|
},
|
|
166
|
-
body: payload
|
|
167
|
-
})
|
|
150
|
+
body: payload,
|
|
151
|
+
})
|
|
152
|
+
);
|
|
168
153
|
},
|
|
169
154
|
|
|
170
155
|
submitCallDiagnosticEvents(payload) {
|
|
171
156
|
const event = {
|
|
172
157
|
type: 'diagnostic-event',
|
|
173
|
-
eventPayload: payload
|
|
158
|
+
eventPayload: payload,
|
|
174
159
|
};
|
|
175
160
|
|
|
176
161
|
return this.callDiagnosticEventsBatcher.request(event);
|
|
177
|
-
}
|
|
162
|
+
},
|
|
178
163
|
});
|
|
179
164
|
|
|
180
165
|
export default Metrics;
|
|
@@ -27,8 +27,8 @@ describe('plugin-metrics', () => {
|
|
|
27
27
|
beforeEach(() => {
|
|
28
28
|
webex = new MockWebex({
|
|
29
29
|
children: {
|
|
30
|
-
metrics: Metrics
|
|
31
|
-
}
|
|
30
|
+
metrics: Metrics,
|
|
31
|
+
},
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
webex.config.metrics = config.metrics;
|
|
@@ -37,7 +37,7 @@ describe('plugin-metrics', () => {
|
|
|
37
37
|
return Promise.resolve({
|
|
38
38
|
statusCode: 204,
|
|
39
39
|
body: undefined,
|
|
40
|
-
options
|
|
40
|
+
options,
|
|
41
41
|
});
|
|
42
42
|
};
|
|
43
43
|
sinon.spy(webex, 'request');
|
|
@@ -58,9 +58,10 @@ describe('plugin-metrics', () => {
|
|
|
58
58
|
it('clears the queue', () => {
|
|
59
59
|
clock.uninstall();
|
|
60
60
|
|
|
61
|
-
return webex.internal.metrics.batcher
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
return webex.internal.metrics.batcher
|
|
62
|
+
.request({
|
|
63
|
+
key: 'testMetric',
|
|
64
|
+
})
|
|
64
65
|
.then(() => {
|
|
65
66
|
assert.calledOnce(webex.request);
|
|
66
67
|
assert.lengthOf(webex.internal.metrics.batcher.queue, 0);
|
|
@@ -80,26 +81,28 @@ describe('plugin-metrics', () => {
|
|
|
80
81
|
|
|
81
82
|
sinon.stub(webex, 'request').callsFake((options) => {
|
|
82
83
|
options.headers = {
|
|
83
|
-
trackingid: count
|
|
84
|
+
trackingid: count,
|
|
84
85
|
};
|
|
85
86
|
|
|
86
87
|
count += 1;
|
|
87
88
|
if (count < 9) {
|
|
88
|
-
return Promise.reject(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
return Promise.reject(
|
|
90
|
+
new WebexHttpError.NetworkOrCORSError({
|
|
91
|
+
statusCode: 0,
|
|
92
|
+
options,
|
|
93
|
+
})
|
|
94
|
+
);
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
return Promise.resolve({
|
|
95
98
|
statusCode: 204,
|
|
96
99
|
body: undefined,
|
|
97
|
-
options
|
|
100
|
+
options,
|
|
98
101
|
});
|
|
99
102
|
});
|
|
100
103
|
|
|
101
104
|
const promise = webex.internal.metrics.batcher.request({
|
|
102
|
-
key: 'testMetric'
|
|
105
|
+
key: 'testMetric',
|
|
103
106
|
});
|
|
104
107
|
|
|
105
108
|
return promiseTick(50)
|
|
@@ -159,8 +162,16 @@ describe('plugin-metrics', () => {
|
|
|
159
162
|
.then(() => assert.lengthOf(webex.internal.metrics.batcher.queue, 0))
|
|
160
163
|
.then(() => promise)
|
|
161
164
|
.then(() => {
|
|
162
|
-
assert.lengthOf(
|
|
163
|
-
|
|
165
|
+
assert.lengthOf(
|
|
166
|
+
webex.request.args[1][0].body.metrics,
|
|
167
|
+
1,
|
|
168
|
+
'Reenqueuing the metric once did not increase the number of metrics to be submitted'
|
|
169
|
+
);
|
|
170
|
+
assert.lengthOf(
|
|
171
|
+
webex.request.args[2][0].body.metrics,
|
|
172
|
+
1,
|
|
173
|
+
'Reenqueuing the metric twice did not increase the number of metrics to be submitted'
|
|
174
|
+
);
|
|
164
175
|
assert.lengthOf(webex.internal.metrics.batcher.queue, 0);
|
|
165
176
|
});
|
|
166
177
|
});
|