@webex/internal-plugin-metrics 3.0.0-beta.26 → 3.0.0-beta.261

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 (60) hide show
  1. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +65 -0
  2. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -0
  3. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +446 -0
  4. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -0
  5. package/dist/call-diagnostic/call-diagnostic-metrics.js +728 -0
  6. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -0
  7. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +281 -0
  8. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -0
  9. package/dist/call-diagnostic/config.js +620 -0
  10. package/dist/call-diagnostic/config.js.map +1 -0
  11. package/dist/config.js +20 -1
  12. package/dist/config.js.map +1 -1
  13. package/dist/index.js +30 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/metrics.js +30 -30
  16. package/dist/metrics.js.map +1 -1
  17. package/dist/metrics.types.js +7 -0
  18. package/dist/metrics.types.js.map +1 -0
  19. package/dist/new-metrics.js +333 -0
  20. package/dist/new-metrics.js.map +1 -0
  21. package/dist/types/batcher.d.ts +2 -0
  22. package/dist/types/call-diagnostic/call-diagnostic-metrics-batcher.d.ts +2 -0
  23. package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +189 -0
  24. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +391 -0
  25. package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +73 -0
  26. package/dist/types/call-diagnostic/config.d.ts +91 -0
  27. package/dist/types/client-metrics-batcher.d.ts +2 -0
  28. package/dist/types/config.d.ts +35 -0
  29. package/dist/types/index.d.ts +13 -0
  30. package/dist/types/metrics.d.ts +3 -0
  31. package/dist/types/metrics.types.d.ts +99 -0
  32. package/dist/types/new-metrics.d.ts +139 -0
  33. package/dist/types/utils.d.ts +6 -0
  34. package/dist/utils.js +27 -0
  35. package/dist/utils.js.map +1 -0
  36. package/package.json +13 -8
  37. package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +82 -0
  38. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +403 -0
  39. package/src/call-diagnostic/call-diagnostic-metrics.ts +784 -0
  40. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +291 -0
  41. package/src/call-diagnostic/config.ts +618 -0
  42. package/src/config.js +19 -0
  43. package/src/index.ts +43 -0
  44. package/src/metrics.js +25 -27
  45. package/src/metrics.types.ts +152 -0
  46. package/src/new-metrics.ts +317 -0
  47. package/src/utils.ts +17 -0
  48. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +394 -0
  49. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +465 -0
  50. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +1550 -0
  51. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +479 -0
  52. package/test/unit/spec/metrics.js +65 -97
  53. package/test/unit/spec/new-metrics.ts +269 -0
  54. package/test/unit/spec/utils.ts +22 -0
  55. package/tsconfig.json +6 -0
  56. package/dist/call-diagnostic-events-batcher.js +0 -60
  57. package/dist/call-diagnostic-events-batcher.js.map +0 -1
  58. package/src/call-diagnostic-events-batcher.js +0 -62
  59. package/src/index.js +0 -17
  60. package/test/unit/spec/call-diagnostic-events-batcher.js +0 -195
@@ -0,0 +1,394 @@
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ import {assert} from '@webex/test-helper-chai';
6
+ import {config, Utils} from '@webex/internal-plugin-metrics';
7
+ import {CallDiagnosticUtils} from '@webex/internal-plugin-metrics';
8
+ import MockWebex from '@webex/test-helper-mock-webex';
9
+ import sinon from 'sinon';
10
+ import FakeTimers from '@sinonjs/fake-timers';
11
+ import {NewMetrics} from '@webex/internal-plugin-metrics';
12
+ import { uniqueId } from 'lodash';
13
+
14
+ const flushPromises = () => new Promise(setImmediate);
15
+
16
+ function promiseTick(count) {
17
+ let promise = Promise.resolve();
18
+
19
+ while (count > 1) {
20
+ promise = promise.then(() => promiseTick(1));
21
+ count -= 1;
22
+ }
23
+
24
+ return promise;
25
+ }
26
+
27
+
28
+ describe('plugin-metrics', () => {
29
+ describe('CallDiagnosticEventsBatcher', () => {
30
+ let webex;
31
+ let clock;
32
+ let now;
33
+
34
+
35
+ beforeEach(() => {
36
+ now = new Date();
37
+ clock = FakeTimers.install({now});
38
+
39
+ //@ts-ignore
40
+ webex = new MockWebex({
41
+ children: {
42
+ newMetrics: NewMetrics
43
+ }
44
+ });
45
+
46
+ webex.request = (options) => Promise.resolve({body: {items: []}, options});
47
+ sinon.spy(webex, 'request');
48
+
49
+ webex.emit("ready");
50
+
51
+ webex.config.metrics = config.metrics;
52
+ });
53
+
54
+ afterEach(() => {
55
+ sinon.restore();
56
+ clock.uninstall();
57
+ });
58
+
59
+ describe('#request()', () => {
60
+ describe('when the request completes successfully', async () => {
61
+ it('clears the queue', async () => {
62
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
63
+ //@ts-ignore
64
+ {event: {name: 'client.interstitial-window.launched'}}
65
+ );
66
+ await flushPromises();
67
+ clock.tick(config.metrics.batcherWait);
68
+
69
+ await promise;
70
+
71
+ //@ts-ignore
72
+ assert.calledOnce(webex.request);
73
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
74
+ });
75
+
76
+ it('doesnt include any joinTimes for other events', async () => {
77
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
78
+ //@ts-ignore
79
+ {event: {name: 'client.alert.displayed'}}
80
+ );
81
+ await flushPromises();
82
+ clock.tick(config.metrics.batcherWait);
83
+
84
+ await promise;
85
+
86
+ //@ts-ignore
87
+ assert.calledOnce(webex.request);
88
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
89
+ name: 'client.alert.displayed',
90
+ });
91
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
92
+ });
93
+
94
+ it('appends the correct join times to the request for client.interstitial-window.launched', async () => {
95
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
96
+ webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitial = sinon.stub().returns(10);
97
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
98
+ //@ts-ignore
99
+ {event: {name: 'client.interstitial-window.launched'}}
100
+ );
101
+ await flushPromises();
102
+ clock.tick(config.metrics.batcherWait);
103
+
104
+ await promise;
105
+
106
+ //@ts-ignore
107
+ assert.calledOnce(webex.request);
108
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
109
+ name: 'client.interstitial-window.launched',
110
+ joinTimes: {
111
+ clickToInterstitial: 10,
112
+ meetingInfoReqResp: 10,
113
+ },
114
+ });
115
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
116
+ });
117
+
118
+ it('appends the correct join times to the request for client.call.initiated', async () => {
119
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
120
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
121
+ //@ts-ignore
122
+ {event: {name: 'client.call.initiated'}}
123
+ );
124
+ await flushPromises();
125
+ clock.tick(config.metrics.batcherWait);
126
+
127
+ await promise;
128
+ //@ts-ignore
129
+ assert.calledOnce(webex.request);
130
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
131
+ name: 'client.call.initiated',
132
+ joinTimes: {
133
+ meetingInfoReqResp: 10,
134
+ showInterstitialTime: 10,
135
+ },
136
+ });
137
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
138
+ });
139
+
140
+ it('appends the correct join times to the request for client.locus.join.response', async () => {
141
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
142
+ webex.internal.newMetrics.callDiagnosticLatencies.getJoinRespSentReceived = sinon.stub().returns(20);
143
+ webex.internal.newMetrics.callDiagnosticLatencies.getPageJMT = sinon.stub().returns(30);
144
+ webex.internal.newMetrics.callDiagnosticLatencies.getClientJMT = sinon.stub().returns(5);
145
+ webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitial = sinon.stub().returns(10);
146
+ webex.internal.newMetrics.callDiagnosticLatencies.getCallInitJoinReq = sinon.stub().returns(10);
147
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
148
+ //@ts-ignore
149
+ {event: {name: 'client.locus.join.response'}}
150
+ );
151
+ await flushPromises();
152
+ clock.tick(config.metrics.batcherWait);
153
+
154
+ await promise;
155
+
156
+ //@ts-ignore
157
+ assert.calledOnce(webex.request);
158
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
159
+ name: 'client.locus.join.response',
160
+ joinTimes: {
161
+ callInitJoinReq: 10,
162
+ clickToInterstitial: 10,
163
+ interstitialToJoinOK: 10,
164
+ joinReqResp: 10,
165
+ joinReqSentReceived: 20,
166
+ meetingInfoReqResp: 10,
167
+ pageJmt: 30,
168
+ totalJmt: 20,
169
+ clientJmt: 5,
170
+ },
171
+ });
172
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
173
+ });
174
+
175
+ it('appends the correct join times to the request for client.ice.end', async () => {
176
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
177
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
178
+ //@ts-ignore
179
+ {event: {name: 'client.ice.end'}}
180
+ );
181
+ await flushPromises();
182
+ clock.tick(config.metrics.batcherWait);
183
+
184
+ await promise;
185
+
186
+ //@ts-ignore
187
+ assert.calledOnce(webex.request);
188
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
189
+ name: 'client.ice.end',
190
+ joinTimes: {
191
+ ICESetupTime: 10,
192
+ audioICESetupTime: 10,
193
+ shareICESetupTime: 10,
194
+ videoICESetupTime: 10,
195
+ },
196
+ });
197
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
198
+ });
199
+
200
+ it('appends the correct join times to the request for client.media.rx.start', async () => {
201
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
202
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
203
+ //@ts-ignore
204
+ {event: {name: 'client.media.rx.start'}}
205
+ );
206
+ await flushPromises();
207
+ clock.tick(config.metrics.batcherWait);
208
+
209
+ await promise;
210
+
211
+ //@ts-ignore
212
+ assert.calledOnce(webex.request);
213
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
214
+ name: 'client.media.rx.start',
215
+ joinTimes: {
216
+ localSDPGenRemoteSDPRecv: 10,
217
+ },
218
+ });
219
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
220
+ });
221
+
222
+ it('appends the correct join times to the request for client.media-engine.ready', async () => {
223
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
224
+ webex.internal.newMetrics.callDiagnosticLatencies.getInterstitialToMediaOKJMT = sinon.stub().returns(10);
225
+ webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitial = sinon.stub().returns(10);
226
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
227
+ //@ts-ignore
228
+ {event: {name: 'client.media-engine.ready'}}
229
+ );
230
+ await flushPromises();
231
+ clock.tick(config.metrics.batcherWait);
232
+
233
+ await promise;
234
+
235
+ //@ts-ignore
236
+ assert.calledOnce(webex.request);
237
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
238
+ name: 'client.media-engine.ready',
239
+ joinTimes: {
240
+ totalMediaJMT: 30,
241
+ interstitialToMediaOKJMT: 10,
242
+ callInitMediaEngineReady: 10,
243
+ stayLobbyTime: 10,
244
+ },
245
+ });
246
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
247
+ });
248
+
249
+ it('appends the correct audio and video setup delays to the request for client.mediaquality.event', async () => {
250
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
251
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
252
+ //@ts-ignore
253
+ {event: {name: 'client.mediaquality.event'}}
254
+ );
255
+ await flushPromises();
256
+ clock.tick(config.metrics.batcherWait);
257
+
258
+ await promise;
259
+
260
+ //@ts-ignore
261
+ assert.calledOnce(webex.request);
262
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
263
+ name: 'client.mediaquality.event',
264
+ audioSetupDelay: {
265
+ joinRespRxStart: 10,
266
+ joinRespTxStart: 10,
267
+ },
268
+ videoSetupDelay: {
269
+ joinRespRxStart: 10,
270
+ joinRespTxStart: 10,
271
+ }
272
+ });
273
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
274
+ });
275
+
276
+ it('doesnt include audioSetup and videoSetup delays for other events', async () => {
277
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
278
+ //@ts-ignore
279
+ {event: {name: 'client.alert.displayed'}}
280
+ );
281
+ await flushPromises();
282
+ clock.tick(config.metrics.batcherWait);
283
+
284
+ await promise;
285
+
286
+ //@ts-ignore
287
+ assert.calledOnce(webex.request);
288
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event.audioSetupDelay, undefined);
289
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event.videoSetupDelay, undefined);
290
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
291
+ })
292
+ });
293
+
294
+ describe('when the request fails', () => {
295
+ it('does not clear the queue', async () => {
296
+ // avoid setting .sent timestamp
297
+ webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.prepareRequest =
298
+ (q) => Promise.resolve(q);
299
+
300
+ const err = new Error('error');
301
+ webex.request = sinon.stub().returns(Promise.reject(err));
302
+
303
+ webex.logger.error = sinon.stub();
304
+ webex.logger.log = sinon.stub();
305
+ sinon.stub(Utils, 'generateCommonErrorMetadata').returns('formattedError');
306
+
307
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics({
308
+ event: 'my.event',
309
+ });
310
+
311
+ await flushPromises();
312
+ clock.tick(config.metrics.batcherWait);
313
+
314
+ let error;
315
+
316
+ // catch the expected error and store it
317
+ await promise.catch((e) => {
318
+ error = e;
319
+ });
320
+
321
+ const loggerLogCalls = webex.logger.log.getCalls();
322
+
323
+ assert.deepEqual(loggerLogCalls[0].args, [
324
+ 'call-diagnostic-events -> ',
325
+ 'CallDiagnosticMetrics: @submitToCallDiagnostics. Preparing to send the request',
326
+ `finalEvent: {"eventPayload":{"event":"my.event"},"type":["diagnostic-event"]}`,
327
+ ]);
328
+
329
+ // This is horrific, but stubbing lodash is proving difficult
330
+ const expectedBatchId = parseInt(uniqueId()) - 1;
331
+
332
+ assert.deepEqual(JSON.stringify(loggerLogCalls[1].args), `["call-diagnostic-events -> ","CallDiagnosticEventsBatcher: @submitHttpRequest#call-diagnostic-metrics-batch-${expectedBatchId}. Sending the request:","payload:",[{"eventPayload":{"event":"my.event","origin":{"buildType":"test","networkType":"unknown"}},"type":["diagnostic-event"]}]]`);
333
+
334
+ // check that promise was rejected with the original error of the webex.request
335
+ assert.deepEqual(err, error);
336
+
337
+ assert.calledOnceWithExactly(
338
+ webex.logger.error,
339
+ 'call-diagnostic-events -> ',
340
+ `CallDiagnosticEventsBatcher: @submitHttpRequest#call-diagnostic-metrics-batch-${expectedBatchId}. Request failed:`,
341
+ `error: formattedError`
342
+ );
343
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
344
+ });
345
+ });
346
+ });
347
+
348
+ describe('prepareItem', () => {
349
+ it('calls prepareDiagnosticMetricItem correctly', async () => {
350
+ // avoid setting .sent timestamp
351
+ webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.prepareRequest =
352
+ (q) => Promise.resolve(q);
353
+
354
+ const prepareItemSpy = sinon.spy(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher, 'prepareItem');
355
+ const prepareDiagnosticMetricItemSpy = sinon.spy(CallDiagnosticUtils, 'prepareDiagnosticMetricItem');
356
+
357
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics({
358
+ event: 'my.event',
359
+ });
360
+
361
+ await flushPromises();
362
+
363
+ clock.tick(config.metrics.batcherWait);
364
+
365
+ await promise;
366
+
367
+ const calls = prepareItemSpy.getCalls()[0];
368
+
369
+ // item also gets assigned a delay property but the key is a Symbol and haven't been able to test that..
370
+ assert.deepEqual(calls.args[0].eventPayload, {
371
+ event: 'my.event',
372
+ origin: {buildType: 'test', networkType: 'unknown'},
373
+ });
374
+
375
+ assert.deepEqual(calls.args[0].type, ['diagnostic-event']);
376
+
377
+
378
+ const prepareDiagnosticMetricItemCalls = prepareDiagnosticMetricItemSpy.getCalls()
379
+
380
+ // second argument (item) also gets assigned a delay property but the key is a Symbol and haven't been able to test that..
381
+ assert.deepEqual(prepareDiagnosticMetricItemCalls[0].args[0], webex);
382
+ assert.deepEqual(prepareDiagnosticMetricItemCalls[0].args[1].eventPayload, {
383
+ event: 'my.event',
384
+ origin: {
385
+ buildType: 'test',
386
+ networkType: 'unknown',
387
+ },
388
+ });
389
+ assert.deepEqual(prepareDiagnosticMetricItemCalls[0].args[1].type, ['diagnostic-event']);
390
+
391
+ })
392
+ })
393
+ });
394
+ });