@webex/internal-plugin-metrics 3.0.0-beta.23 → 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 (60) hide show
  1. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +66 -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 +693 -0
  6. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -0
  7. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +276 -0
  8. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -0
  9. package/dist/call-diagnostic/config.js +582 -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 +28 -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 +316 -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 +385 -0
  25. package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +73 -0
  26. package/dist/types/call-diagnostic/config.d.ts +87 -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 +12 -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 +133 -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 +80 -0
  38. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +403 -0
  39. package/src/call-diagnostic/call-diagnostic-metrics.ts +751 -0
  40. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +280 -0
  41. package/src/call-diagnostic/config.ts +580 -0
  42. package/src/config.js +19 -0
  43. package/src/index.ts +42 -0
  44. package/src/metrics.js +25 -27
  45. package/src/metrics.types.ts +152 -0
  46. package/src/new-metrics.ts +304 -0
  47. package/src/utils.ts +17 -0
  48. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +351 -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 +1283 -0
  51. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +454 -0
  52. package/test/unit/spec/metrics.js +65 -97
  53. package/test/unit/spec/new-metrics.ts +234 -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,351 @@
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 MockWebex from '@webex/test-helper-mock-webex';
8
+ import sinon from 'sinon';
9
+ import FakeTimers from '@sinonjs/fake-timers';
10
+ import {NewMetrics} from '@webex/internal-plugin-metrics';
11
+ import { uniqueId } from 'lodash';
12
+
13
+ const flushPromises = () => new Promise(setImmediate);
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
+
27
+ describe('plugin-metrics', () => {
28
+ describe('CallDiagnosticEventsBatcher', () => {
29
+ let webex;
30
+ let clock;
31
+ let now;
32
+
33
+
34
+ beforeEach(() => {
35
+ now = new Date();
36
+ clock = FakeTimers.install({now});
37
+
38
+ //@ts-ignore
39
+ webex = new MockWebex({
40
+ children: {
41
+ newMetrics: NewMetrics
42
+ }
43
+ });
44
+
45
+ webex.request = (options) => Promise.resolve({body: {items: []}, options});
46
+ sinon.spy(webex, 'request');
47
+
48
+ webex.emit("ready");
49
+
50
+ webex.config.metrics = config.metrics;
51
+ });
52
+
53
+ afterEach(() => {
54
+ sinon.restore();
55
+ clock.uninstall();
56
+ });
57
+
58
+ describe('#request()', () => {
59
+ describe('when the request completes successfully', async () => {
60
+ it('clears the queue', async () => {
61
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
62
+ //@ts-ignore
63
+ {event: {name: 'client.interstitial-window.launched'}}
64
+ );
65
+ await flushPromises();
66
+ clock.tick(config.metrics.batcherWait);
67
+
68
+ await promise;
69
+
70
+ //@ts-ignore
71
+ assert.calledOnce(webex.request);
72
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
73
+ });
74
+
75
+ it('doesnt include any joinTimes for other events', async () => {
76
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
77
+ //@ts-ignore
78
+ {event: {name: 'client.alert.displayed'}}
79
+ );
80
+ await flushPromises();
81
+ clock.tick(config.metrics.batcherWait);
82
+
83
+ await promise;
84
+
85
+ //@ts-ignore
86
+ assert.calledOnce(webex.request);
87
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
88
+ name: 'client.alert.displayed',
89
+ });
90
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
91
+ });
92
+
93
+ it('appends the correct join times to the request for client.interstitial-window.launched', async () => {
94
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
95
+ webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitial = sinon.stub().returns(10);
96
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
97
+ //@ts-ignore
98
+ {event: {name: 'client.interstitial-window.launched'}}
99
+ );
100
+ await flushPromises();
101
+ clock.tick(config.metrics.batcherWait);
102
+
103
+ await promise;
104
+
105
+ //@ts-ignore
106
+ assert.calledOnce(webex.request);
107
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
108
+ name: 'client.interstitial-window.launched',
109
+ joinTimes: {
110
+ clickToInterstitial: 10,
111
+ meetingInfoReqResp: 10,
112
+ },
113
+ });
114
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
115
+ });
116
+
117
+ it('appends the correct join times to the request for client.call.initiated', async () => {
118
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
119
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
120
+ //@ts-ignore
121
+ {event: {name: 'client.call.initiated'}}
122
+ );
123
+ await flushPromises();
124
+ clock.tick(config.metrics.batcherWait);
125
+
126
+ await promise;
127
+ //@ts-ignore
128
+ assert.calledOnce(webex.request);
129
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
130
+ name: 'client.call.initiated',
131
+ joinTimes: {
132
+ meetingInfoReqResp: 10,
133
+ showInterstitialTime: 10,
134
+ },
135
+ });
136
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
137
+ });
138
+
139
+ it('appends the correct join times to the request for client.locus.join.response', async () => {
140
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
141
+ webex.internal.newMetrics.callDiagnosticLatencies.getJoinRespSentReceived = sinon.stub().returns(20);
142
+ webex.internal.newMetrics.callDiagnosticLatencies.getPageJMT = sinon.stub().returns(30);
143
+ webex.internal.newMetrics.callDiagnosticLatencies.getClientJMT = sinon.stub().returns(5);
144
+ webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitial = sinon.stub().returns(10);
145
+ webex.internal.newMetrics.callDiagnosticLatencies.getCallInitJoinReq = sinon.stub().returns(10);
146
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
147
+ //@ts-ignore
148
+ {event: {name: 'client.locus.join.response'}}
149
+ );
150
+ await flushPromises();
151
+ clock.tick(config.metrics.batcherWait);
152
+
153
+ await promise;
154
+
155
+ //@ts-ignore
156
+ assert.calledOnce(webex.request);
157
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
158
+ name: 'client.locus.join.response',
159
+ joinTimes: {
160
+ callInitJoinReq: 10,
161
+ clickToInterstitial: 10,
162
+ interstitialToJoinOK: 10,
163
+ joinReqResp: 10,
164
+ joinReqSentReceived: 20,
165
+ meetingInfoReqResp: 10,
166
+ pageJmt: 30,
167
+ totalJmt: 20,
168
+ clientJmt: 5,
169
+ },
170
+ });
171
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
172
+ });
173
+
174
+ it('appends the correct join times to the request for client.ice.end', async () => {
175
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
176
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
177
+ //@ts-ignore
178
+ {event: {name: 'client.ice.end'}}
179
+ );
180
+ await flushPromises();
181
+ clock.tick(config.metrics.batcherWait);
182
+
183
+ await promise;
184
+
185
+ //@ts-ignore
186
+ assert.calledOnce(webex.request);
187
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
188
+ name: 'client.ice.end',
189
+ joinTimes: {
190
+ ICESetupTime: 10,
191
+ audioICESetupTime: 10,
192
+ shareICESetupTime: 10,
193
+ videoICESetupTime: 10,
194
+ },
195
+ });
196
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
197
+ });
198
+
199
+ it('appends the correct join times to the request for client.media.rx.start', async () => {
200
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
201
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
202
+ //@ts-ignore
203
+ {event: {name: 'client.media.rx.start'}}
204
+ );
205
+ await flushPromises();
206
+ clock.tick(config.metrics.batcherWait);
207
+
208
+ await promise;
209
+
210
+ //@ts-ignore
211
+ assert.calledOnce(webex.request);
212
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
213
+ name: 'client.media.rx.start',
214
+ joinTimes: {
215
+ localSDPGenRemoteSDPRecv: 10,
216
+ },
217
+ });
218
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
219
+ });
220
+
221
+ it('appends the correct join times to the request for client.media-engine.ready', async () => {
222
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
223
+ webex.internal.newMetrics.callDiagnosticLatencies.getInterstitialToMediaOKJMT = sinon.stub().returns(10);
224
+ webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitial = sinon.stub().returns(10);
225
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
226
+ //@ts-ignore
227
+ {event: {name: 'client.media-engine.ready'}}
228
+ );
229
+ await flushPromises();
230
+ clock.tick(config.metrics.batcherWait);
231
+
232
+ await promise;
233
+
234
+ //@ts-ignore
235
+ assert.calledOnce(webex.request);
236
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
237
+ name: 'client.media-engine.ready',
238
+ joinTimes: {
239
+ totalMediaJMT: 30,
240
+ interstitialToMediaOKJMT: 10,
241
+ callInitMediaEngineReady: 10,
242
+ stayLobbyTime: 10,
243
+ },
244
+ });
245
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
246
+ });
247
+
248
+ it('appends the correct audio and video setup delays to the request for client.mediaquality.event', async () => {
249
+ webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon.stub().returns(10);
250
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
251
+ //@ts-ignore
252
+ {event: {name: 'client.mediaquality.event'}}
253
+ );
254
+ await flushPromises();
255
+ clock.tick(config.metrics.batcherWait);
256
+
257
+ await promise;
258
+
259
+ //@ts-ignore
260
+ assert.calledOnce(webex.request);
261
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
262
+ name: 'client.mediaquality.event',
263
+ audioSetupDelay: {
264
+ joinRespRxStart: 10,
265
+ joinRespTxStart: 10,
266
+ },
267
+ videoSetupDelay: {
268
+ joinRespRxStart: 10,
269
+ joinRespTxStart: 10,
270
+ }
271
+ });
272
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
273
+ });
274
+
275
+ it('doesnt include audioSetup and videoSetup delays for other events', async () => {
276
+ const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
277
+ //@ts-ignore
278
+ {event: {name: 'client.alert.displayed'}}
279
+ );
280
+ await flushPromises();
281
+ clock.tick(config.metrics.batcherWait);
282
+
283
+ await promise;
284
+
285
+ //@ts-ignore
286
+ assert.calledOnce(webex.request);
287
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event.audioSetupDelay, undefined);
288
+ assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event.videoSetupDelay, undefined);
289
+ assert.lengthOf(webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue, 0);
290
+ })
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
+ });
349
+ });
350
+ });
351
+ });