@webex/internal-plugin-metrics 3.0.0-next.9 → 3.1.0-next.1
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/call-diagnostic/call-diagnostic-metrics-latencies.js +33 -9
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.js +1 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js +4 -2
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
- package/dist/client-metrics-prelogin-batcher.js +32 -0
- package/dist/client-metrics-prelogin-batcher.js.map +1 -0
- package/dist/metrics.js +6 -25
- package/dist/metrics.js.map +1 -1
- package/dist/metrics.types.js.map +1 -1
- package/dist/prelogin-metrics-batcher.js +1 -1
- package/dist/prelogin-metrics-batcher.js.map +1 -1
- package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +18 -7
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +2 -2
- package/dist/types/client-metrics-prelogin-batcher.d.ts +2 -0
- package/dist/types/metrics.types.d.ts +1 -1
- package/package.json +12 -12
- package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +36 -10
- package/src/call-diagnostic/call-diagnostic-metrics.ts +1 -0
- package/src/call-diagnostic/call-diagnostic-metrics.util.ts +11 -2
- package/src/client-metrics-prelogin-batcher.ts +26 -0
- package/src/metrics.js +5 -23
- package/src/metrics.types.ts +3 -1
- package/src/prelogin-metrics-batcher.ts +1 -1
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +9 -1
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +47 -22
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +57 -23
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +27 -13
- package/test/unit/spec/client-metrics-prelogin-batcher.ts +54 -0
- package/test/unit/spec/metrics.js +1 -31
- package/test/unit/spec/prelogin-metrics-batcher.ts +5 -3
|
@@ -252,6 +252,7 @@ export const prepareDiagnosticMetricItem = (webex: any, item: any) => {
|
|
|
252
252
|
joinTimes.meetingInfoReqResp = cdl.getMeetingInfoReqResp();
|
|
253
253
|
joinTimes.clickToInterstitial = cdl.getClickToInterstitial();
|
|
254
254
|
joinTimes.refreshCaptchaServiceReqResp = cdl.getRefreshCaptchaReqResp();
|
|
255
|
+
joinTimes.downloadIntelligenceModelsReqResp = cdl.getDownloadIntelligenceModelsReqResp();
|
|
255
256
|
break;
|
|
256
257
|
|
|
257
258
|
case 'client.call.initiated':
|
|
@@ -259,6 +260,7 @@ export const prepareDiagnosticMetricItem = (webex: any, item: any) => {
|
|
|
259
260
|
joinTimes.showInterstitialTime = cdl.getShowInterstitialTime();
|
|
260
261
|
joinTimes.registerWDMDeviceJMT = cdl.getRegisterWDMDeviceJMT();
|
|
261
262
|
joinTimes.getU2CTime = cdl.getU2CTime();
|
|
263
|
+
joinTimes.getReachabilityClustersReqResp = cdl.getReachabilityClustersReqResp();
|
|
262
264
|
break;
|
|
263
265
|
|
|
264
266
|
case 'client.locus.join.response':
|
|
@@ -381,11 +383,18 @@ export const generateClientErrorCodeForIceFailure = ({
|
|
|
381
383
|
errorCode = MISSING_ROAP_ANSWER_CLIENT_CODE;
|
|
382
384
|
}
|
|
383
385
|
|
|
384
|
-
if (
|
|
386
|
+
if (
|
|
387
|
+
signalingState === 'stable' &&
|
|
388
|
+
(iceConnectionState === 'connected' || iceConnectionState === 'disconnected')
|
|
389
|
+
) {
|
|
385
390
|
errorCode = DTLS_HANDSHAKE_FAILED_CLIENT_CODE;
|
|
386
391
|
}
|
|
387
392
|
|
|
388
|
-
if (
|
|
393
|
+
if (
|
|
394
|
+
signalingState !== 'have-local-offer' &&
|
|
395
|
+
iceConnectionState !== 'connected' &&
|
|
396
|
+
iceConnectionState !== 'disconnected'
|
|
397
|
+
) {
|
|
389
398
|
if (turnServerUsed) {
|
|
390
399
|
errorCode = ICE_FAILED_WITH_TURN_TLS_CLIENT_CODE;
|
|
391
400
|
} else {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import PreLoginMetricsBatcher from './prelogin-metrics-batcher';
|
|
2
|
+
|
|
3
|
+
const ClientMetricsPreloginBatcher = PreLoginMetricsBatcher.extend({
|
|
4
|
+
namespace: 'Metrics',
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Prepare item
|
|
8
|
+
* @param {any} item
|
|
9
|
+
* @returns {Promise<any>}
|
|
10
|
+
*/
|
|
11
|
+
prepareItem(item) {
|
|
12
|
+
// Add more defaults to payload when the clientmetrics endpoint evolves to support richer payloads
|
|
13
|
+
return Promise.resolve(item);
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Prepare request, add time sensitive date etc.
|
|
18
|
+
* @param {any[]} queue
|
|
19
|
+
* @returns {Promise<any[]>}
|
|
20
|
+
*/
|
|
21
|
+
prepareRequest(queue) {
|
|
22
|
+
return Promise.resolve(queue);
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export default ClientMetricsPreloginBatcher;
|
package/src/metrics.js
CHANGED
|
@@ -10,6 +10,7 @@ import {OS_NAME, OSMap, CLIENT_NAME} from './config';
|
|
|
10
10
|
|
|
11
11
|
import Batcher from './batcher';
|
|
12
12
|
import ClientMetricsBatcher from './client-metrics-batcher';
|
|
13
|
+
import ClientMetricsPreloginBatcher from './client-metrics-prelogin-batcher';
|
|
13
14
|
|
|
14
15
|
const {getOSName, getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
|
|
15
16
|
|
|
@@ -37,6 +38,7 @@ const Metrics = WebexPlugin.extend({
|
|
|
37
38
|
children: {
|
|
38
39
|
batcher: Batcher,
|
|
39
40
|
clientMetricsBatcher: ClientMetricsBatcher,
|
|
41
|
+
clientMetricsPreloginBatcher: ClientMetricsPreloginBatcher,
|
|
40
42
|
},
|
|
41
43
|
|
|
42
44
|
namespace: 'Metrics',
|
|
@@ -117,14 +119,9 @@ const Metrics = WebexPlugin.extend({
|
|
|
117
119
|
const payload = this.getClientMetricsPayload(eventName, props);
|
|
118
120
|
|
|
119
121
|
if (preLoginId) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
// Do not batch these because pre-login events occur during onboarding, so we will be partially blind
|
|
125
|
-
// to users' progress through the reg flow if we wait to persist pre-login metrics for people who drop off because
|
|
126
|
-
// their metrics will not post from a queue flush in time
|
|
127
|
-
return this.postPreLoginMetric(_payload, preLoginId);
|
|
122
|
+
this.clientMetricsPreloginBatcher.savePreLoginId(preLoginId);
|
|
123
|
+
|
|
124
|
+
return this.clientMetricsPreloginBatcher.request(payload);
|
|
128
125
|
}
|
|
129
126
|
|
|
130
127
|
return this.clientMetricsBatcher.request(payload);
|
|
@@ -149,21 +146,6 @@ const Metrics = WebexPlugin.extend({
|
|
|
149
146
|
},
|
|
150
147
|
});
|
|
151
148
|
},
|
|
152
|
-
|
|
153
|
-
postPreLoginMetric(payload, preLoginId) {
|
|
154
|
-
return this.webex.credentials.getClientToken().then((token) =>
|
|
155
|
-
this.request({
|
|
156
|
-
method: 'POST',
|
|
157
|
-
api: 'metrics',
|
|
158
|
-
resource: 'clientmetrics-prelogin',
|
|
159
|
-
headers: {
|
|
160
|
-
authorization: token.toString(),
|
|
161
|
-
'x-prelogin-userid': preLoginId,
|
|
162
|
-
},
|
|
163
|
-
body: payload,
|
|
164
|
-
})
|
|
165
|
-
);
|
|
166
|
-
},
|
|
167
149
|
});
|
|
168
150
|
|
|
169
151
|
export default Metrics;
|
package/src/metrics.types.ts
CHANGED
|
@@ -169,9 +169,11 @@ export type BuildClientEventFetchRequestOptions = (args: {
|
|
|
169
169
|
export type PreComputedLatencies =
|
|
170
170
|
| 'internal.client.pageJMT'
|
|
171
171
|
| 'internal.download.time'
|
|
172
|
+
| 'internal.get.cluster.time'
|
|
172
173
|
| 'internal.click.to.interstitial'
|
|
173
174
|
| 'internal.refresh.captcha.time'
|
|
174
175
|
| 'internal.exchange.ci.token.time'
|
|
175
176
|
| 'internal.get.u2c.time'
|
|
176
177
|
| 'internal.call.init.join.req'
|
|
177
|
-
| 'internal.other.app.api.time'
|
|
178
|
+
| 'internal.other.app.api.time'
|
|
179
|
+
| 'internal.api.fetch.intelligence.models';
|
|
@@ -48,7 +48,7 @@ const PreLoginMetricsBatcher = Batcher.extend({
|
|
|
48
48
|
* @returns {Promise<any>}
|
|
49
49
|
*/
|
|
50
50
|
submitHttpRequest(payload: any) {
|
|
51
|
-
const batchId = uniqueId('prelogin-
|
|
51
|
+
const batchId = uniqueId('prelogin-batch-');
|
|
52
52
|
if (this.preLoginId === undefined) {
|
|
53
53
|
this.webex.logger.error(
|
|
54
54
|
PRE_LOGIN_METRICS_IDENTIFIER,
|
|
@@ -106,6 +106,9 @@ describe('plugin-metrics', () => {
|
|
|
106
106
|
webex.internal.newMetrics.callDiagnosticLatencies.getRefreshCaptchaReqResp = sinon
|
|
107
107
|
.stub()
|
|
108
108
|
.returns(10);
|
|
109
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getDownloadIntelligenceModelsReqResp =
|
|
110
|
+
sinon.stub().returns(42);
|
|
111
|
+
|
|
109
112
|
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
110
113
|
//@ts-ignore
|
|
111
114
|
{event: {name: 'client.interstitial-window.launched'}}
|
|
@@ -123,6 +126,7 @@ describe('plugin-metrics', () => {
|
|
|
123
126
|
clickToInterstitial: 10,
|
|
124
127
|
meetingInfoReqResp: 10,
|
|
125
128
|
refreshCaptchaServiceReqResp: 10,
|
|
129
|
+
downloadIntelligenceModelsReqResp: 42,
|
|
126
130
|
},
|
|
127
131
|
});
|
|
128
132
|
assert.lengthOf(
|
|
@@ -138,6 +142,9 @@ describe('plugin-metrics', () => {
|
|
|
138
142
|
webex.internal.newMetrics.callDiagnosticLatencies.getU2CTime = sinon
|
|
139
143
|
.stub()
|
|
140
144
|
.returns(20);
|
|
145
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getReachabilityClustersReqResp = sinon
|
|
146
|
+
.stub()
|
|
147
|
+
.returns(10);
|
|
141
148
|
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
142
149
|
//@ts-ignore
|
|
143
150
|
{event: {name: 'client.call.initiated'}}
|
|
@@ -154,7 +161,8 @@ describe('plugin-metrics', () => {
|
|
|
154
161
|
meetingInfoReqResp: 10,
|
|
155
162
|
registerWDMDeviceJMT: 10,
|
|
156
163
|
showInterstitialTime: 10,
|
|
157
|
-
getU2CTime: 20
|
|
164
|
+
getU2CTime: 20,
|
|
165
|
+
getReachabilityClustersReqResp: 10
|
|
158
166
|
},
|
|
159
167
|
});
|
|
160
168
|
assert.lengthOf(
|
|
@@ -51,29 +51,29 @@ describe('internal-plugin-metrics', () => {
|
|
|
51
51
|
assert.deepEqual(cdl.precomputedLatencies.get('internal.client.pageJMT'), 20);
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
it('should overwrite latency when
|
|
54
|
+
it('should overwrite latency when accumulate is false', () => {
|
|
55
55
|
assert.deepEqual(cdl.precomputedLatencies.size, 0);
|
|
56
|
-
cdl.saveLatency('internal.client.pageJMT', 10,
|
|
56
|
+
cdl.saveLatency('internal.client.pageJMT', 10, false);
|
|
57
57
|
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
58
58
|
assert.deepEqual(cdl.precomputedLatencies.get('internal.client.pageJMT'), 10);
|
|
59
|
-
cdl.saveLatency('internal.client.pageJMT', 20,
|
|
59
|
+
cdl.saveLatency('internal.client.pageJMT', 20, false);
|
|
60
60
|
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
61
61
|
assert.deepEqual(cdl.precomputedLatencies.get('internal.client.pageJMT'), 20);
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
it('should save latency correctly when
|
|
64
|
+
it('should save latency correctly when accumulate is true', () => {
|
|
65
65
|
assert.deepEqual(cdl.precomputedLatencies.size, 0);
|
|
66
|
-
cdl.saveLatency('internal.client.pageJMT', 10,
|
|
66
|
+
cdl.saveLatency('internal.client.pageJMT', 10, true);
|
|
67
67
|
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
68
68
|
assert.deepEqual(cdl.precomputedLatencies.get('internal.client.pageJMT'), 10);
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
it('should save latency correctly when
|
|
71
|
+
it('should save latency correctly when accumulate is true and there is existing value', () => {
|
|
72
72
|
assert.deepEqual(cdl.precomputedLatencies.size, 0);
|
|
73
73
|
cdl.saveLatency('internal.client.pageJMT', 10);
|
|
74
74
|
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
75
75
|
assert.deepEqual(cdl.precomputedLatencies.get('internal.client.pageJMT'), 10);
|
|
76
|
-
cdl.saveLatency('internal.client.pageJMT', 10,
|
|
76
|
+
cdl.saveLatency('internal.client.pageJMT', 10, true);
|
|
77
77
|
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
78
78
|
assert.deepEqual(cdl.precomputedLatencies.get('internal.client.pageJMT'), 20);
|
|
79
79
|
});
|
|
@@ -108,8 +108,13 @@ describe('internal-plugin-metrics', () => {
|
|
|
108
108
|
cdl.saveTimestamp({key: 'client.alert.displayed'});
|
|
109
109
|
cdl.saveTimestamp({key: 'client.alert.removed'});
|
|
110
110
|
assert.deepEqual(cdl.latencyTimestamps.size, 2);
|
|
111
|
+
cdl.saveLatency('internal.api.fetch.intelligence.models', 42);
|
|
112
|
+
assert.deepEqual(cdl.precomputedLatencies.size, 1);
|
|
113
|
+
|
|
111
114
|
cdl.clearTimestamps();
|
|
115
|
+
|
|
112
116
|
assert.deepEqual(cdl.latencyTimestamps.size, 0);
|
|
117
|
+
assert.deepEqual(cdl.precomputedLatencies.size, 0);
|
|
113
118
|
});
|
|
114
119
|
|
|
115
120
|
it('should calculate diff between timestamps correctly', () => {
|
|
@@ -145,9 +150,9 @@ describe('internal-plugin-metrics', () => {
|
|
|
145
150
|
let clock;
|
|
146
151
|
let saveLatencySpy;
|
|
147
152
|
|
|
148
|
-
beforeEach(() => {
|
|
149
|
-
clock = sinon.useFakeTimers();
|
|
150
|
-
|
|
153
|
+
beforeEach(() => {
|
|
154
|
+
clock = sinon.useFakeTimers();
|
|
155
|
+
|
|
151
156
|
saveLatencySpy = sinon.stub(cdl, 'saveLatency');
|
|
152
157
|
});
|
|
153
158
|
|
|
@@ -155,54 +160,56 @@ describe('internal-plugin-metrics', () => {
|
|
|
155
160
|
clock.restore();
|
|
156
161
|
sinon.restore();
|
|
157
162
|
});
|
|
158
|
-
|
|
159
|
-
it('checks measureLatency with
|
|
163
|
+
|
|
164
|
+
it('checks measureLatency with accumulate false', async () => {
|
|
160
165
|
const key = 'internal.client.pageJMT';
|
|
161
|
-
const
|
|
166
|
+
const accumulate = false;
|
|
167
|
+
|
|
162
168
|
const callbackStub = sinon.stub().callsFake(() => {
|
|
163
169
|
clock.tick(50);
|
|
164
170
|
return Promise.resolve('test');
|
|
165
171
|
});
|
|
166
172
|
|
|
167
|
-
|
|
173
|
+
// accumulate should be false by default
|
|
174
|
+
const promise = cdl.measureLatency(callbackStub, 'internal.client.pageJMT');
|
|
168
175
|
|
|
169
176
|
const resolvedValue = await promise;
|
|
170
177
|
assert.deepEqual(resolvedValue, 'test');
|
|
171
178
|
assert.calledOnceWithExactly(callbackStub);
|
|
172
|
-
assert.calledOnceWithExactly(saveLatencySpy, key, 50,
|
|
179
|
+
assert.calledOnceWithExactly(saveLatencySpy, key, 50, accumulate);
|
|
173
180
|
});
|
|
174
181
|
|
|
175
|
-
it('checks measureLatency with
|
|
182
|
+
it('checks measureLatency with accumulate true', async () => {
|
|
176
183
|
const key = 'internal.download.time';
|
|
177
|
-
const
|
|
184
|
+
const accumulate = true;
|
|
178
185
|
const callbackStub = sinon.stub().callsFake(() => {
|
|
179
186
|
clock.tick(20);
|
|
180
187
|
return Promise.resolve('test123');
|
|
181
188
|
});
|
|
182
189
|
|
|
183
|
-
const promise = cdl.measureLatency(callbackStub, 'internal.download.time',
|
|
190
|
+
const promise = cdl.measureLatency(callbackStub, 'internal.download.time', accumulate);
|
|
184
191
|
|
|
185
192
|
const resolvedValue = await promise;
|
|
186
193
|
assert.deepEqual(resolvedValue, 'test123');
|
|
187
194
|
assert.calledOnceWithExactly(callbackStub);
|
|
188
|
-
assert.calledOnceWithExactly(saveLatencySpy, key, 20,
|
|
195
|
+
assert.calledOnceWithExactly(saveLatencySpy, key, 20, accumulate);
|
|
189
196
|
});
|
|
190
197
|
|
|
191
198
|
it('checks measureLatency when callBack rejects', async () => {
|
|
192
199
|
const key = 'internal.client.pageJMT';
|
|
193
|
-
const
|
|
200
|
+
const accumulate = false;
|
|
194
201
|
const error = new Error('some error');
|
|
195
202
|
const callbackStub = sinon.stub().callsFake(() => {
|
|
196
203
|
clock.tick(50);
|
|
197
204
|
return Promise.reject(error);
|
|
198
205
|
});
|
|
199
206
|
|
|
200
|
-
const promise = cdl.measureLatency(callbackStub, 'internal.client.pageJMT',
|
|
207
|
+
const promise = cdl.measureLatency(callbackStub, 'internal.client.pageJMT', accumulate);
|
|
201
208
|
|
|
202
209
|
const rejectedValue = await assert.isRejected(promise);
|
|
203
210
|
assert.deepEqual(rejectedValue, error);
|
|
204
211
|
assert.calledOnceWithExactly(callbackStub);
|
|
205
|
-
assert.calledOnceWithExactly(saveLatencySpy, key, 50,
|
|
212
|
+
assert.calledOnceWithExactly(saveLatencySpy, key, 50, accumulate);
|
|
206
213
|
});
|
|
207
214
|
});
|
|
208
215
|
|
|
@@ -224,6 +231,24 @@ describe('internal-plugin-metrics', () => {
|
|
|
224
231
|
});
|
|
225
232
|
});
|
|
226
233
|
|
|
234
|
+
describe('getReachabilityClustersReqResp', () => {
|
|
235
|
+
it('returns undefined when no precomputed value available', () => {
|
|
236
|
+
assert.deepEqual(cdl.getReachabilityClustersReqResp(), undefined);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('returns the correct value', () => {
|
|
240
|
+
cdl.saveLatency('internal.get.cluster.time', 123);
|
|
241
|
+
|
|
242
|
+
assert.deepEqual(cdl.getReachabilityClustersReqResp(), 123);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('returns the correct whole number', () => {
|
|
246
|
+
cdl.saveLatency('internal.get.cluster.time', 321.44);
|
|
247
|
+
|
|
248
|
+
assert.deepEqual(cdl.getReachabilityClustersReqResp(), 321);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
227
252
|
describe('getExchangeCITokenJMT', () => {
|
|
228
253
|
it('returns undefined when no precomputed value available', () => {
|
|
229
254
|
assert.deepEqual(cdl.getExchangeCITokenJMT(), undefined);
|
|
@@ -541,7 +541,10 @@ describe('internal-plugin-metrics', () => {
|
|
|
541
541
|
it('should prepare diagnostic event successfully', () => {
|
|
542
542
|
const options = {meetingId: fakeMeeting.id};
|
|
543
543
|
const getOriginStub = sinon.stub(cd, 'getOrigin').returns({origin: 'fake-origin'});
|
|
544
|
-
const clearEmptyKeysRecursivelyStub = sinon.stub(
|
|
544
|
+
const clearEmptyKeysRecursivelyStub = sinon.stub(
|
|
545
|
+
CallDiagnosticUtils,
|
|
546
|
+
'clearEmptyKeysRecursively'
|
|
547
|
+
);
|
|
545
548
|
|
|
546
549
|
const res = cd.prepareDiagnosticEvent(
|
|
547
550
|
{
|
|
@@ -896,11 +899,13 @@ describe('internal-plugin-metrics', () => {
|
|
|
896
899
|
options
|
|
897
900
|
);
|
|
898
901
|
assert.notCalled(submitToCallDiagnosticsSpy);
|
|
899
|
-
assert.calledWith(
|
|
902
|
+
assert.calledWith(
|
|
903
|
+
submitToCallDiagnosticsPreLoginSpy,
|
|
904
|
+
{
|
|
900
905
|
eventId: 'my-fake-id',
|
|
901
906
|
version: 1,
|
|
902
|
-
origin: {
|
|
903
|
-
originTime: {
|
|
907
|
+
origin: {origin: 'fake-origin'},
|
|
908
|
+
originTime: {triggered: now.toISOString(), sent: 'not_defined_yet'},
|
|
904
909
|
senderCountryCode: 'UK',
|
|
905
910
|
event: {
|
|
906
911
|
name: 'client.alert.displayed',
|
|
@@ -912,12 +917,14 @@ describe('internal-plugin-metrics', () => {
|
|
|
912
917
|
orgId: 'orgId',
|
|
913
918
|
locusUrl: 'locus-url',
|
|
914
919
|
webexConferenceIdStr: 'webexConferenceIdStr1',
|
|
915
|
-
globalMeetingId: 'globalMeetingId1'
|
|
920
|
+
globalMeetingId: 'globalMeetingId1',
|
|
916
921
|
},
|
|
917
|
-
eventData: {
|
|
918
|
-
loginType: 'login-ci'
|
|
922
|
+
eventData: {webClientDomain: 'whatever'},
|
|
923
|
+
loginType: 'login-ci',
|
|
919
924
|
},
|
|
920
|
-
|
|
925
|
+
},
|
|
926
|
+
options.preLoginId
|
|
927
|
+
);
|
|
921
928
|
});
|
|
922
929
|
|
|
923
930
|
it('should use meeting loginType if present and meetingId provided', () => {
|
|
@@ -1382,7 +1389,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1382
1389
|
});
|
|
1383
1390
|
});
|
|
1384
1391
|
|
|
1385
|
-
describe(
|
|
1392
|
+
describe('#submitToCallDiagnostics', () => {
|
|
1386
1393
|
it('should send request to call diagnostic batcher', () => {
|
|
1387
1394
|
const requestStub = sinon.stub();
|
|
1388
1395
|
//@ts-ignore
|
|
@@ -1391,7 +1398,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1391
1398
|
cd.submitToCallDiagnostics({event: 'test'});
|
|
1392
1399
|
assert.calledWith(requestStub, {eventPayload: {event: 'test'}, type: ['diagnostic-event']});
|
|
1393
1400
|
});
|
|
1394
|
-
})
|
|
1401
|
+
});
|
|
1395
1402
|
|
|
1396
1403
|
describe('#submitMQE', () => {
|
|
1397
1404
|
it('submits the event correctly', () => {
|
|
@@ -1445,6 +1452,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1445
1452
|
},
|
|
1446
1453
|
eventData: {webClientDomain: 'whatever'},
|
|
1447
1454
|
intervals: [{}],
|
|
1455
|
+
callingServiceType: 'LOCUS',
|
|
1448
1456
|
sourceMetadata: {
|
|
1449
1457
|
applicationSoftwareType: 'webex-js-sdk',
|
|
1450
1458
|
applicationSoftwareVersion: 'webex-version',
|
|
@@ -1480,6 +1488,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1480
1488
|
},
|
|
1481
1489
|
eventData: {webClientDomain: 'whatever'},
|
|
1482
1490
|
intervals: [{}],
|
|
1491
|
+
callingServiceType: 'LOCUS',
|
|
1483
1492
|
sourceMetadata: {
|
|
1484
1493
|
applicationSoftwareType: 'webex-js-sdk',
|
|
1485
1494
|
applicationSoftwareVersion: 'webex-version',
|
|
@@ -1513,6 +1522,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
1513
1522
|
},
|
|
1514
1523
|
eventData: {webClientDomain: 'whatever'},
|
|
1515
1524
|
intervals: [{}],
|
|
1525
|
+
callingServiceType: 'LOCUS',
|
|
1516
1526
|
sourceMetadata: {
|
|
1517
1527
|
applicationSoftwareType: 'webex-js-sdk',
|
|
1518
1528
|
applicationSoftwareVersion: 'webex-version',
|
|
@@ -2006,12 +2016,16 @@ describe('internal-plugin-metrics', () => {
|
|
|
2006
2016
|
|
|
2007
2017
|
describe('httpStatusCode', () => {
|
|
2008
2018
|
it('should include httpStatusCode for browser media errors', () => {
|
|
2009
|
-
const res = cd.generateClientEventErrorPayload({
|
|
2019
|
+
const res = cd.generateClientEventErrorPayload({
|
|
2020
|
+
name: 'PermissionDeniedError',
|
|
2021
|
+
message: 'bad times',
|
|
2022
|
+
statusCode: 401,
|
|
2023
|
+
});
|
|
2010
2024
|
assert.deepEqual(res, {
|
|
2011
2025
|
category: 'expected',
|
|
2012
2026
|
errorCode: 4032,
|
|
2013
2027
|
errorData: {
|
|
2014
|
-
errorName: 'PermissionDeniedError'
|
|
2028
|
+
errorName: 'PermissionDeniedError',
|
|
2015
2029
|
},
|
|
2016
2030
|
errorDescription: 'CameraPermissionDenied',
|
|
2017
2031
|
fatal: true,
|
|
@@ -2024,12 +2038,16 @@ describe('internal-plugin-metrics', () => {
|
|
|
2024
2038
|
});
|
|
2025
2039
|
|
|
2026
2040
|
it('should include httpStatusCode for SdpOfferCreationErrors', () => {
|
|
2027
|
-
const res = cd.generateClientEventErrorPayload({
|
|
2041
|
+
const res = cd.generateClientEventErrorPayload({
|
|
2042
|
+
name: 'SdpOfferCreationError',
|
|
2043
|
+
message: 'bad times',
|
|
2044
|
+
statusCode: 404,
|
|
2045
|
+
});
|
|
2028
2046
|
assert.deepEqual(res, {
|
|
2029
2047
|
category: 'media',
|
|
2030
2048
|
errorCode: 2050,
|
|
2031
2049
|
errorData: {
|
|
2032
|
-
errorName: 'SdpOfferCreationError'
|
|
2050
|
+
errorName: 'SdpOfferCreationError',
|
|
2033
2051
|
},
|
|
2034
2052
|
errorDescription: 'SdpOfferCreationError',
|
|
2035
2053
|
fatal: true,
|
|
@@ -2042,7 +2060,11 @@ describe('internal-plugin-metrics', () => {
|
|
|
2042
2060
|
});
|
|
2043
2061
|
|
|
2044
2062
|
it('should include httpStatusCode for service error codes', () => {
|
|
2045
|
-
const res = cd.generateClientEventErrorPayload({
|
|
2063
|
+
const res = cd.generateClientEventErrorPayload({
|
|
2064
|
+
body: {errorCode: 58400},
|
|
2065
|
+
message: 'bad times',
|
|
2066
|
+
statusCode: 400,
|
|
2067
|
+
});
|
|
2046
2068
|
assert.deepEqual(res, {
|
|
2047
2069
|
category: 'signaling',
|
|
2048
2070
|
errorCode: 4100,
|
|
@@ -2057,7 +2079,11 @@ describe('internal-plugin-metrics', () => {
|
|
|
2057
2079
|
});
|
|
2058
2080
|
|
|
2059
2081
|
it('should include httpStatusCode for locus service error codes', () => {
|
|
2060
|
-
const res = cd.generateClientEventErrorPayload({
|
|
2082
|
+
const res = cd.generateClientEventErrorPayload({
|
|
2083
|
+
body: {errorCode: 2403001},
|
|
2084
|
+
message: 'bad times',
|
|
2085
|
+
statusCode: 400,
|
|
2086
|
+
});
|
|
2061
2087
|
assert.deepEqual(res, {
|
|
2062
2088
|
category: 'expected',
|
|
2063
2089
|
errorCode: 3007,
|
|
@@ -2072,7 +2098,11 @@ describe('internal-plugin-metrics', () => {
|
|
|
2072
2098
|
});
|
|
2073
2099
|
|
|
2074
2100
|
it('should include httpStatusCode for meetingInfo service error codes', () => {
|
|
2075
|
-
const res = cd.generateClientEventErrorPayload({
|
|
2101
|
+
const res = cd.generateClientEventErrorPayload({
|
|
2102
|
+
body: {data: {meetingInfo: {}}},
|
|
2103
|
+
message: 'bad times',
|
|
2104
|
+
statusCode: 400,
|
|
2105
|
+
});
|
|
2076
2106
|
assert.deepEqual(res, {
|
|
2077
2107
|
category: 'signaling',
|
|
2078
2108
|
errorCode: 4100,
|
|
@@ -2087,8 +2117,10 @@ describe('internal-plugin-metrics', () => {
|
|
|
2087
2117
|
});
|
|
2088
2118
|
|
|
2089
2119
|
it('should include httpStatusCode for network errors', () => {
|
|
2090
|
-
const error = new WebexHttpError.NetworkOrCORSError(
|
|
2091
|
-
|
|
2120
|
+
const error = new WebexHttpError.NetworkOrCORSError({
|
|
2121
|
+
statusCode: 400,
|
|
2122
|
+
options: {service: '', headers: {}},
|
|
2123
|
+
});
|
|
2092
2124
|
const res = cd.generateClientEventErrorPayload(error);
|
|
2093
2125
|
assert.deepEqual(res, {
|
|
2094
2126
|
category: 'network',
|
|
@@ -2104,8 +2136,10 @@ describe('internal-plugin-metrics', () => {
|
|
|
2104
2136
|
});
|
|
2105
2137
|
|
|
2106
2138
|
it('should include httpStatusCode for unauthorized errors', () => {
|
|
2107
|
-
const error = new WebexHttpError.Unauthorized(
|
|
2108
|
-
|
|
2139
|
+
const error = new WebexHttpError.Unauthorized({
|
|
2140
|
+
statusCode: 401,
|
|
2141
|
+
options: {service: '', headers: {}},
|
|
2142
|
+
});
|
|
2109
2143
|
const res = cd.generateClientEventErrorPayload(error);
|
|
2110
2144
|
assert.deepEqual(res, {
|
|
2111
2145
|
category: 'network',
|
|
@@ -2308,7 +2342,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
2308
2342
|
});
|
|
2309
2343
|
});
|
|
2310
2344
|
|
|
2311
|
-
describe(
|
|
2345
|
+
describe('#submitToCallDiagnosticsPreLogin', () => {
|
|
2312
2346
|
it('should send request to call diagnostic batcher and saves preLoginId', () => {
|
|
2313
2347
|
const requestStub = sinon.stub();
|
|
2314
2348
|
//@ts-ignore
|
|
@@ -2321,7 +2355,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
2321
2355
|
assert.calledWith(cd.preLoginMetricsBatcher.savePreLoginId, preLoginId);
|
|
2322
2356
|
assert.calledWith(requestStub, {eventPayload: {event: 'test'}, type: ['diagnostic-event']});
|
|
2323
2357
|
});
|
|
2324
|
-
})
|
|
2358
|
+
});
|
|
2325
2359
|
|
|
2326
2360
|
describe('#isServiceErrorExpected', () => {
|
|
2327
2361
|
it('returns true for code mapped to "expected"', () => {
|
|
@@ -301,17 +301,23 @@ describe('internal-plugin-metrics', () => {
|
|
|
301
301
|
|
|
302
302
|
[
|
|
303
303
|
['client.exit.app', {}],
|
|
304
|
-
[
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
304
|
+
[
|
|
305
|
+
'client.login.end',
|
|
306
|
+
{
|
|
307
|
+
joinTimes: {
|
|
308
|
+
otherAppApiReqResp: undefined,
|
|
309
|
+
exchangeCITokenJMT: undefined,
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
],
|
|
313
|
+
[
|
|
314
|
+
'client.webexapp.launched',
|
|
315
|
+
{
|
|
316
|
+
joinTimes: {
|
|
317
|
+
downloadTime: undefined,
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
],
|
|
315
321
|
[
|
|
316
322
|
'client.interstitial-window.launched',
|
|
317
323
|
{
|
|
@@ -319,6 +325,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
319
325
|
clickToInterstitial: undefined,
|
|
320
326
|
meetingInfoReqResp: undefined,
|
|
321
327
|
refreshCaptchaServiceReqResp: undefined,
|
|
328
|
+
downloadIntelligenceModelsReqResp: undefined,
|
|
322
329
|
},
|
|
323
330
|
},
|
|
324
331
|
],
|
|
@@ -329,7 +336,8 @@ describe('internal-plugin-metrics', () => {
|
|
|
329
336
|
showInterstitialTime: undefined,
|
|
330
337
|
meetingInfoReqResp: undefined,
|
|
331
338
|
registerWDMDeviceJMT: undefined,
|
|
332
|
-
getU2CTime: undefined
|
|
339
|
+
getU2CTime: undefined,
|
|
340
|
+
getReachabilityClustersReqResp: undefined,
|
|
333
341
|
},
|
|
334
342
|
},
|
|
335
343
|
],
|
|
@@ -345,7 +353,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
345
353
|
interstitialToJoinOK: undefined,
|
|
346
354
|
totalJmt: undefined,
|
|
347
355
|
clientJmt: undefined,
|
|
348
|
-
downloadTime: undefined
|
|
356
|
+
downloadTime: undefined,
|
|
349
357
|
},
|
|
350
358
|
},
|
|
351
359
|
],
|
|
@@ -607,6 +615,12 @@ describe('internal-plugin-metrics', () => {
|
|
|
607
615
|
turnServerUsed: true,
|
|
608
616
|
errorCode: DTLS_HANDSHAKE_FAILED_CLIENT_CODE,
|
|
609
617
|
},
|
|
618
|
+
{
|
|
619
|
+
signalingState: 'stable',
|
|
620
|
+
iceConnectionState: 'disconnected',
|
|
621
|
+
turnServerUsed: true,
|
|
622
|
+
errorCode: DTLS_HANDSHAKE_FAILED_CLIENT_CODE,
|
|
623
|
+
},
|
|
610
624
|
{
|
|
611
625
|
signalingState: 'stable',
|
|
612
626
|
iceConnectionState: 'failed',
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {assert} from '@webex/test-helper-chai';
|
|
6
|
+
import MockWebex from '@webex/test-helper-mock-webex';
|
|
7
|
+
import sinon from 'sinon';
|
|
8
|
+
import Metrics from '@webex/internal-plugin-metrics';
|
|
9
|
+
import PreLoginMetricsBatcher from '@webex/internal-plugin-metrics';
|
|
10
|
+
import ClientMetricsPreloginBatcher from '@webex/internal-plugin-metrics';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
describe('internal-plugin-metrics', () => {
|
|
14
|
+
describe('ClientMetricsPreloginBatcher', () => {
|
|
15
|
+
let webex;
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
//@ts-ignore
|
|
19
|
+
webex = new MockWebex({
|
|
20
|
+
children: {
|
|
21
|
+
metrics: Metrics,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
webex.request = (options) =>
|
|
26
|
+
Promise.resolve({body: {items: []}, waitForServiceTimeout: 15, options});
|
|
27
|
+
|
|
28
|
+
sinon.spy(webex, 'request');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
sinon.restore();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should be an instance of PreLoginMetricsBatcher', () => {
|
|
36
|
+
const clientMetricsPreloginBatcher = new ClientMetricsPreloginBatcher();
|
|
37
|
+
assert.instanceOf(clientMetricsPreloginBatcher, PreLoginMetricsBatcher);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
it('checks prepareItem', async () => {
|
|
42
|
+
const testItem = {id: 1};
|
|
43
|
+
const resultPromise = await webex.internal.metrics.clientMetricsPreloginBatcher.prepareItem(testItem);
|
|
44
|
+
assert.strictEqual(resultPromise, testItem);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('checks prepareRequest', async () => {
|
|
48
|
+
const testQueue = [];
|
|
49
|
+
|
|
50
|
+
const resultPromise = await webex.internal.metrics.clientMetricsPreloginBatcher.prepareRequest(testQueue);
|
|
51
|
+
assert.strictEqual(resultPromise, testQueue);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|