@webex/internal-plugin-metrics 3.0.0-beta.26 → 3.0.0-beta.260
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/call-diagnostic/call-diagnostic-metrics-batcher.js +65 -0
- package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -0
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +446 -0
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.js +728 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js +281 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -0
- package/dist/call-diagnostic/config.js +620 -0
- package/dist/call-diagnostic/config.js.map +1 -0
- package/dist/config.js +20 -1
- package/dist/config.js.map +1 -1
- package/dist/index.js +30 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics.js +30 -30
- package/dist/metrics.js.map +1 -1
- package/dist/metrics.types.js +7 -0
- package/dist/metrics.types.js.map +1 -0
- package/dist/new-metrics.js +333 -0
- package/dist/new-metrics.js.map +1 -0
- package/dist/types/batcher.d.ts +2 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics-batcher.d.ts +2 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +189 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +391 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +73 -0
- package/dist/types/call-diagnostic/config.d.ts +91 -0
- package/dist/types/client-metrics-batcher.d.ts +2 -0
- package/dist/types/config.d.ts +35 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/metrics.d.ts +3 -0
- package/dist/types/metrics.types.d.ts +99 -0
- package/dist/types/new-metrics.d.ts +139 -0
- package/dist/types/utils.d.ts +6 -0
- package/dist/utils.js +27 -0
- package/dist/utils.js.map +1 -0
- package/package.json +13 -8
- package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +82 -0
- package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +403 -0
- package/src/call-diagnostic/call-diagnostic-metrics.ts +784 -0
- package/src/call-diagnostic/call-diagnostic-metrics.util.ts +291 -0
- package/src/call-diagnostic/config.ts +618 -0
- package/src/config.js +19 -0
- package/src/index.ts +43 -0
- package/src/metrics.js +25 -27
- package/src/metrics.types.ts +152 -0
- package/src/new-metrics.ts +317 -0
- package/src/utils.ts +17 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +394 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +465 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +1550 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +479 -0
- package/test/unit/spec/metrics.js +65 -97
- package/test/unit/spec/new-metrics.ts +269 -0
- package/test/unit/spec/utils.ts +22 -0
- package/tsconfig.json +6 -0
- package/dist/call-diagnostic-events-batcher.js +0 -60
- package/dist/call-diagnostic-events-batcher.js.map +0 -1
- package/src/call-diagnostic-events-batcher.js +0 -62
- package/src/index.js +0 -17
- package/test/unit/spec/call-diagnostic-events-batcher.js +0 -195
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
import {assert} from '@webex/test-helper-chai';
|
|
2
|
+
import sinon from 'sinon';
|
|
3
|
+
|
|
4
|
+
import * as CallDiagnosticUtils from '../../../../src/call-diagnostic/call-diagnostic-metrics.util';
|
|
5
|
+
import CallDiagnosticLatencies from '../../../../src/call-diagnostic/call-diagnostic-metrics-latencies';
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
clearEmptyKeysRecursively,
|
|
9
|
+
extractVersionMetadata,
|
|
10
|
+
getBuildType,
|
|
11
|
+
isBrowserMediaErrorName,
|
|
12
|
+
isLocusServiceErrorCode,
|
|
13
|
+
isMeetingInfoServiceError,
|
|
14
|
+
prepareDiagnosticMetricItem,
|
|
15
|
+
setMetricTimings,
|
|
16
|
+
} = CallDiagnosticUtils;
|
|
17
|
+
|
|
18
|
+
describe('internal-plugin-metrics', () => {
|
|
19
|
+
describe('clearEmptyKeysRecursively', () => {
|
|
20
|
+
it('should clear empty objects and empty nested objects recursively', () => {
|
|
21
|
+
const obj: any = {
|
|
22
|
+
foo: '',
|
|
23
|
+
bar: {},
|
|
24
|
+
baz: [],
|
|
25
|
+
nested: {
|
|
26
|
+
prop: {},
|
|
27
|
+
arr: ['test'],
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
clearEmptyKeysRecursively(obj);
|
|
31
|
+
console.log(obj);
|
|
32
|
+
assert.deepEqual(obj, {nested: {arr: ['test']}});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should not modify non-empty objects and arrays', () => {
|
|
36
|
+
const obj = {
|
|
37
|
+
foo: 'bar',
|
|
38
|
+
arr: [1, 2, 3],
|
|
39
|
+
};
|
|
40
|
+
clearEmptyKeysRecursively(obj);
|
|
41
|
+
assert.deepEqual(obj, {foo: 'bar', arr: [1, 2, 3]});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should not modify non-object and non-array values', () => {
|
|
45
|
+
const obj = {
|
|
46
|
+
prop1: 'value1',
|
|
47
|
+
prop2: 123,
|
|
48
|
+
};
|
|
49
|
+
clearEmptyKeysRecursively(obj);
|
|
50
|
+
assert.deepEqual(obj, {prop1: 'value1', prop2: 123});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('should handle nested empty objects and arrays', () => {
|
|
54
|
+
const obj: any = {
|
|
55
|
+
foo: {
|
|
56
|
+
bar: {},
|
|
57
|
+
baz: [],
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
clearEmptyKeysRecursively(obj);
|
|
61
|
+
assert.deepEqual(obj, {foo: {}});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should handle an empty input object', () => {
|
|
65
|
+
const obj = {};
|
|
66
|
+
clearEmptyKeysRecursively(obj);
|
|
67
|
+
assert.deepEqual(obj, {});
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('isLocusServiceErrorCode', () => {
|
|
72
|
+
[
|
|
73
|
+
[10000, false],
|
|
74
|
+
[2400000, true],
|
|
75
|
+
['2400000', true],
|
|
76
|
+
[2400001, true],
|
|
77
|
+
['2400001', true],
|
|
78
|
+
[240000, false],
|
|
79
|
+
[14000000, false],
|
|
80
|
+
].forEach(([error, expected]) => {
|
|
81
|
+
it(`for code ${error} returns the correct result`, () => {
|
|
82
|
+
//@ts-ignore
|
|
83
|
+
assert.deepEqual(isLocusServiceErrorCode(error), expected);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('isMeetingInfoServiceError', () => {
|
|
89
|
+
[
|
|
90
|
+
[{body: {data: {meetingInfo: 'something'}}}, true],
|
|
91
|
+
[{body: {url: 'abcde-123-wbxappapi-efgh'}}, true],
|
|
92
|
+
[{body: {data: {meetingInformation: 'something'}}}, false],
|
|
93
|
+
[{body: {uri: 'abcde-123-wbxappap-efgh'}}, false],
|
|
94
|
+
['2400001', false],
|
|
95
|
+
[2400001, false],
|
|
96
|
+
[{}, false],
|
|
97
|
+
].forEach(([rawError, expected]) => {
|
|
98
|
+
it(`for rawError ${rawError} returns the correct result`, () => {
|
|
99
|
+
//@ts-ignore
|
|
100
|
+
assert.deepEqual(isMeetingInfoServiceError(rawError), expected);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe('isBrowserMediaErrorName', () => {
|
|
106
|
+
[
|
|
107
|
+
['PermissionDeniedError', true],
|
|
108
|
+
['PermissionDeniedErrors', false],
|
|
109
|
+
['NotAllowedError', true],
|
|
110
|
+
['NotAllowedErrors', false],
|
|
111
|
+
['NotReadableError', true],
|
|
112
|
+
['NotReadableErrors', false],
|
|
113
|
+
['AbortError', true],
|
|
114
|
+
['AbortErrors', false],
|
|
115
|
+
['NotFoundError', true],
|
|
116
|
+
['NotFoundErrors', false],
|
|
117
|
+
['OverconstrainedError', true],
|
|
118
|
+
['OverconstrainedErrors', false],
|
|
119
|
+
['SecurityError', true],
|
|
120
|
+
['SecurityErrors', false],
|
|
121
|
+
['TypeError', true],
|
|
122
|
+
['TypeErrors', false],
|
|
123
|
+
['', false],
|
|
124
|
+
['SomethingElse', false],
|
|
125
|
+
[{name: 'SomethingElse'}, false],
|
|
126
|
+
|
|
127
|
+
].forEach(([errorName, expected]) => {
|
|
128
|
+
it(`for rawError ${errorName} returns the correct result`, () => {
|
|
129
|
+
//@ts-ignore
|
|
130
|
+
assert.deepEqual(isBrowserMediaErrorName(errorName), expected);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe('getBuildType', () => {
|
|
136
|
+
beforeEach(() => {
|
|
137
|
+
process.env.NODE_ENV = 'production';
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
[
|
|
141
|
+
['https://localhost', undefined, 'test'],
|
|
142
|
+
['https://127.0.0.1', undefined, 'test'],
|
|
143
|
+
['https://web.webex.com', undefined, 'prod'],
|
|
144
|
+
['https://web.webex.com', true, 'test'],
|
|
145
|
+
].forEach(([webClientDomain, markAsTestEvent, expected]) => {
|
|
146
|
+
it(`returns expected result for ${webClientDomain}`, () => {
|
|
147
|
+
assert.deepEqual(getBuildType(webClientDomain, markAsTestEvent as any), expected);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('returns "test" for NODE_ENV "foo"', () => {
|
|
152
|
+
process.env.NODE_ENV = 'foo';
|
|
153
|
+
assert.deepEqual(getBuildType('production'), 'test');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('returns "test" for NODE_ENV "production" and markAsTestEvent = true', () => {
|
|
157
|
+
process.env.NODE_ENV = 'production';
|
|
158
|
+
assert.deepEqual(getBuildType('my.domain', true), 'test');
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
describe('prepareDiagnosticMetricItem', async () => {
|
|
163
|
+
let webex: any;
|
|
164
|
+
|
|
165
|
+
const check = (eventName: string, expectedEvent: any) => {
|
|
166
|
+
const eventPayload = {event: {name: eventName}};
|
|
167
|
+
const item = prepareDiagnosticMetricItem(webex, {
|
|
168
|
+
eventPayload,
|
|
169
|
+
type: ['diagnostic-event'],
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
assert.deepEqual(item, {
|
|
173
|
+
eventPayload: {
|
|
174
|
+
origin: {
|
|
175
|
+
buildType: 'prod',
|
|
176
|
+
networkType: 'unknown',
|
|
177
|
+
},
|
|
178
|
+
event: {name: eventName, ...expectedEvent},
|
|
179
|
+
},
|
|
180
|
+
type: ['diagnostic-event'],
|
|
181
|
+
});
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
before(async () => {
|
|
185
|
+
webex = {internal: {newMetrics: {}}};
|
|
186
|
+
webex.internal.newMetrics.callDiagnosticLatencies = new CallDiagnosticLatencies(
|
|
187
|
+
{},
|
|
188
|
+
{parent: webex}
|
|
189
|
+
);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
beforeEach(() => {
|
|
193
|
+
process.env.NODE_ENV = 'production';
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
afterEach(() => {
|
|
197
|
+
process.env.NODE_ENV = 'test';
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
[
|
|
201
|
+
['client.exit.app', {}],
|
|
202
|
+
[
|
|
203
|
+
'client.interstitial-window.launched',
|
|
204
|
+
{
|
|
205
|
+
joinTimes: {
|
|
206
|
+
clickToInterstitial: undefined,
|
|
207
|
+
meetingInfoReqResp: undefined,
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
[
|
|
212
|
+
'client.call.initiated',
|
|
213
|
+
{
|
|
214
|
+
joinTimes: {
|
|
215
|
+
showInterstitialTime: undefined,
|
|
216
|
+
meetingInfoReqResp: undefined,
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
[
|
|
221
|
+
'client.locus.join.response',
|
|
222
|
+
{
|
|
223
|
+
joinTimes: {
|
|
224
|
+
meetingInfoReqResp: undefined,
|
|
225
|
+
callInitJoinReq: undefined,
|
|
226
|
+
joinReqResp: undefined,
|
|
227
|
+
joinReqSentReceived: undefined,
|
|
228
|
+
pageJmt: undefined,
|
|
229
|
+
clickToInterstitial: undefined,
|
|
230
|
+
interstitialToJoinOK: undefined,
|
|
231
|
+
totalJmt: undefined,
|
|
232
|
+
clientJmt: undefined,
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
[
|
|
237
|
+
'client.ice.end',
|
|
238
|
+
{
|
|
239
|
+
joinTimes: {
|
|
240
|
+
ICESetupTime: undefined,
|
|
241
|
+
audioICESetupTime: undefined,
|
|
242
|
+
videoICESetupTime: undefined,
|
|
243
|
+
shareICESetupTime: undefined,
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
[
|
|
248
|
+
'client.media.rx.start',
|
|
249
|
+
{
|
|
250
|
+
joinTimes: {
|
|
251
|
+
localSDPGenRemoteSDPRecv: undefined,
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
[
|
|
256
|
+
'client.media-engine.ready',
|
|
257
|
+
{
|
|
258
|
+
joinTimes: {
|
|
259
|
+
totalMediaJMT: undefined,
|
|
260
|
+
interstitialToMediaOKJMT: undefined,
|
|
261
|
+
callInitMediaEngineReady: undefined,
|
|
262
|
+
stayLobbyTime: undefined,
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
[
|
|
267
|
+
'client.mediaquality.event',
|
|
268
|
+
{
|
|
269
|
+
audioSetupDelay: {
|
|
270
|
+
joinRespRxStart: undefined,
|
|
271
|
+
joinRespTxStart: undefined,
|
|
272
|
+
},
|
|
273
|
+
videoSetupDelay: {
|
|
274
|
+
joinRespRxStart: undefined,
|
|
275
|
+
joinRespTxStart: undefined,
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
].forEach(([eventName, expectedEvent]) => {
|
|
280
|
+
it(`returns expected result for ${eventName}`, () => {
|
|
281
|
+
check(eventName as string, expectedEvent);
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it('calls getBuildType correctly', () => {
|
|
286
|
+
const getBuildTypeSpy = sinon.spy(CallDiagnosticUtils, 'getBuildType');
|
|
287
|
+
const markAsTestEvent = true;
|
|
288
|
+
const webClientDomain = 'https://web.webex.com';
|
|
289
|
+
|
|
290
|
+
// just submit any event
|
|
291
|
+
prepareDiagnosticMetricItem(webex, {
|
|
292
|
+
eventPayload: {
|
|
293
|
+
event: {name: 'client.exit.app', eventData: {markAsTestEvent, webClientDomain}}
|
|
294
|
+
},
|
|
295
|
+
type: ['diagnostic-event'],
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
assert.calledOnceWithExactly(getBuildTypeSpy, webClientDomain, markAsTestEvent);
|
|
299
|
+
})
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
describe('setMetricTimings', async () => {
|
|
303
|
+
let webex: any;
|
|
304
|
+
|
|
305
|
+
const check = (options: any, expectedOptions: any) => {
|
|
306
|
+
const newOptions = setMetricTimings(options);
|
|
307
|
+
|
|
308
|
+
assert.deepEqual(newOptions, expectedOptions);
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
it(`returns expected options`, () => {
|
|
312
|
+
const now = new Date();
|
|
313
|
+
sinon.useFakeTimers(now.getTime());
|
|
314
|
+
|
|
315
|
+
const options = {
|
|
316
|
+
json: true,
|
|
317
|
+
body: JSON.stringify({
|
|
318
|
+
metrics: [
|
|
319
|
+
{
|
|
320
|
+
eventPayload: {
|
|
321
|
+
originTime: {
|
|
322
|
+
triggered: 555,
|
|
323
|
+
sent: 666,
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
],
|
|
328
|
+
}),
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
const expectedOptions = {
|
|
332
|
+
json: true,
|
|
333
|
+
body: JSON.stringify({
|
|
334
|
+
metrics: [
|
|
335
|
+
{
|
|
336
|
+
eventPayload: {
|
|
337
|
+
originTime: {
|
|
338
|
+
triggered: now.toISOString(),
|
|
339
|
+
sent: now.toISOString(),
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
],
|
|
344
|
+
}),
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
check(options, expectedOptions);
|
|
348
|
+
sinon.restore();
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it(`returns expected options for multiple metrics`, () => {
|
|
352
|
+
const now = new Date();
|
|
353
|
+
sinon.useFakeTimers(now.getTime());
|
|
354
|
+
|
|
355
|
+
const options = {
|
|
356
|
+
json: true,
|
|
357
|
+
body: JSON.stringify({
|
|
358
|
+
metrics: [
|
|
359
|
+
{
|
|
360
|
+
eventPayload: {
|
|
361
|
+
originTime: {
|
|
362
|
+
triggered: 555,
|
|
363
|
+
sent: 666,
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
eventPayload: {
|
|
369
|
+
originTime: {
|
|
370
|
+
triggered: 777,
|
|
371
|
+
sent: 888,
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
],
|
|
376
|
+
}),
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
const expectedOptions = {
|
|
380
|
+
json: true,
|
|
381
|
+
body: JSON.stringify({
|
|
382
|
+
metrics: [
|
|
383
|
+
{
|
|
384
|
+
eventPayload: {
|
|
385
|
+
originTime: {
|
|
386
|
+
triggered: now.toISOString(),
|
|
387
|
+
sent: now.toISOString(),
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
eventPayload: {
|
|
393
|
+
originTime: {
|
|
394
|
+
triggered: now.toISOString(),
|
|
395
|
+
sent: now.toISOString(),
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
],
|
|
400
|
+
}),
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
check(options, expectedOptions);
|
|
404
|
+
sinon.restore();
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it(`returns expected options when json is falsey`, () => {
|
|
408
|
+
const now = new Date();
|
|
409
|
+
sinon.useFakeTimers(now.getTime());
|
|
410
|
+
|
|
411
|
+
const options = {
|
|
412
|
+
body: JSON.stringify({
|
|
413
|
+
metrics: [
|
|
414
|
+
{
|
|
415
|
+
eventPayload: {
|
|
416
|
+
originTime: {
|
|
417
|
+
triggered: 555,
|
|
418
|
+
sent: 666,
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
},
|
|
422
|
+
],
|
|
423
|
+
}),
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
const expectedOptions = {
|
|
427
|
+
body: JSON.stringify({
|
|
428
|
+
metrics: [
|
|
429
|
+
{
|
|
430
|
+
eventPayload: {
|
|
431
|
+
originTime: {
|
|
432
|
+
triggered: 555,
|
|
433
|
+
sent: 666,
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
],
|
|
438
|
+
}),
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
check(options, expectedOptions);
|
|
442
|
+
sinon.restore();
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
it(`does not throw when there is no body`, () => {
|
|
446
|
+
const options = {};
|
|
447
|
+
|
|
448
|
+
const expectedOptions = {};
|
|
449
|
+
|
|
450
|
+
check(options, expectedOptions);
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
it(`does not throw when body is empty`, () => {
|
|
454
|
+
const options = {body: '"{}"'};
|
|
455
|
+
|
|
456
|
+
const expectedOptions = {body: '"{}"'};
|
|
457
|
+
|
|
458
|
+
check(options, expectedOptions);
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
describe('extractVersionMetadata', () => {
|
|
463
|
+
[
|
|
464
|
+
['1.2.3', {majorVersion: 1, minorVersion: 2}],
|
|
465
|
+
['0.0.1', {majorVersion: 0, minorVersion: 0}],
|
|
466
|
+
['0.0.0', {majorVersion: 0, minorVersion: 0}],
|
|
467
|
+
['1.2', {majorVersion: 1, minorVersion: 2}],
|
|
468
|
+
['1', {majorVersion: 1, minorVersion: NaN}],
|
|
469
|
+
['foo', {majorVersion: NaN, minorVersion: NaN}],
|
|
470
|
+
['1.foo', {majorVersion: 1, minorVersion: NaN}],
|
|
471
|
+
['foo.1', {majorVersion: NaN, minorVersion: 1}],
|
|
472
|
+
['foo.bar', {majorVersion: NaN, minorVersion: NaN}],
|
|
473
|
+
].forEach(([version, expected]) => {
|
|
474
|
+
it(`returns expected result for ${version}`, () => {
|
|
475
|
+
assert.deepEqual(extractVersionMetadata(version as string), expected);
|
|
476
|
+
});
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
});
|
|
@@ -8,6 +8,9 @@ import {Token, Credentials} from '@webex/webex-core';
|
|
|
8
8
|
import FakeTimers from '@sinonjs/fake-timers';
|
|
9
9
|
import sinon from 'sinon';
|
|
10
10
|
import Metrics, {config} from '@webex/internal-plugin-metrics';
|
|
11
|
+
import {BrowserDetection} from '@webex/common';
|
|
12
|
+
|
|
13
|
+
const {getOSVersion} = BrowserDetection();
|
|
11
14
|
|
|
12
15
|
function promiseTick(count) {
|
|
13
16
|
let promise = Promise.resolve();
|
|
@@ -102,7 +105,6 @@ describe('plugin-metrics', () => {
|
|
|
102
105
|
sinon.spy(webex, 'request');
|
|
103
106
|
sinon.spy(metrics, 'postPreLoginMetric');
|
|
104
107
|
sinon.spy(metrics, 'aliasUser');
|
|
105
|
-
sinon.spy(metrics, 'submitCallDiagnosticEvents');
|
|
106
108
|
});
|
|
107
109
|
|
|
108
110
|
describe('#submit()', () => {
|
|
@@ -131,6 +133,67 @@ describe('plugin-metrics', () => {
|
|
|
131
133
|
});
|
|
132
134
|
});
|
|
133
135
|
|
|
136
|
+
describe('#getClientMetricsPayload()', () => {
|
|
137
|
+
it('returns the expected payload', () => {
|
|
138
|
+
webex.credentials.supertoken = new Token(
|
|
139
|
+
{
|
|
140
|
+
access_token: 'a_b_orgid',
|
|
141
|
+
},
|
|
142
|
+
{parent: webex}
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
const testPayload = {
|
|
146
|
+
tags: {success: true},
|
|
147
|
+
fields: {perceivedDurationInMillis: 314},
|
|
148
|
+
context: {},
|
|
149
|
+
eventPayload: {value: 'splunk business metric payload'},
|
|
150
|
+
};
|
|
151
|
+
const date = clock.now;
|
|
152
|
+
|
|
153
|
+
const result = metrics.getClientMetricsPayload('test', testPayload);
|
|
154
|
+
|
|
155
|
+
assert.deepEqual(result, {
|
|
156
|
+
context: {
|
|
157
|
+
app: {
|
|
158
|
+
version: undefined,
|
|
159
|
+
},
|
|
160
|
+
locale: 'en-US',
|
|
161
|
+
os: {
|
|
162
|
+
name: 'other',
|
|
163
|
+
version: getOSVersion(),
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
eventPayload: {
|
|
167
|
+
value: 'splunk business metric payload',
|
|
168
|
+
},
|
|
169
|
+
fields: {
|
|
170
|
+
browser_version: '',
|
|
171
|
+
client_id: 'fake',
|
|
172
|
+
os_version: getOSVersion(),
|
|
173
|
+
perceivedDurationInMillis: 314,
|
|
174
|
+
platform: 'Web',
|
|
175
|
+
sdk_version: undefined,
|
|
176
|
+
spark_user_agent: 'webex-js-sdk appName/appVersion appPlatform',
|
|
177
|
+
},
|
|
178
|
+
metricName: 'test',
|
|
179
|
+
tags: {
|
|
180
|
+
browser: '',
|
|
181
|
+
domain: 'whatever',
|
|
182
|
+
os: 'other',
|
|
183
|
+
success: true,
|
|
184
|
+
},
|
|
185
|
+
timestamp: 0,
|
|
186
|
+
type: ['operational'],
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('throws when no event name is specified', () => {
|
|
191
|
+
assert.throws(() => {
|
|
192
|
+
metrics.getClientMetricsPayload();
|
|
193
|
+
}, 'Missing behavioral metric name. Please provide one');
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
134
197
|
describe('#submitClientMetrics()', () => {
|
|
135
198
|
describe('before login', () => {
|
|
136
199
|
it('posts pre-login metric', () => {
|
|
@@ -199,17 +262,15 @@ describe('plugin-metrics', () => {
|
|
|
199
262
|
assert.property(metric, 'eventPayload');
|
|
200
263
|
|
|
201
264
|
assert.property(metric.tags, 'browser');
|
|
202
|
-
assert.property(metric.tags, 'org_id');
|
|
203
265
|
assert.property(metric.tags, 'os');
|
|
204
266
|
assert.property(metric.tags, 'domain');
|
|
205
|
-
assert.property(metric.tags, 'client_id');
|
|
206
|
-
assert.property(metric.tags, 'user_id');
|
|
207
267
|
|
|
208
268
|
assert.property(metric.fields, 'browser_version');
|
|
209
269
|
assert.property(metric.fields, 'os_version');
|
|
210
270
|
assert.property(metric.fields, 'sdk_version');
|
|
211
271
|
assert.property(metric.fields, 'platform');
|
|
212
272
|
assert.property(metric.fields, 'spark_user_agent');
|
|
273
|
+
assert.property(metric.fields, 'client_id');
|
|
213
274
|
|
|
214
275
|
assert.property(metric.context, 'app');
|
|
215
276
|
assert.property(metric.context, 'locale');
|
|
@@ -269,98 +330,5 @@ describe('plugin-metrics', () => {
|
|
|
269
330
|
assert.match(params, {alias: true});
|
|
270
331
|
}));
|
|
271
332
|
});
|
|
272
|
-
|
|
273
|
-
describe('#submitCallDiagnosticEvents()', () => {
|
|
274
|
-
it('submits a call diagnostic event', () => {
|
|
275
|
-
const promise = metrics.submitCallDiagnosticEvents(mockCallDiagnosticEvent);
|
|
276
|
-
|
|
277
|
-
return promiseTick(50)
|
|
278
|
-
.then(() => clock.tick(config.metrics.batcherWait))
|
|
279
|
-
.then(() => promise)
|
|
280
|
-
.then(() => {
|
|
281
|
-
assert.calledOnce(webex.request);
|
|
282
|
-
const req = webex.request.args[0][0];
|
|
283
|
-
const metric = req.body.metrics[0];
|
|
284
|
-
|
|
285
|
-
assert.property(metric.eventPayload, 'origin');
|
|
286
|
-
assert.property(metric.eventPayload, 'originTime');
|
|
287
|
-
assert.property(metric.eventPayload.origin, 'buildType');
|
|
288
|
-
assert.property(metric.eventPayload.origin, 'networkType');
|
|
289
|
-
assert.property(metric.eventPayload.originTime, 'sent');
|
|
290
|
-
assert.equal(metric.eventPayload.origin.buildType, 'test');
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
it('submits a call diagnostic event with buildType set in the payload', () => {
|
|
295
|
-
const promise = metrics.submitCallDiagnosticEvents({
|
|
296
|
-
...mockCallDiagnosticEvent,
|
|
297
|
-
origin: {
|
|
298
|
-
buildType: 'prod',
|
|
299
|
-
},
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
return promiseTick(50)
|
|
303
|
-
.then(() => clock.tick(config.metrics.batcherWait))
|
|
304
|
-
.then(() => promise)
|
|
305
|
-
.then(() => {
|
|
306
|
-
assert.calledOnce(webex.request);
|
|
307
|
-
const req = webex.request.args[0][0];
|
|
308
|
-
const metric = req.body.metrics[0];
|
|
309
|
-
|
|
310
|
-
assert.property(metric.eventPayload, 'origin');
|
|
311
|
-
assert.property(metric.eventPayload, 'originTime');
|
|
312
|
-
assert.property(metric.eventPayload.origin, 'buildType');
|
|
313
|
-
assert.property(metric.eventPayload.origin, 'networkType');
|
|
314
|
-
assert.property(metric.eventPayload.originTime, 'sent');
|
|
315
|
-
assert.equal(metric.eventPayload.origin.buildType, 'prod');
|
|
316
|
-
});
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
xit('submits a call diagnostic event with a test domain', () => {
|
|
320
|
-
global.window.location.hostname = 'test.webex.com';
|
|
321
|
-
|
|
322
|
-
const promise = metrics.submitCallDiagnosticEvents(mockCallDiagnosticEvent);
|
|
323
|
-
|
|
324
|
-
return promiseTick(50)
|
|
325
|
-
.then(() => clock.tick(config.metrics.batcherWait))
|
|
326
|
-
.then(() => promise)
|
|
327
|
-
.then(() => {
|
|
328
|
-
assert.calledOnce(webex.request);
|
|
329
|
-
const req = webex.request.args[0][0];
|
|
330
|
-
const metric = req.body.metrics[0];
|
|
331
|
-
|
|
332
|
-
assert.property(metric.eventPayload, 'origin');
|
|
333
|
-
assert.property(metric.eventPayload, 'originTime');
|
|
334
|
-
assert.property(metric.eventPayload.origin, 'buildType');
|
|
335
|
-
assert.property(metric.eventPayload.origin, 'networkType');
|
|
336
|
-
assert.property(metric.eventPayload.originTime, 'sent');
|
|
337
|
-
assert.equal(metric.eventPayload.origin.buildType, 'test');
|
|
338
|
-
});
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
// Skip because it's current unable to overwrite NODE_ENV
|
|
342
|
-
// However doing `NODE_ENV=test npm run test ...` will get this test case to pass
|
|
343
|
-
xit('submits a call diagnostic event with a NODE_ENV=production', () => {
|
|
344
|
-
process.env.NODE_ENV = 'production';
|
|
345
|
-
|
|
346
|
-
const promise = metrics.submitCallDiagnosticEvents(mockCallDiagnosticEvent);
|
|
347
|
-
|
|
348
|
-
return promiseTick(50)
|
|
349
|
-
.then(() => clock.tick(config.metrics.batcherWait))
|
|
350
|
-
.then(() => promise)
|
|
351
|
-
.then(() => {
|
|
352
|
-
assert.calledOnce(webex.request);
|
|
353
|
-
const req = webex.request.args[0][0];
|
|
354
|
-
const metric = req.body.metrics[0];
|
|
355
|
-
|
|
356
|
-
assert.property(metric.eventPayload, 'origin');
|
|
357
|
-
assert.property(metric.eventPayload, 'originTime');
|
|
358
|
-
assert.property(metric.eventPayload.origin, 'buildType');
|
|
359
|
-
assert.property(metric.eventPayload.origin, 'networkType');
|
|
360
|
-
assert.property(metric.eventPayload.originTime, 'sent');
|
|
361
|
-
assert.equal(metric.eventPayload.origin.buildType, 'prod');
|
|
362
|
-
});
|
|
363
|
-
});
|
|
364
|
-
});
|
|
365
333
|
});
|
|
366
334
|
});
|