@webex/internal-plugin-metrics 3.0.0-beta.229 → 3.0.0-beta.230

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 (31) hide show
  1. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +5 -3
  2. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -1
  3. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +1 -1
  4. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
  5. package/dist/call-diagnostic/call-diagnostic-metrics.js +12 -11
  6. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
  7. package/dist/index.js +3 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/metrics.js +1 -1
  10. package/dist/metrics.types.js.map +1 -1
  11. package/dist/new-metrics.js +6 -4
  12. package/dist/new-metrics.js.map +1 -1
  13. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +4 -1
  14. package/dist/types/index.d.ts +2 -1
  15. package/dist/types/metrics.types.d.ts +1 -1
  16. package/dist/types/utils.d.ts +6 -0
  17. package/dist/utils.js +27 -0
  18. package/dist/utils.js.map +1 -0
  19. package/package.json +8 -8
  20. package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +4 -3
  21. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +1 -1
  22. package/src/call-diagnostic/call-diagnostic-metrics.ts +17 -16
  23. package/src/index.ts +2 -1
  24. package/src/metrics.types.ts +0 -1
  25. package/src/new-metrics.ts +17 -4
  26. package/src/utils.ts +17 -0
  27. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +119 -11
  28. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +1 -1
  29. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +134 -0
  30. package/test/unit/spec/new-metrics.ts +56 -7
  31. package/test/unit/spec/utils.ts +22 -0
@@ -3,17 +3,38 @@
3
3
  */
4
4
 
5
5
  import {assert} from '@webex/test-helper-chai';
6
- import {config} from '@webex/internal-plugin-metrics';
6
+ import {config, Utils} from '@webex/internal-plugin-metrics';
7
7
  import MockWebex from '@webex/test-helper-mock-webex';
8
8
  import sinon from 'sinon';
9
+ import FakeTimers from '@sinonjs/fake-timers';
9
10
  import {NewMetrics} from '@webex/internal-plugin-metrics';
11
+ import { uniqueId } from 'lodash';
12
+
10
13
  const flushPromises = () => new Promise(setImmediate);
11
14
 
15
+ function promiseTick(count) {
16
+ let promise = Promise.resolve();
17
+
18
+ while (count > 1) {
19
+ promise = promise.then(() => promiseTick(1));
20
+ count -= 1;
21
+ }
22
+
23
+ return promise;
24
+ }
25
+
26
+
12
27
  describe('plugin-metrics', () => {
13
28
  describe('CallDiagnosticEventsBatcher', () => {
14
29
  let webex;
30
+ let clock;
31
+ let now;
32
+
15
33
 
16
34
  beforeEach(() => {
35
+ now = new Date();
36
+ clock = FakeTimers.install({now});
37
+
17
38
  //@ts-ignore
18
39
  webex = new MockWebex({
19
40
  children: {
@@ -31,16 +52,20 @@ describe('plugin-metrics', () => {
31
52
 
32
53
  afterEach(() => {
33
54
  sinon.restore();
55
+ clock.uninstall();
34
56
  });
35
57
 
36
58
  describe('#request()', () => {
37
59
  describe('when the request completes successfully', async () => {
38
60
  it('clears the queue', async () => {
39
- await webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
61
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
40
62
  //@ts-ignore
41
63
  {event: {name: 'client.interstitial-window.launched'}}
42
64
  );
43
65
  await flushPromises();
66
+ clock.tick(config.metrics.batcherWait);
67
+
68
+ await promise;
44
69
 
45
70
  //@ts-ignore
46
71
  assert.calledOnce(webex.request);
@@ -48,11 +73,14 @@ describe('plugin-metrics', () => {
48
73
  });
49
74
 
50
75
  it('doesnt include any joinTimes for other events', async () => {
51
- await webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
76
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
52
77
  //@ts-ignore
53
78
  {event: {name: 'client.alert.displayed'}}
54
79
  );
55
80
  await flushPromises();
81
+ clock.tick(config.metrics.batcherWait);
82
+
83
+ await promise;
56
84
 
57
85
  //@ts-ignore
58
86
  assert.calledOnce(webex.request);
@@ -65,11 +93,14 @@ describe('plugin-metrics', () => {
65
93
  it('appends the correct join times to the request for client.interstitial-window.launched', async () => {
66
94
  webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
67
95
  webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitial = sinon.stub().returns(10);
68
- await webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
96
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
69
97
  //@ts-ignore
70
98
  {event: {name: 'client.interstitial-window.launched'}}
71
99
  );
72
100
  await flushPromises();
101
+ clock.tick(config.metrics.batcherWait);
102
+
103
+ await promise;
73
104
 
74
105
  //@ts-ignore
75
106
  assert.calledOnce(webex.request);
@@ -85,12 +116,14 @@ describe('plugin-metrics', () => {
85
116
 
86
117
  it('appends the correct join times to the request for client.call.initiated', async () => {
87
118
  webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
88
- await webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
119
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
89
120
  //@ts-ignore
90
121
  {event: {name: 'client.call.initiated'}}
91
122
  );
92
123
  await flushPromises();
124
+ clock.tick(config.metrics.batcherWait);
93
125
 
126
+ await promise;
94
127
  //@ts-ignore
95
128
  assert.calledOnce(webex.request);
96
129
  assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
@@ -110,11 +143,14 @@ describe('plugin-metrics', () => {
110
143
  webex.internal.newMetrics.callDiagnosticLatencies.getClientJMT = sinon.stub().returns(5);
111
144
  webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitial = sinon.stub().returns(10);
112
145
  webex.internal.newMetrics.callDiagnosticLatencies.getCallInitJoinReq = sinon.stub().returns(10);
113
- await webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
146
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
114
147
  //@ts-ignore
115
148
  {event: {name: 'client.locus.join.response'}}
116
149
  );
117
150
  await flushPromises();
151
+ clock.tick(config.metrics.batcherWait);
152
+
153
+ await promise;
118
154
 
119
155
  //@ts-ignore
120
156
  assert.calledOnce(webex.request);
@@ -137,11 +173,14 @@ describe('plugin-metrics', () => {
137
173
 
138
174
  it('appends the correct join times to the request for client.ice.end', async () => {
139
175
  webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
140
- await webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
176
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
141
177
  //@ts-ignore
142
178
  {event: {name: 'client.ice.end'}}
143
179
  );
144
180
  await flushPromises();
181
+ clock.tick(config.metrics.batcherWait);
182
+
183
+ await promise;
145
184
 
146
185
  //@ts-ignore
147
186
  assert.calledOnce(webex.request);
@@ -159,11 +198,14 @@ describe('plugin-metrics', () => {
159
198
 
160
199
  it('appends the correct join times to the request for client.media.rx.start', async () => {
161
200
  webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
162
- await webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
201
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
163
202
  //@ts-ignore
164
203
  {event: {name: 'client.media.rx.start'}}
165
204
  );
166
205
  await flushPromises();
206
+ clock.tick(config.metrics.batcherWait);
207
+
208
+ await promise;
167
209
 
168
210
  //@ts-ignore
169
211
  assert.calledOnce(webex.request);
@@ -180,11 +222,14 @@ describe('plugin-metrics', () => {
180
222
  webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
181
223
  webex.internal.newMetrics.callDiagnosticLatencies.getInterstitialToMediaOKJMT = sinon.stub().returns(10);
182
224
  webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitial = sinon.stub().returns(10);
183
- await webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
225
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
184
226
  //@ts-ignore
185
227
  {event: {name: 'client.media-engine.ready'}}
186
228
  );
187
229
  await flushPromises();
230
+ clock.tick(config.metrics.batcherWait);
231
+
232
+ await promise;
188
233
 
189
234
  //@ts-ignore
190
235
  assert.calledOnce(webex.request);
@@ -202,11 +247,14 @@ describe('plugin-metrics', () => {
202
247
 
203
248
  it('appends the correct audio and video setup delays to the request for client.mediaquality.event', async () => {
204
249
  webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
205
- await webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
250
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
206
251
  //@ts-ignore
207
252
  {event: {name: 'client.mediaquality.event'}}
208
253
  );
209
254
  await flushPromises();
255
+ clock.tick(config.metrics.batcherWait);
256
+
257
+ await promise;
210
258
 
211
259
  //@ts-ignore
212
260
  assert.calledOnce(webex.request);
@@ -225,11 +273,14 @@ describe('plugin-metrics', () => {
225
273
  });
226
274
 
227
275
  it('doesnt include audioSetup and videoSetup delays for other events', async () => {
228
- await webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
276
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
229
277
  //@ts-ignore
230
278
  {event: {name: 'client.alert.displayed'}}
231
279
  );
232
280
  await flushPromises();
281
+ clock.tick(config.metrics.batcherWait);
282
+
283
+ await promise;
233
284
 
234
285
  //@ts-ignore
235
286
  assert.calledOnce(webex.request);
@@ -238,6 +289,63 @@ describe('plugin-metrics', () => {
238
289
  assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
239
290
  })
240
291
  });
292
+
293
+ describe('when the request fails', () => {
294
+ it('does not clear the queue', async () => {
295
+ // avoid setting .sent timestamp
296
+ webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.prepareRequest =
297
+ (q) => Promise.resolve(q);
298
+
299
+ const err = new Error('error');
300
+ webex.request = sinon.stub().returns(Promise.reject(err));
301
+
302
+ webex.logger.error = sinon.stub();
303
+ webex.logger.log = sinon.stub();
304
+ sinon.stub(Utils, 'generateCommonErrorMetadata').returns('formattedError');
305
+
306
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics({
307
+ event: 'my.event',
308
+ });
309
+
310
+ await flushPromises();
311
+ clock.tick(config.metrics.batcherWait);
312
+
313
+ let error;
314
+
315
+ // catch the expected error and store it
316
+ await promise.catch((e) => {
317
+ error = e;
318
+ });
319
+
320
+ const loggerLogCalls = webex.logger.log.getCalls();
321
+
322
+ assert.deepEqual(loggerLogCalls[0].args, [
323
+ 'call-diagnostic-events -> ',
324
+ 'CallDiagnosticMetrics: @submitToCallDiagnostics. Preparing to send the request',
325
+ `finalEvent: {"eventPayload":{"event":"my.event"},"type":["diagnostic-event"]}`,
326
+ ]);
327
+
328
+ // This is horrific, but stubbing lodash is proving difficult
329
+ const expectedBatchId = parseInt(uniqueId()) - 1;
330
+
331
+ assert.deepEqual(loggerLogCalls[1].args, [
332
+ 'call-diagnostic-events -> ',
333
+ `CallDiagnosticEventsBatcher: @submitHttpRequest#call-diagnostic-metrics-batch-${expectedBatchId}. Sending the request:`,
334
+ `payload: [{"eventPayload":{"event":"my.event","origin":{"buildType":"test","networkType":"unknown"}},"type":["diagnostic-event"]}]`,
335
+ ]);
336
+
337
+ // check that promise was rejected with the original error of the webex.request
338
+ assert.deepEqual(err, error);
339
+
340
+ assert.calledOnceWithExactly(
341
+ webex.logger.error,
342
+ 'call-diagnostic-events -> ',
343
+ `CallDiagnosticEventsBatcher: @submitHttpRequest#call-diagnostic-metrics-batch-${expectedBatchId}. Request failed:`,
344
+ `error: formattedError`
345
+ );
346
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
347
+ });
348
+ });
241
349
  });
242
350
  });
243
351
  });
@@ -104,7 +104,7 @@ describe('internal-plugin-metrics', () => {
104
104
  });
105
105
 
106
106
  it('calculates getShowInterstitialTime correctly', () => {
107
- cdl.saveTimestamp({key: 'internal.client.interstitial-window.launched', value: 10});
107
+ cdl.saveTimestamp({key: 'client.interstitial-window.start-launch', value: 10});
108
108
  cdl.saveTimestamp({key: 'internal.client.interstitial-window.click.joinbutton', value: 20});
109
109
  assert.deepEqual(cdl.getShowInterstitialTime(), 10);
110
110
  });
@@ -405,6 +405,28 @@ describe('internal-plugin-metrics', () => {
405
405
  senderCountryCode: 'UK',
406
406
  version: 1,
407
407
  });
408
+
409
+ const webexLoggerLogCalls = webex.logger.log.getCalls();
410
+ assert.deepEqual(webexLoggerLogCalls[0].args, [
411
+ 'call-diagnostic-events -> ',
412
+ 'CallDiagnosticMetrics: @submitClientEvent. Submit Client Event CA event.',
413
+ `name: client.alert.displayed`,
414
+ `payload: undefined`,
415
+ `options: ${JSON.stringify(options)}`,
416
+ ]);
417
+
418
+ assert.deepEqual(webexLoggerLogCalls[1].args, [
419
+ 'call-diagnostic-events -> ',
420
+ 'CallDiagnosticMetrics: @createClientEventObjectInMeeting. Creating in meeting event object.',
421
+ `name: client.alert.displayed`
422
+ ]);
423
+
424
+ assert.deepEqual(webexLoggerLogCalls[2].args, [
425
+ 'call-diagnostic-events -> ',
426
+ 'CallDiagnosticMetrics: @submitToCallDiagnostics. Preparing to send the request',
427
+ `finalEvent: {"eventPayload":{"eventId":"my-fake-id","version":1,"origin":{"origin":"fake-origin"},"originTime":{"triggered":"${now.toISOString()}","sent":"not_defined_yet"},"senderCountryCode":"UK","event":{"name":"client.alert.displayed","canProceed":true,"identifiers":{"correlationId":"correlationId","userId":"userId","deviceId":"deviceUrl","orgId":"orgId","locusUrl":"locus/url","locusId":"url","locusStartTime":"lastActive","mediaAgentAlias":"alias","mediaAgentGroupId":"1"},"eventData":{"webClientDomain":"whatever"},"userType":"host","loginType":"login-ci"}},"type":["diagnostic-event"]}`,
428
+ ]);
429
+
408
430
  });
409
431
 
410
432
  it('should submit client event successfully with correlationId', () => {
@@ -474,6 +496,30 @@ describe('internal-plugin-metrics', () => {
474
496
  senderCountryCode: 'UK',
475
497
  version: 1,
476
498
  });
499
+
500
+ const webexLoggerLogCalls = webex.logger.log.getCalls();
501
+
502
+ assert.deepEqual(webexLoggerLogCalls[0].args, [
503
+ 'call-diagnostic-events -> ',
504
+ 'CallDiagnosticMetrics: @submitClientEvent. Submit Client Event CA event.',
505
+ `name: client.alert.displayed`,
506
+ `payload: undefined`,
507
+ `options: ${JSON.stringify(options)}`,
508
+ ]);
509
+
510
+ assert.deepEqual(webexLoggerLogCalls[1].args, [
511
+ 'call-diagnostic-events -> ',
512
+ 'CallDiagnosticMetrics: @createClientEventObjectPreMeeting. Creating pre meeting event object.',
513
+ `name: client.alert.displayed`
514
+ ]);
515
+
516
+ assert.deepEqual(webexLoggerLogCalls[2].args, [
517
+ 'call-diagnostic-events -> ',
518
+ 'CallDiagnosticMetrics: @submitToCallDiagnostics. Preparing to send the request',
519
+ `finalEvent: {"eventPayload":{"eventId":"my-fake-id","version":1,"origin":{"origin":"fake-origin"},"originTime":{"triggered":"${now.toISOString()}","sent":"not_defined_yet"},"senderCountryCode":"UK","event":{"name":"client.alert.displayed","canProceed":true,"identifiers":{"correlationId":"correlationId","userId":"userId","deviceId":"deviceUrl","orgId":"orgId","locusUrl":"locus-url"},"eventData":{"webClientDomain":"whatever"},"loginType":"login-ci"}},"type":["diagnostic-event"]}`,
520
+ ]);
521
+
522
+
477
523
  });
478
524
 
479
525
  it('it should include errors if provided with meetingId', () => {
@@ -539,6 +585,41 @@ describe('internal-plugin-metrics', () => {
539
585
  senderCountryCode: 'UK',
540
586
  version: 1,
541
587
  });
588
+
589
+ const webexLoggerLogCalls = webex.logger.log.getCalls();
590
+ assert.deepEqual(webexLoggerLogCalls[0].args, [
591
+ 'call-diagnostic-events -> ',
592
+ 'CallDiagnosticMetrics: @submitClientEvent. Submit Client Event CA event.',
593
+ `name: client.alert.displayed`,
594
+ `payload: undefined`,
595
+ `options: ${JSON.stringify(options)}`,
596
+ ]);
597
+
598
+
599
+ assert.deepEqual(webexLoggerLogCalls[1].args, [
600
+ 'call-diagnostic-events -> ',
601
+ 'CallDiagnosticMetrics: @prepareClientEvent. Error detected, attempting to map and attach it to the event...',
602
+ `name: client.alert.displayed`,
603
+ `rawError: ${options.rawError}`
604
+ ]);
605
+
606
+ assert.deepEqual(webexLoggerLogCalls[2].args, [
607
+ 'call-diagnostic-events -> ',
608
+ 'CallDiagnosticMetrics: @prepareClientEvent. Generated errors:',
609
+ `generatedError: {"fatal":true,"shownToUser":false,"name":"other","category":"expected","errorCode":4029,"serviceErrorCode":2409005,"errorDescription":"StartRecordingFailed"}`
610
+ ])
611
+
612
+ assert.deepEqual(webexLoggerLogCalls[3].args, [
613
+ 'call-diagnostic-events -> ',
614
+ 'CallDiagnosticMetrics: @createClientEventObjectInMeeting. Creating in meeting event object.',
615
+ `name: client.alert.displayed`
616
+ ]);
617
+
618
+ assert.deepEqual(webexLoggerLogCalls[4].args, [
619
+ 'call-diagnostic-events -> ',
620
+ 'CallDiagnosticMetrics: @submitToCallDiagnostics. Preparing to send the request',
621
+ `finalEvent: {"eventPayload":{"eventId":"my-fake-id","version":1,"origin":{"origin":"fake-origin"},"originTime":{"triggered":"${now.toISOString()}","sent":"not_defined_yet"},"senderCountryCode":"UK","event":{"name":"client.alert.displayed","canProceed":true,"identifiers":{"correlationId":"correlationId","userId":"userId","deviceId":"deviceUrl","orgId":"orgId","locusUrl":"locus/url","locusId":"url","locusStartTime":"lastActive","mediaAgentAlias":"alias","mediaAgentGroupId":"1"},"errors":[{"fatal":true,"shownToUser":false,"name":"other","category":"expected","errorCode":4029,"serviceErrorCode":2409005,"errorDescription":"StartRecordingFailed"}],"eventData":{"webClientDomain":"whatever"},"userType":"host","loginType":"login-ci"}},"type":["diagnostic-event"]}`,
622
+ ]);
542
623
  });
543
624
 
544
625
  it('it should include errors if provided with correlationId', () => {
@@ -597,6 +678,42 @@ describe('internal-plugin-metrics', () => {
597
678
  senderCountryCode: 'UK',
598
679
  version: 1,
599
680
  });
681
+
682
+ const webexLoggerLogCalls = webex.logger.log.getCalls();
683
+
684
+ assert.deepEqual(webexLoggerLogCalls[0].args, [
685
+ 'call-diagnostic-events -> ',
686
+ 'CallDiagnosticMetrics: @submitClientEvent. Submit Client Event CA event.',
687
+ `name: client.alert.displayed`,
688
+ `payload: undefined`,
689
+ `options: ${JSON.stringify(options)}`,
690
+ ]);
691
+
692
+
693
+ assert.deepEqual(webexLoggerLogCalls[1].args, [
694
+ 'call-diagnostic-events -> ',
695
+ 'CallDiagnosticMetrics: @prepareClientEvent. Error detected, attempting to map and attach it to the event...',
696
+ `name: client.alert.displayed`,
697
+ `rawError: ${options.rawError}`
698
+ ]);
699
+
700
+ assert.deepEqual(webexLoggerLogCalls[2].args, [
701
+ 'call-diagnostic-events -> ',
702
+ 'CallDiagnosticMetrics: @prepareClientEvent. Generated errors:',
703
+ `generatedError: {"fatal":true,"shownToUser":false,"name":"other","category":"expected","errorCode":4029,"serviceErrorCode":2409005,"errorDescription":"StartRecordingFailed"}`
704
+ ])
705
+
706
+ assert.deepEqual(webexLoggerLogCalls[3].args, [
707
+ 'call-diagnostic-events -> ',
708
+ 'CallDiagnosticMetrics: @createClientEventObjectPreMeeting. Creating pre meeting event object.',
709
+ `name: client.alert.displayed`
710
+ ]);
711
+
712
+ assert.deepEqual(webexLoggerLogCalls[4].args, [
713
+ 'call-diagnostic-events -> ',
714
+ 'CallDiagnosticMetrics: @submitToCallDiagnostics. Preparing to send the request',
715
+ `finalEvent: {"eventPayload":{"eventId":"my-fake-id","version":1,"origin":{"origin":"fake-origin"},"originTime":{"triggered":"${now.toISOString()}","sent":"not_defined_yet"},"senderCountryCode":"UK","event":{"name":"client.alert.displayed","errors":[{"fatal":true,"shownToUser":false,"name":"other","category":"expected","errorCode":4029,"serviceErrorCode":2409005,"errorDescription":"StartRecordingFailed"}],"canProceed":true,"identifiers":{"correlationId":"correlationId","userId":"userId","deviceId":"deviceUrl","orgId":"orgId","locusUrl":"locus-url"},"eventData":{"webClientDomain":"whatever"},"loginType":"login-ci"}},"type":["diagnostic-event"]}`,
716
+ ]);
600
717
  });
601
718
 
602
719
  it('should include errors in payload if provided via payload', () => {
@@ -1097,6 +1214,23 @@ describe('internal-plugin-metrics', () => {
1097
1214
  resource: 'clientmetrics',
1098
1215
  service: 'metrics',
1099
1216
  });
1217
+
1218
+ const webexLoggerLogCalls = webex.logger.log.getCalls();
1219
+
1220
+ assert.deepEqual(webexLoggerLogCalls[0].args, [
1221
+ 'call-diagnostic-events -> ',
1222
+ 'CallDiagnosticMetrics: @buildClientEventFetchRequestOptions. Building request options object for fetch()...',
1223
+ `name: client.exit.app`,
1224
+ `payload: {"trigger":"user-interaction","canProceed":false}`,
1225
+ `options: ${JSON.stringify(options)}`,
1226
+ ]);
1227
+
1228
+ assert.deepEqual(webexLoggerLogCalls[1].args, [
1229
+ 'call-diagnostic-events -> ',
1230
+ 'CallDiagnosticMetrics: @createClientEventObjectInMeeting. Creating in meeting event object.',
1231
+ `name: client.exit.app`
1232
+ ]);
1233
+
1100
1234
  });
1101
1235
  });
1102
1236
 
@@ -2,6 +2,7 @@ import {assert} from '@webex/test-helper-chai';
2
2
  import {NewMetrics} from '@webex/internal-plugin-metrics';
3
3
  import MockWebex from '@webex/test-helper-mock-webex';
4
4
  import sinon from 'sinon';
5
+ import {Utils} from '@webex/internal-plugin-metrics';
5
6
 
6
7
  describe('internal-plugin-metrics', () => {
7
8
  describe('new-metrics', () => {
@@ -18,7 +19,11 @@ describe('internal-plugin-metrics', () => {
18
19
  get: sinon.stub(),
19
20
  },
20
21
  },
21
- request: sinon.stub().resolves({})
22
+ request: sinon.stub().resolves({}),
23
+ logger: {
24
+ log: sinon.stub(),
25
+ error: sinon.stub(),
26
+ }
22
27
  });
23
28
 
24
29
  webex.emit('ready');
@@ -34,6 +39,10 @@ describe('internal-plugin-metrics', () => {
34
39
  webex.setTimingsAndFetch = sinon.stub();
35
40
  });
36
41
 
42
+ afterEach(() => {
43
+ sinon.restore();
44
+ })
45
+
37
46
  it('submits Client Event successfully', () => {
38
47
  webex.internal.newMetrics.submitClientEvent({
39
48
  name: 'client.alert.displayed',
@@ -99,8 +108,9 @@ describe('internal-plugin-metrics', () => {
99
108
  });
100
109
 
101
110
  describe('#clientMetricsAliasUser', () => {
102
- it('aliases the user correctly', () => {
103
- webex.internal.newMetrics.clientMetricsAliasUser('my-id');
111
+ it('aliases the user correctly', async () => {
112
+ webex.request.resolves({response: 'abc'});
113
+ await webex.internal.newMetrics.clientMetricsAliasUser('my-id');
104
114
  assert.calledWith(webex.request, {
105
115
  method: 'POST',
106
116
  api: 'metrics',
@@ -109,12 +119,32 @@ describe('internal-plugin-metrics', () => {
109
119
  body: {},
110
120
  qs: { alias: true }
111
121
  });
112
- })
122
+ assert.calledWith(
123
+ webex.logger.log,
124
+ 'NewMetrics: @clientMetricsAliasUser. Request successful:',
125
+ 'res: {"response":"abc"}'
126
+ );
127
+ });
128
+
129
+ it('handles failed request correctly', async () => {
130
+ webex.request.rejects(new Error("test error"));
131
+ sinon.stub(Utils, 'generateCommonErrorMetadata').returns('formattedError')
132
+ try {
133
+ await webex.internal.newMetrics.clientMetricsAliasUser({event: 'test'}, 'my-id');
134
+ } catch (err) {
135
+ assert.calledWith(
136
+ webex.logger.error,
137
+ 'NewMetrics: @clientMetricsAliasUser. Request failed:',
138
+ `err: formattedError`
139
+ );
140
+ }
141
+ });
113
142
  });
114
143
 
115
144
  describe('#postPreLoginMetric', () => {
116
- it('sends the request correctly', () => {
117
- webex.internal.newMetrics.postPreLoginMetric({event: 'test'}, 'my-id');
145
+ it('sends the request correctly', async () => {
146
+ webex.request.resolves({response: 'abc'});
147
+ await webex.internal.newMetrics.postPreLoginMetric({event: 'test'}, 'my-id');
118
148
  assert.calledWith(webex.request, {
119
149
  method: 'POST',
120
150
  api: 'metrics',
@@ -122,7 +152,26 @@ describe('internal-plugin-metrics', () => {
122
152
  headers: { 'x-prelogin-userid': 'my-id', authorization: false },
123
153
  body: {event: 'test'},
124
154
  });
125
- })
155
+ assert.calledWith(
156
+ webex.logger.log,
157
+ 'NewMetrics: @postPreLoginMetric. Request successful:',
158
+ 'res: {"response":"abc"}'
159
+ );
160
+ });
161
+
162
+ it('handles failed request correctly', async () => {
163
+ webex.request.rejects(new Error("test error"));
164
+ sinon.stub(Utils, 'generateCommonErrorMetadata').returns('formattedError')
165
+ try {
166
+ await webex.internal.newMetrics.postPreLoginMetric({event: 'test'}, 'my-id');
167
+ } catch (err) {
168
+ assert.calledWith(
169
+ webex.logger.error,
170
+ 'NewMetrics: @postPreLoginMetric. Request failed:',
171
+ `err: formattedError`
172
+ );
173
+ }
174
+ });
126
175
  })
127
176
 
128
177
  describe('#buildClientEventFetchRequestOptions', () => {
@@ -0,0 +1,22 @@
1
+ import {assert} from '@webex/test-helper-chai';
2
+ import {Utils} from '@webex/internal-plugin-metrics';
3
+
4
+ describe('internal-plugin-metrics', () => {
5
+ describe('generateCommonErrorMetadata', () => {
6
+ it('should return JSON stringified error object', () => {
7
+ const error = new Error('test error');
8
+ const result = Utils.generateCommonErrorMetadata(error);
9
+ assert.deepEqual(result, JSON.stringify({
10
+ message: 'test error',
11
+ name: 'Error',
12
+ stack: error.stack
13
+ }))
14
+ });
15
+
16
+ it('should return error if not instanceof Error', () => {
17
+ const error = 'test error';
18
+ const result = Utils.generateCommonErrorMetadata(error);
19
+ assert.deepEqual(result, 'test error')
20
+ });
21
+ });
22
+ })