@webex/internal-plugin-metrics 3.12.0-task-refactor.1 → 3.12.0-webex-services-ready.2
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/batcher.js +3 -0
- package/dist/batcher.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +23 -0
- package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +68 -50
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.js +60 -8
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js +44 -4
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
- package/dist/call-diagnostic/config.js +17 -3
- package/dist/call-diagnostic/config.js.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/generic-metrics.js +8 -6
- package/dist/generic-metrics.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/metrics.js +1 -1
- package/dist/metrics.types.js.map +1 -1
- package/dist/new-metrics.js +56 -20
- package/dist/new-metrics.js.map +1 -1
- package/dist/prelogin-metrics-batcher.js +23 -0
- package/dist/prelogin-metrics-batcher.js.map +1 -1
- package/dist/prelogin-metrics.js +106 -0
- package/dist/prelogin-metrics.js.map +1 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +9 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +57 -20
- package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +23 -2
- package/dist/types/call-diagnostic/config.d.ts +6 -19
- package/dist/types/config.d.ts +16 -15
- package/dist/types/index.d.ts +2 -1
- package/dist/types/metrics.types.d.ts +4 -4
- package/dist/types/new-metrics.d.ts +12 -0
- package/dist/types/prelogin-metrics.d.ts +47 -0
- package/package.json +11 -11
- package/src/batcher.js +4 -0
- package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +26 -0
- package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +139 -70
- package/src/call-diagnostic/call-diagnostic-metrics.ts +52 -1
- package/src/call-diagnostic/call-diagnostic-metrics.util.ts +49 -2
- package/src/call-diagnostic/config.ts +15 -0
- package/src/config.js +1 -0
- package/src/generic-metrics.ts +6 -6
- package/src/index.ts +2 -0
- package/src/metrics.types.ts +3 -3
- package/src/new-metrics.ts +42 -0
- package/src/prelogin-metrics-batcher.ts +26 -0
- package/src/prelogin-metrics.ts +94 -0
- package/test/unit/spec/batcher.js +43 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +183 -11
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +324 -366
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +724 -159
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +92 -3
- package/test/unit/spec/prelogin-metrics-batcher.ts +190 -36
- package/test/unit/spec/prelogin-metrics.ts +132 -0
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
ICE_AND_REACHABILITY_FAILED_CLIENT_CODE,
|
|
11
11
|
ICE_FAILED_WITH_TURN_TLS_CLIENT_CODE,
|
|
12
12
|
MISSING_ROAP_ANSWER_CLIENT_CODE,
|
|
13
|
+
BROWSER_MEDIA_ERROR_NAME_TO_CLIENT_ERROR_CODES_MAP,
|
|
13
14
|
} from '../../../../src/call-diagnostic/config';
|
|
14
15
|
import Logger from '@webex/plugin-logger';
|
|
15
16
|
|
|
@@ -26,6 +27,7 @@ const {
|
|
|
26
27
|
isUnauthorizedError,
|
|
27
28
|
generateClientErrorCodeForIceFailure,
|
|
28
29
|
isSdpOfferCreationError,
|
|
30
|
+
isWebrtcApiNotAvailableError,
|
|
29
31
|
} = CallDiagnosticUtils;
|
|
30
32
|
|
|
31
33
|
describe('internal-plugin-metrics', () => {
|
|
@@ -205,6 +207,29 @@ describe('internal-plugin-metrics', () => {
|
|
|
205
207
|
});
|
|
206
208
|
});
|
|
207
209
|
|
|
210
|
+
describe('isWebrtcApiNotAvailableError', () => {
|
|
211
|
+
type TestWebrtcApiNotAvailableError = {
|
|
212
|
+
code: number;
|
|
213
|
+
message: string;
|
|
214
|
+
name: string;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const error: TestWebrtcApiNotAvailableError = {
|
|
218
|
+
code: 30007,
|
|
219
|
+
name: 'WebrtcApiNotAvailableError',
|
|
220
|
+
message: 'RTCPeerConnection API is not available in this environment',
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
[
|
|
224
|
+
['WebrtcApiNotAvailableError', error, true],
|
|
225
|
+
['generic error', new Error('this is an error'), false],
|
|
226
|
+
].forEach(([errorType, rawError, expected]) => {
|
|
227
|
+
it(`for ${errorType} rawError returns the correct result`, () => {
|
|
228
|
+
assert.strictEqual(isWebrtcApiNotAvailableError(rawError), expected);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
208
233
|
describe('isBrowserMediaErrorName', () => {
|
|
209
234
|
[
|
|
210
235
|
['PermissionDeniedError', true],
|
|
@@ -286,7 +311,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
286
311
|
origin: {
|
|
287
312
|
buildType: 'prod',
|
|
288
313
|
networkType: 'unknown',
|
|
289
|
-
upgradeChannel: expectedUpgradeChannel
|
|
314
|
+
upgradeChannel: expectedUpgradeChannel,
|
|
290
315
|
},
|
|
291
316
|
event: {name: eventName, ...expectedEvent},
|
|
292
317
|
},
|
|
@@ -368,7 +393,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
368
393
|
totalJmt: undefined,
|
|
369
394
|
clientJmt: undefined,
|
|
370
395
|
downloadTime: undefined,
|
|
371
|
-
clickToInterstitialWithUserDelay:
|
|
396
|
+
clickToInterstitialWithUserDelay: undefined,
|
|
372
397
|
totalJMTWithUserDelay: undefined,
|
|
373
398
|
},
|
|
374
399
|
},
|
|
@@ -405,7 +430,6 @@ describe('internal-plugin-metrics', () => {
|
|
|
405
430
|
totalMediaJMT: undefined,
|
|
406
431
|
interstitialToMediaOKJMT: undefined,
|
|
407
432
|
callInitMediaEngineReady: undefined,
|
|
408
|
-
stayLobbyTime: undefined,
|
|
409
433
|
totalMediaJMTWithUserDelay: undefined,
|
|
410
434
|
totalJMTWithUserDelay: undefined,
|
|
411
435
|
},
|
|
@@ -422,12 +446,47 @@ describe('internal-plugin-metrics', () => {
|
|
|
422
446
|
},
|
|
423
447
|
},
|
|
424
448
|
],
|
|
449
|
+
[
|
|
450
|
+
'client.lobby.exited',
|
|
451
|
+
{
|
|
452
|
+
joinTimes: {
|
|
453
|
+
stayLobbyTime: undefined,
|
|
454
|
+
},
|
|
455
|
+
},
|
|
456
|
+
],
|
|
425
457
|
].forEach(([eventName, expectedEvent]) => {
|
|
426
458
|
it(`returns expected result for ${eventName}`, () => {
|
|
427
459
|
check(eventName as string, expectedEvent, 'gold');
|
|
428
460
|
});
|
|
429
461
|
});
|
|
430
462
|
|
|
463
|
+
it('logs a Milestone entry when event name is present', () => {
|
|
464
|
+
const logSpy = sinon.spy(webex.logger, 'log');
|
|
465
|
+
const eventName = 'client.call.initiated';
|
|
466
|
+
const eventPayload = {event: {name: eventName}};
|
|
467
|
+
|
|
468
|
+
prepareDiagnosticMetricItem(webex, {eventPayload, type: ['diagnostic-event']});
|
|
469
|
+
|
|
470
|
+
assert.isTrue(
|
|
471
|
+
logSpy.calledWith('Milestone,CallDiagnostic', eventName),
|
|
472
|
+
'expected logger.log to be called with Milestone,CallDiagnostic and the event name'
|
|
473
|
+
);
|
|
474
|
+
sinon.restore();
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
it('does not log a Milestone entry when event name is absent', () => {
|
|
478
|
+
const logSpy = sinon.spy(webex.logger, 'log');
|
|
479
|
+
const eventPayload = {event: {}};
|
|
480
|
+
|
|
481
|
+
prepareDiagnosticMetricItem(webex, {eventPayload, type: ['diagnostic-event']});
|
|
482
|
+
|
|
483
|
+
assert.isFalse(
|
|
484
|
+
logSpy.calledWith('Milestone,CallDiagnostic', sinon.match.any),
|
|
485
|
+
'expected logger.log not to be called with Milestone,CallDiagnostic when event name is absent'
|
|
486
|
+
);
|
|
487
|
+
sinon.restore();
|
|
488
|
+
});
|
|
489
|
+
|
|
431
490
|
it('sets buildType and upgradeChannel correctly', () => {
|
|
432
491
|
const item: any = {
|
|
433
492
|
eventPayload: {
|
|
@@ -685,4 +744,34 @@ describe('internal-plugin-metrics', () => {
|
|
|
685
744
|
});
|
|
686
745
|
});
|
|
687
746
|
});
|
|
747
|
+
|
|
748
|
+
describe('isBrowserMediaError', () => {
|
|
749
|
+
it('should return true if error name is in BROWSER_MEDIA_ERROR_NAME_TO_CLIENT_ERROR_CODES_MAP', () => {
|
|
750
|
+
// Use a known browser media error name from the config map
|
|
751
|
+
const errorName = Object.keys(BROWSER_MEDIA_ERROR_NAME_TO_CLIENT_ERROR_CODES_MAP)[0];
|
|
752
|
+
const error = {name: errorName};
|
|
753
|
+
assert.isTrue(CallDiagnosticUtils.isBrowserMediaError(error));
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
it('should return false if error name is not in BROWSER_MEDIA_ERROR_NAME_TO_CLIENT_ERROR_CODES_MAP', () => {
|
|
757
|
+
const error = {name: 'SomeOtherError'};
|
|
758
|
+
assert.isFalse(CallDiagnosticUtils.isBrowserMediaError(error));
|
|
759
|
+
});
|
|
760
|
+
});
|
|
761
|
+
|
|
762
|
+
describe('getBrowserMediaErrorCode', () => {
|
|
763
|
+
it('should return correct error code for known error name', () => {
|
|
764
|
+
const errorName = Object.keys(BROWSER_MEDIA_ERROR_NAME_TO_CLIENT_ERROR_CODES_MAP)[0];
|
|
765
|
+
const error = {name: errorName};
|
|
766
|
+
assert.strictEqual(
|
|
767
|
+
CallDiagnosticUtils.getBrowserMediaErrorCode(error),
|
|
768
|
+
BROWSER_MEDIA_ERROR_NAME_TO_CLIENT_ERROR_CODES_MAP[errorName]
|
|
769
|
+
);
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
it('should return undefined for unknown error name', () => {
|
|
773
|
+
const error = {name: 'UnknownError'};
|
|
774
|
+
assert.isUndefined(CallDiagnosticUtils.getBrowserMediaErrorCode(error));
|
|
775
|
+
});
|
|
776
|
+
});
|
|
688
777
|
});
|
|
@@ -64,45 +64,37 @@ describe('internal-plugin-metrics', () => {
|
|
|
64
64
|
//@ts-ignore
|
|
65
65
|
assert.calledOnce(webex.request);
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
networkType: 'unknown',
|
|
87
|
-
upgradeChannel: 'test',
|
|
88
|
-
},
|
|
89
|
-
originTime: {
|
|
90
|
-
sent: dateAfterBatcherWait.toISOString(),
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
type: ['diagnostic-event'],
|
|
94
|
-
},
|
|
95
|
-
],
|
|
67
|
+
assert.deepEqual(webexRequestArgs.headers, {
|
|
68
|
+
authorization: false,
|
|
69
|
+
'x-prelogin-userid': preLoginId,
|
|
70
|
+
});
|
|
71
|
+
assert.equal(webexRequestArgs.method, 'POST');
|
|
72
|
+
assert.equal(webexRequestArgs.resource, 'clientmetrics-prelogin');
|
|
73
|
+
assert.equal(webexRequestArgs.service, 'metrics');
|
|
74
|
+
assert.equal(webexRequestArgs.waitForServiceTimeout, 30);
|
|
75
|
+
|
|
76
|
+
assert.deepEqual(webexRequestArgs.body.metrics[0].eventPayload, {
|
|
77
|
+
event: {
|
|
78
|
+
joinTimes: {
|
|
79
|
+
meetingInfoReqResp: undefined,
|
|
80
|
+
clickToInterstitial: undefined,
|
|
81
|
+
refreshCaptchaServiceReqResp: undefined,
|
|
82
|
+
downloadIntelligenceModelsReqResp: undefined,
|
|
83
|
+
clickToInterstitialWithUserDelay: undefined,
|
|
84
|
+
},
|
|
85
|
+
name: 'client.interstitial-window.launched',
|
|
96
86
|
},
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
'
|
|
87
|
+
origin: {
|
|
88
|
+
buildType: 'test',
|
|
89
|
+
networkType: 'unknown',
|
|
90
|
+
upgradeChannel: 'test',
|
|
91
|
+
},
|
|
92
|
+
originTime: {
|
|
93
|
+
sent: dateAfterBatcherWait.toISOString(),
|
|
100
94
|
},
|
|
101
|
-
method: 'POST',
|
|
102
|
-
resource: 'clientmetrics-prelogin',
|
|
103
|
-
service: 'metrics',
|
|
104
|
-
waitForServiceTimeout: 30,
|
|
105
95
|
});
|
|
96
|
+
assert.deepEqual(webexRequestArgs.body.metrics[0].type, ['diagnostic-event']);
|
|
97
|
+
assert.equal(webexRequestArgs.body.metrics[0].markTelemetryOptOutOnResponse, true);
|
|
106
98
|
assert.lengthOf(
|
|
107
99
|
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.queue,
|
|
108
100
|
0
|
|
@@ -320,5 +312,167 @@ describe('internal-plugin-metrics', () => {
|
|
|
320
312
|
);
|
|
321
313
|
});
|
|
322
314
|
});
|
|
315
|
+
|
|
316
|
+
describe('#submitHttpRequest', () => {
|
|
317
|
+
it('calls webex.request with the correct parameters and then it calls handleHttpResponseStatus on success', async () => {
|
|
318
|
+
const payload = [
|
|
319
|
+
{
|
|
320
|
+
eventPayload: {event: 'my.event'},
|
|
321
|
+
type: ['diagnostic-event'],
|
|
322
|
+
},
|
|
323
|
+
];
|
|
324
|
+
|
|
325
|
+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.savePreLoginId(
|
|
326
|
+
preLoginId
|
|
327
|
+
);
|
|
328
|
+
webex.request = sinon.stub().resolves({statusCode: 200});
|
|
329
|
+
|
|
330
|
+
const handleHttpResponseStatusSpy = sinon.spy(
|
|
331
|
+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher,
|
|
332
|
+
'handleHttpResponseStatus'
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
const promise =
|
|
336
|
+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.submitHttpRequest(
|
|
337
|
+
payload
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
assert.deepEqual(handleHttpResponseStatusSpy.getCalls().length, 0);
|
|
341
|
+
|
|
342
|
+
await flushPromises();
|
|
343
|
+
|
|
344
|
+
clock.tick(config.metrics.batcherWait);
|
|
345
|
+
|
|
346
|
+
await promise;
|
|
347
|
+
|
|
348
|
+
const webexRequestArgs = webex.request.args[0][0];
|
|
349
|
+
|
|
350
|
+
assert.match(webexRequestArgs, {
|
|
351
|
+
//@ts-ignore
|
|
352
|
+
body: {
|
|
353
|
+
metrics: payload,
|
|
354
|
+
},
|
|
355
|
+
headers: {
|
|
356
|
+
authorization: false,
|
|
357
|
+
'x-prelogin-userid': preLoginId,
|
|
358
|
+
},
|
|
359
|
+
method: 'POST',
|
|
360
|
+
resource: 'clientmetrics-prelogin',
|
|
361
|
+
service: 'metrics',
|
|
362
|
+
waitForServiceTimeout: 30,
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
assert.deepEqual(handleHttpResponseStatusSpy.getCalls().length, 1);
|
|
366
|
+
|
|
367
|
+
assert.deepEqual(handleHttpResponseStatusSpy.args[0][0], 200);
|
|
368
|
+
assert.deepEqual(handleHttpResponseStatusSpy.args[0][1], payload);
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it('it calls handleHttpResponseStatus on failure', async () => {
|
|
372
|
+
const payload = [
|
|
373
|
+
{
|
|
374
|
+
eventPayload: {event: 'my.event'},
|
|
375
|
+
type: ['diagnostic-event'],
|
|
376
|
+
},
|
|
377
|
+
];
|
|
378
|
+
|
|
379
|
+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.savePreLoginId(
|
|
380
|
+
preLoginId
|
|
381
|
+
);
|
|
382
|
+
webex.request = sinon.stub().rejects({statusCode: 503});
|
|
383
|
+
|
|
384
|
+
const handleHttpResponseStatusSpy = sinon.spy(
|
|
385
|
+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher,
|
|
386
|
+
'handleHttpResponseStatus'
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
const promise =
|
|
390
|
+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.submitHttpRequest(
|
|
391
|
+
payload
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
assert.deepEqual(handleHttpResponseStatusSpy.getCalls().length, 0);
|
|
395
|
+
|
|
396
|
+
await flushPromises();
|
|
397
|
+
|
|
398
|
+
clock.tick(config.metrics.batcherWait);
|
|
399
|
+
|
|
400
|
+
let error;
|
|
401
|
+
|
|
402
|
+
try {
|
|
403
|
+
await promise;
|
|
404
|
+
} catch (err) {
|
|
405
|
+
error = err;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
assert.deepEqual(error.statusCode, 503);
|
|
409
|
+
|
|
410
|
+
assert.deepEqual(handleHttpResponseStatusSpy.getCalls().length, 1);
|
|
411
|
+
|
|
412
|
+
assert.deepEqual(handleHttpResponseStatusSpy.args[0][0], 503);
|
|
413
|
+
assert.deepEqual(handleHttpResponseStatusSpy.args[0][1], payload);
|
|
414
|
+
});
|
|
415
|
+
})
|
|
416
|
+
|
|
417
|
+
describe('#handleHttpResponseStatus', () => {
|
|
418
|
+
let setIsTelemetryOptOutAutomaticStub;
|
|
419
|
+
|
|
420
|
+
beforeEach(() => {
|
|
421
|
+
setIsTelemetryOptOutAutomaticStub = sinon.stub(
|
|
422
|
+
webex.internal.newMetrics.callDiagnosticMetrics,
|
|
423
|
+
'setIsTelemetryOptOutAutomatic'
|
|
424
|
+
);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
[201, 400, 503, undefined].forEach((statusCode) => {
|
|
428
|
+
it(`does not call setIsTelemetryOptOutAutomatic when shouldMark is true and statusCode is ${statusCode}`, () => {
|
|
429
|
+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.handleHttpResponseStatus(
|
|
430
|
+
statusCode,
|
|
431
|
+
[{markTelemetryOptOutOnResponse: true}]
|
|
432
|
+
);
|
|
433
|
+
|
|
434
|
+
assert.notCalled(setIsTelemetryOptOutAutomaticStub);
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
it('calls setIsTelemetryOptOutAutomatic(true) when statusCode is 200 and markTelemetryOptOutOnResponse is true', () => {
|
|
439
|
+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.handleHttpResponseStatus(
|
|
440
|
+
200,
|
|
441
|
+
[{markTelemetryOptOutOnResponse: true}]
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
assert.calledOnce(setIsTelemetryOptOutAutomaticStub);
|
|
445
|
+
assert.calledWithExactly(setIsTelemetryOptOutAutomaticStub, true);
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
[200, 201, 400, 503, undefined].forEach((statusCode) => {
|
|
449
|
+
it(`does not call setIsTelemetryOptOutAutomatic when shouldMark is false (statusCode: ${statusCode})`, () => {
|
|
450
|
+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.handleHttpResponseStatus(
|
|
451
|
+
statusCode,
|
|
452
|
+
[{markTelemetryOptOutOnResponse: false}]
|
|
453
|
+
);
|
|
454
|
+
|
|
455
|
+
assert.notCalled(setIsTelemetryOptOutAutomaticStub);
|
|
456
|
+
});
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
it('does not call setIsTelemetryOptOutAutomatic when payload is empty', () => {
|
|
460
|
+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.handleHttpResponseStatus(
|
|
461
|
+
200,
|
|
462
|
+
[]
|
|
463
|
+
);
|
|
464
|
+
|
|
465
|
+
assert.notCalled(setIsTelemetryOptOutAutomaticStub);
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
it('does not call setIsTelemetryOptOutAutomatic when payload is not an array', () => {
|
|
469
|
+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.handleHttpResponseStatus(
|
|
470
|
+
200,
|
|
471
|
+
null
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
assert.notCalled(setIsTelemetryOptOutAutomaticStub);
|
|
475
|
+
});
|
|
476
|
+
});
|
|
323
477
|
});
|
|
324
478
|
});
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import PreLoginMetricsBatcher from '../../../src/prelogin-metrics-batcher';
|
|
2
|
+
import {PreLoginMetrics} from '@webex/internal-plugin-metrics';
|
|
3
|
+
import {assert} from '@webex/test-helper-chai';
|
|
4
|
+
import MockWebex from '@webex/test-helper-mock-webex';
|
|
5
|
+
import sinon from 'sinon';
|
|
6
|
+
|
|
7
|
+
describe('internal-plugin-metrics', () => {
|
|
8
|
+
const mockedWebex: MockWebex = new MockWebex();
|
|
9
|
+
const fakedPreLoginMetricsBatcher: typeof PreLoginMetricsBatcher = new PreLoginMetricsBatcher({}, {parent: mockedWebex});
|
|
10
|
+
|
|
11
|
+
describe('prelogin-metrics', () => {
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
sinon.restore();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('Should send metrics to preloginMetricsBatcher', async () => {
|
|
17
|
+
const testEvent = 'test';
|
|
18
|
+
const testId = 'abc123';
|
|
19
|
+
const preLoginMetrics = new PreLoginMetrics(fakedPreLoginMetricsBatcher, {}, {parent: mockedWebex});
|
|
20
|
+
|
|
21
|
+
sinon.stub(fakedPreLoginMetricsBatcher, 'savePreLoginId');
|
|
22
|
+
const requestSpy = sinon.stub(fakedPreLoginMetricsBatcher, 'request');
|
|
23
|
+
|
|
24
|
+
await preLoginMetrics.submitPreLoginEvent({name: testEvent, preLoginId: testId, payload: {}});
|
|
25
|
+
|
|
26
|
+
assert.calledOnceWithMatch(requestSpy, {
|
|
27
|
+
type: ['business'],
|
|
28
|
+
eventPayload: {metricName: testEvent, value: {preLoginId: testId}},
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('Should send metadata to preloginMetricsBatcher', async () => {
|
|
33
|
+
const testEvent = 'test';
|
|
34
|
+
const testId = 'abc123';
|
|
35
|
+
const testMetadata = { 'testKey': 'test-value' };
|
|
36
|
+
const preLoginMetrics = new PreLoginMetrics(fakedPreLoginMetricsBatcher, {}, {parent: mockedWebex});
|
|
37
|
+
|
|
38
|
+
sinon.stub(fakedPreLoginMetricsBatcher, 'savePreLoginId');
|
|
39
|
+
const requestSpy = sinon.stub(fakedPreLoginMetricsBatcher, 'request');
|
|
40
|
+
|
|
41
|
+
await preLoginMetrics.submitPreLoginEvent({name: testEvent, preLoginId: testId, payload: {}, metadata: testMetadata});
|
|
42
|
+
|
|
43
|
+
assert.calledOnceWithMatch(requestSpy, {
|
|
44
|
+
type: ['business'],
|
|
45
|
+
eventPayload: {metricName: testEvent, value: {preLoginId: testId, ...testMetadata}},
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('Should send payload to preloginMetricsBatcher', async () => {
|
|
50
|
+
const testEvent = 'test';
|
|
51
|
+
const testId = 'abc123';
|
|
52
|
+
const testPayload = { 'testKey': 'test-value' };
|
|
53
|
+
const preLoginMetrics = new PreLoginMetrics(fakedPreLoginMetricsBatcher, {}, {parent: mockedWebex});
|
|
54
|
+
|
|
55
|
+
sinon.stub(fakedPreLoginMetricsBatcher, 'savePreLoginId');
|
|
56
|
+
const requestSpy = sinon.stub(fakedPreLoginMetricsBatcher, 'request');
|
|
57
|
+
|
|
58
|
+
await preLoginMetrics.submitPreLoginEvent({name: testEvent, preLoginId: testId, payload: testPayload});
|
|
59
|
+
|
|
60
|
+
assert.calledOnceWithMatch(requestSpy, {
|
|
61
|
+
type: ['business'],
|
|
62
|
+
eventPayload: {metricName: testEvent, value: {preLoginId: testId, ...testPayload}},
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('Should fill appType if not defined', async () => {
|
|
67
|
+
const testEvent = 'test';
|
|
68
|
+
const preLoginMetrics = new PreLoginMetrics(fakedPreLoginMetricsBatcher, {}, {parent: mockedWebex});
|
|
69
|
+
|
|
70
|
+
sinon.stub(fakedPreLoginMetricsBatcher, 'savePreLoginId');
|
|
71
|
+
const requestSpy = sinon.stub(fakedPreLoginMetricsBatcher, 'request');
|
|
72
|
+
|
|
73
|
+
await preLoginMetrics.submitPreLoginEvent({name: testEvent, preLoginId: 'abc123', payload: {}});
|
|
74
|
+
|
|
75
|
+
assert.calledOnceWithMatch(requestSpy, {
|
|
76
|
+
type: ['business'],
|
|
77
|
+
eventPayload: {metricName: testEvent, value: {appType: 'Web Client'}},
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('Should add browser details', async () => {
|
|
82
|
+
const testEvent = 'test';
|
|
83
|
+
const testBrowserDetails = { browser: 'Firefox', domain: 'test.example.com' };
|
|
84
|
+
const preLoginMetrics = new PreLoginMetrics(fakedPreLoginMetricsBatcher, {}, {parent: mockedWebex});
|
|
85
|
+
|
|
86
|
+
sinon.stub(preLoginMetrics, 'getBrowserDetails').returns(testBrowserDetails);
|
|
87
|
+
sinon.stub(fakedPreLoginMetricsBatcher, 'savePreLoginId');
|
|
88
|
+
const requestSpy = sinon.stub(fakedPreLoginMetricsBatcher, 'request');
|
|
89
|
+
|
|
90
|
+
await preLoginMetrics.submitPreLoginEvent({name: testEvent, preLoginId: 'abc123', payload: {}});
|
|
91
|
+
|
|
92
|
+
assert.calledOnceWithMatch(requestSpy, {
|
|
93
|
+
type: ['business'],
|
|
94
|
+
eventPayload: {browserDetails: testBrowserDetails, metricName: testEvent},
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('Should add context', async () => {
|
|
99
|
+
const testEvent = 'test';
|
|
100
|
+
const testContext = { device: { id: 'abc123' }};
|
|
101
|
+
const preLoginMetrics = new PreLoginMetrics(fakedPreLoginMetricsBatcher, {}, {parent: mockedWebex});
|
|
102
|
+
|
|
103
|
+
sinon.stub(preLoginMetrics, 'getContext').returns(testContext);
|
|
104
|
+
sinon.stub(fakedPreLoginMetricsBatcher, 'savePreLoginId');
|
|
105
|
+
const requestSpy = sinon.stub(fakedPreLoginMetricsBatcher, 'request');
|
|
106
|
+
|
|
107
|
+
await preLoginMetrics.submitPreLoginEvent({name: testEvent, preLoginId: 'abc123', payload: {}});
|
|
108
|
+
|
|
109
|
+
assert.calledOnceWithMatch(requestSpy, {
|
|
110
|
+
type: ['business'],
|
|
111
|
+
eventPayload: {context: testContext, metricName: testEvent},
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('Should add timestamp', async () => {
|
|
116
|
+
const testEvent = 'test';
|
|
117
|
+
const testTime = 1234;
|
|
118
|
+
const preLoginMetrics = new PreLoginMetrics(fakedPreLoginMetricsBatcher, {}, {parent: mockedWebex});
|
|
119
|
+
|
|
120
|
+
sinon.useFakeTimers(testTime);
|
|
121
|
+
sinon.stub(fakedPreLoginMetricsBatcher, 'savePreLoginId');
|
|
122
|
+
const requestSpy = sinon.stub(fakedPreLoginMetricsBatcher, 'request');
|
|
123
|
+
|
|
124
|
+
await preLoginMetrics.submitPreLoginEvent({name: testEvent, preLoginId: 'abc123', payload: {}});
|
|
125
|
+
|
|
126
|
+
assert.calledOnceWithMatch(requestSpy, {
|
|
127
|
+
type: ['business'],
|
|
128
|
+
eventPayload: {metricName: testEvent, timestamp: testTime},
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|