@webex/internal-plugin-metrics 3.12.0-next.9 → 3.12.0-webex-services-ready.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.
Files changed (38) hide show
  1. package/dist/batcher.js +3 -0
  2. package/dist/batcher.js.map +1 -1
  3. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +23 -0
  4. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -1
  5. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +29 -25
  6. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
  7. package/dist/call-diagnostic/call-diagnostic-metrics.js +55 -8
  8. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
  9. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +5 -0
  10. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
  11. package/dist/call-diagnostic/config.js +14 -2
  12. package/dist/call-diagnostic/config.js.map +1 -1
  13. package/dist/config.js +1 -0
  14. package/dist/config.js.map +1 -1
  15. package/dist/metrics.js +1 -1
  16. package/dist/metrics.types.js.map +1 -1
  17. package/dist/prelogin-metrics-batcher.js +23 -0
  18. package/dist/prelogin-metrics-batcher.js.map +1 -1
  19. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +23 -0
  20. package/dist/types/call-diagnostic/config.d.ts +4 -0
  21. package/dist/types/config.d.ts +1 -0
  22. package/dist/types/metrics.types.d.ts +2 -2
  23. package/package.json +11 -11
  24. package/src/batcher.js +4 -0
  25. package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +26 -0
  26. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +54 -38
  27. package/src/call-diagnostic/call-diagnostic-metrics.ts +46 -1
  28. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +5 -0
  29. package/src/call-diagnostic/config.ts +13 -0
  30. package/src/config.js +1 -0
  31. package/src/metrics.types.ts +1 -1
  32. package/src/prelogin-metrics-batcher.ts +26 -0
  33. package/test/unit/spec/batcher.js +43 -0
  34. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +145 -0
  35. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +105 -95
  36. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +680 -159
  37. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +27 -0
  38. package/test/unit/spec/prelogin-metrics-batcher.ts +190 -36
@@ -460,6 +460,33 @@ describe('internal-plugin-metrics', () => {
460
460
  });
461
461
  });
462
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
+
463
490
  it('sets buildType and upgradeChannel correctly', () => {
464
491
  const item: any = {
465
492
  eventPayload: {
@@ -64,45 +64,37 @@ describe('internal-plugin-metrics', () => {
64
64
  //@ts-ignore
65
65
  assert.calledOnce(webex.request);
66
66
 
67
- // matching because the request includes a symbol key: value pair and sinon cannot handle to compare it..
68
- assert.match(webexRequestArgs, {
69
- //@ts-ignore
70
- body: {
71
- metrics: [
72
- {
73
- eventPayload: {
74
- event: {
75
- joinTimes: {
76
- meetingInfoReqResp: undefined,
77
- clickToInterstitial: undefined,
78
- refreshCaptchaServiceReqResp: undefined,
79
- downloadIntelligenceModelsReqResp: undefined,
80
- clickToInterstitialWithUserDelay: undefined,
81
- },
82
- name: 'client.interstitial-window.launched',
83
- },
84
- origin: {
85
- buildType: 'test',
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
- headers: {
98
- authorization: false,
99
- 'x-prelogin-userid': preLoginId,
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
  });