@webex/plugin-meetings 1.150.1 → 1.151.0
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/constants.js +3 -1
- package/dist/constants.js.map +1 -1
- package/dist/meeting/index.js +170 -4
- package/dist/meeting/index.js.map +1 -1
- package/dist/metrics/index.js +26 -1
- package/dist/metrics/index.js.map +1 -1
- package/dist/peer-connection-manager/index.js +1 -1
- package/dist/peer-connection-manager/index.js.map +1 -1
- package/package.json +5 -5
- package/src/constants.js +2 -0
- package/src/meeting/index.js +171 -10
- package/src/metrics/index.js +23 -2
- package/src/peer-connection-manager/index.js +7 -2
- package/test/integration/spec/journey.js +10 -7
- package/test/utils/testUtils.js +18 -1
package/src/meeting/index.js
CHANGED
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
MEETING_STATE_MACHINE,
|
|
52
52
|
MEETING_STATE,
|
|
53
53
|
MEETINGS,
|
|
54
|
+
METRICS_JOIN_TIMES_MAX_DURATION,
|
|
54
55
|
METRICS_OPERATIONAL_MEASURES,
|
|
55
56
|
MQA_STATS,
|
|
56
57
|
NETWORK_STATUS,
|
|
@@ -1065,10 +1066,45 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1065
1066
|
};
|
|
1066
1067
|
}
|
|
1067
1068
|
|
|
1069
|
+
const localSDPGenRemoteSDPRecv = this.getLocalSDPGenRemoteSDPRecvDelay();
|
|
1070
|
+
|
|
1071
|
+
if (localSDPGenRemoteSDPRecv) {
|
|
1072
|
+
options.joinTimes = {
|
|
1073
|
+
...options.joinTimes,
|
|
1074
|
+
localSDPGenRemoteSDPRecv
|
|
1075
|
+
};
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
const callInitiateJoinReq = this.getCallInitiateJoinReq();
|
|
1079
|
+
|
|
1080
|
+
if (callInitiateJoinReq) {
|
|
1081
|
+
options.joinTimes = {
|
|
1082
|
+
...options.joinTimes,
|
|
1083
|
+
callInitiateJoinReq
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
const joinReqResp = this.getJoinReqResp();
|
|
1088
|
+
|
|
1089
|
+
if (joinReqResp) {
|
|
1090
|
+
options.joinTimes = {
|
|
1091
|
+
...options.joinTimes,
|
|
1092
|
+
joinReqResp
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
const getTotalJmt = this.getTotalJmt();
|
|
1097
|
+
|
|
1098
|
+
if (getTotalJmt) {
|
|
1099
|
+
options.joinTimes = {
|
|
1100
|
+
...options.joinTimes,
|
|
1101
|
+
getTotalJmt
|
|
1102
|
+
};
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1068
1105
|
if (options.type === MQA_STATS.CA_TYPE) {
|
|
1069
1106
|
payload = Metrics.initMediaPayload(options.event, identifiers, options);
|
|
1070
1107
|
}
|
|
1071
|
-
|
|
1072
1108
|
else {
|
|
1073
1109
|
payload = Metrics.initPayload(options.event, identifiers, options);
|
|
1074
1110
|
}
|
|
@@ -3372,12 +3408,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3372
3408
|
}
|
|
3373
3409
|
}
|
|
3374
3410
|
|
|
3375
|
-
return MeetingUtil.joinMeetingOptions(this, options)
|
|
3376
|
-
|
|
3377
|
-
|
|
3411
|
+
return MeetingUtil.joinMeetingOptions(this, options)
|
|
3412
|
+
.then((join) => {
|
|
3413
|
+
this.meetingFiniteStateMachine.join();
|
|
3414
|
+
LoggerProxy.logger.log('Meeting:index#join --> Success');
|
|
3378
3415
|
|
|
3379
|
-
|
|
3380
|
-
|
|
3416
|
+
return join;
|
|
3417
|
+
})
|
|
3381
3418
|
.then((join) => {
|
|
3382
3419
|
joinSuccess(join);
|
|
3383
3420
|
this.deferJoin = undefined;
|
|
@@ -3851,7 +3888,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3851
3888
|
meetingId: this.id,
|
|
3852
3889
|
remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
|
|
3853
3890
|
enableRtx: this.config.enableRtx,
|
|
3854
|
-
enableExtmap: this.config.enableExtmap
|
|
3891
|
+
enableExtmap: this.config.enableExtmap,
|
|
3892
|
+
setStartLocalSDPGenRemoteSDPRecvDelay: this.setStartLocalSDPGenRemoteSDPRecvDelay.bind(this)
|
|
3855
3893
|
})
|
|
3856
3894
|
.then((peerConnection) => this.getDevices().then((devices) => {
|
|
3857
3895
|
MeetingUtil.handleDeviceLogging(devices);
|
|
@@ -5238,9 +5276,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5238
5276
|
}
|
|
5239
5277
|
|
|
5240
5278
|
/**
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5279
|
+
* @param {string} typeMedia 'audio' or 'video'
|
|
5280
|
+
* @returns {undefined}
|
|
5281
|
+
*/
|
|
5244
5282
|
setEndSendingMediaDelay(typeMedia) {
|
|
5245
5283
|
this[`endSendingMediaDelay${typeMedia}`] = performance.now();
|
|
5246
5284
|
}
|
|
@@ -5255,4 +5293,127 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5255
5293
|
|
|
5256
5294
|
return (start && end) ? end - start : undefined;
|
|
5257
5295
|
}
|
|
5296
|
+
|
|
5297
|
+
/**
|
|
5298
|
+
*
|
|
5299
|
+
* @returns {undefined}
|
|
5300
|
+
*/
|
|
5301
|
+
setStartLocalSDPGenRemoteSDPRecvDelay() {
|
|
5302
|
+
if (!this.startLocalSDPGenRemoteSDPRecvDelay) {
|
|
5303
|
+
this.startLocalSDPGenRemoteSDPRecvDelay = performance.now();
|
|
5304
|
+
this.endLocalSDPGenRemoteSDPRecvDelay = undefined;
|
|
5305
|
+
}
|
|
5306
|
+
}
|
|
5307
|
+
|
|
5308
|
+
/**
|
|
5309
|
+
*
|
|
5310
|
+
* @returns {undefined}
|
|
5311
|
+
*/
|
|
5312
|
+
setEndLocalSDPGenRemoteSDPRecvDelay() {
|
|
5313
|
+
if (!this.endLocalSDPGenRemoteSDPRecvDelay) {
|
|
5314
|
+
this.endLocalSDPGenRemoteSDPRecvDelay = performance.now();
|
|
5315
|
+
}
|
|
5316
|
+
}
|
|
5317
|
+
|
|
5318
|
+
/**
|
|
5319
|
+
*
|
|
5320
|
+
* @returns {string} duration between local SDP generation and remote SDP reception
|
|
5321
|
+
*/
|
|
5322
|
+
getLocalSDPGenRemoteSDPRecvDelay() {
|
|
5323
|
+
const start = this.startLocalSDPGenRemoteSDPRecvDelay;
|
|
5324
|
+
const end = this.endLocalSDPGenRemoteSDPRecvDelay;
|
|
5325
|
+
|
|
5326
|
+
if (start && end) {
|
|
5327
|
+
const calculatedDelay = end - start;
|
|
5328
|
+
|
|
5329
|
+
return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ?
|
|
5330
|
+
undefined :
|
|
5331
|
+
calculatedDelay;
|
|
5332
|
+
}
|
|
5333
|
+
|
|
5334
|
+
return undefined;
|
|
5335
|
+
}
|
|
5336
|
+
|
|
5337
|
+
/**
|
|
5338
|
+
*
|
|
5339
|
+
* @returns {undefined}
|
|
5340
|
+
*/
|
|
5341
|
+
setStartCallInitiateJoinReq() {
|
|
5342
|
+
this.startCallInitiateJoinReq = performance.now();
|
|
5343
|
+
this.endCallInitiateJoinReq = undefined;
|
|
5344
|
+
}
|
|
5345
|
+
|
|
5346
|
+
/**
|
|
5347
|
+
*
|
|
5348
|
+
* @returns {undefined}
|
|
5349
|
+
*/
|
|
5350
|
+
setEndCallInitiateJoinReq() {
|
|
5351
|
+
this.endCallInitiateJoinReq = performance.now();
|
|
5352
|
+
}
|
|
5353
|
+
|
|
5354
|
+
/**
|
|
5355
|
+
*
|
|
5356
|
+
* @returns {string} duration between call initiate and sending join request to locus
|
|
5357
|
+
*/
|
|
5358
|
+
getCallInitiateJoinReq() {
|
|
5359
|
+
const start = this.startCallInitiateJoinReq;
|
|
5360
|
+
const end = this.endCallInitiateJoinReq;
|
|
5361
|
+
|
|
5362
|
+
if (start && end) {
|
|
5363
|
+
const calculatedDelay = end - start;
|
|
5364
|
+
|
|
5365
|
+
return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ?
|
|
5366
|
+
undefined :
|
|
5367
|
+
calculatedDelay;
|
|
5368
|
+
}
|
|
5369
|
+
|
|
5370
|
+
return undefined;
|
|
5371
|
+
}
|
|
5372
|
+
|
|
5373
|
+
/**
|
|
5374
|
+
*
|
|
5375
|
+
* @returns {undefined}
|
|
5376
|
+
*/
|
|
5377
|
+
setStartJoinReqResp() {
|
|
5378
|
+
this.startJoinReqResp = performance.now();
|
|
5379
|
+
this.endJoinReqResp = undefined;
|
|
5380
|
+
}
|
|
5381
|
+
|
|
5382
|
+
/**
|
|
5383
|
+
*
|
|
5384
|
+
* @returns {undefined}
|
|
5385
|
+
*/
|
|
5386
|
+
setEndJoinReqResp() {
|
|
5387
|
+
this.endJoinReqResp = performance.now();
|
|
5388
|
+
}
|
|
5389
|
+
|
|
5390
|
+
/**
|
|
5391
|
+
*
|
|
5392
|
+
* @returns {string} duration between sending locus join request and receiving join response
|
|
5393
|
+
*/
|
|
5394
|
+
getJoinReqResp() {
|
|
5395
|
+
const start = this.startJoinReqResp;
|
|
5396
|
+
const end = this.endJoinReqResp;
|
|
5397
|
+
|
|
5398
|
+
if (start && end) {
|
|
5399
|
+
const calculatedDelay = end - start;
|
|
5400
|
+
|
|
5401
|
+
return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ?
|
|
5402
|
+
undefined :
|
|
5403
|
+
calculatedDelay;
|
|
5404
|
+
}
|
|
5405
|
+
|
|
5406
|
+
return undefined;
|
|
5407
|
+
}
|
|
5408
|
+
|
|
5409
|
+
/**
|
|
5410
|
+
*
|
|
5411
|
+
* @returns {string} duration between call initiate and successful locus join (even if it is in lobby)
|
|
5412
|
+
*/
|
|
5413
|
+
getTotalJmt() {
|
|
5414
|
+
const start = this.startCallInitiateJoinReq;
|
|
5415
|
+
const end = this.endJoinReqResp;
|
|
5416
|
+
|
|
5417
|
+
return (start && end) ? end - start : undefined;
|
|
5418
|
+
}
|
|
5258
5419
|
}
|
package/src/metrics/index.js
CHANGED
|
@@ -48,7 +48,15 @@ const getLocalNetworkPrefix = (localIp) => {
|
|
|
48
48
|
|
|
49
49
|
const triggerTimers = ({event, meeting, data}) => {
|
|
50
50
|
switch (event) {
|
|
51
|
+
case eventType.CALL_INITIATED:
|
|
52
|
+
meeting.setStartCallInitiateJoinReq();
|
|
53
|
+
break;
|
|
54
|
+
case eventType.LOCUS_JOIN_REQUEST:
|
|
55
|
+
meeting.setEndCallInitiateJoinReq();
|
|
56
|
+
meeting.setStartJoinReqResp();
|
|
57
|
+
break;
|
|
51
58
|
case eventType.LOCUS_JOIN_RESPONSE:
|
|
59
|
+
meeting.setEndJoinReqResp();
|
|
52
60
|
meeting.setStartSetupDelay(mediaType.AUDIO);
|
|
53
61
|
meeting.setStartSetupDelay(mediaType.VIDEO);
|
|
54
62
|
meeting.setStartSendingMediaDelay(mediaType.AUDIO);
|
|
@@ -60,6 +68,12 @@ const triggerTimers = ({event, meeting, data}) => {
|
|
|
60
68
|
case eventType.SENDING_MEDIA_START:
|
|
61
69
|
meeting.setEndSendingMediaDelay(data.mediaType);
|
|
62
70
|
break;
|
|
71
|
+
case eventType.LOCAL_SDP_GENERATED:
|
|
72
|
+
meeting.setStartLocalSDPGenRemoteSDPRecvDelay();
|
|
73
|
+
break;
|
|
74
|
+
case eventType.REMOTE_SDP_RECEIVED:
|
|
75
|
+
meeting.setEndLocalSDPGenRemoteSDPRecvDelay();
|
|
76
|
+
break;
|
|
63
77
|
default:
|
|
64
78
|
break;
|
|
65
79
|
}
|
|
@@ -144,6 +158,7 @@ class Metrics {
|
|
|
144
158
|
|
|
145
159
|
if (!meeting && meetingId) {
|
|
146
160
|
meeting = this.meetingCollection.get(meetingId);
|
|
161
|
+
options.meeting = meeting;
|
|
147
162
|
}
|
|
148
163
|
|
|
149
164
|
if (meeting) {
|
|
@@ -228,6 +243,9 @@ class Metrics {
|
|
|
228
243
|
if (options.recoveredBy) {
|
|
229
244
|
payload.event.recoveredBy = options.recoveredBy;
|
|
230
245
|
}
|
|
246
|
+
if (options.joinTimes) {
|
|
247
|
+
payload.event.joinTimes = options.joinTimes;
|
|
248
|
+
}
|
|
231
249
|
}
|
|
232
250
|
|
|
233
251
|
return payload;
|
|
@@ -259,7 +277,7 @@ class Metrics {
|
|
|
259
277
|
* @memberof Metrics
|
|
260
278
|
*/
|
|
261
279
|
initMediaPayload(eventType, identifiers, options = {}) {
|
|
262
|
-
const {audioSetupDelay, videoSetupDelay} = options;
|
|
280
|
+
const {audioSetupDelay, videoSetupDelay, joinTimes} = options;
|
|
263
281
|
|
|
264
282
|
const payload = {
|
|
265
283
|
eventId: uuid.v4(),
|
|
@@ -290,7 +308,10 @@ class Metrics {
|
|
|
290
308
|
canProceed: true,
|
|
291
309
|
identifiers,
|
|
292
310
|
intervals: [options.intervalData],
|
|
293
|
-
|
|
311
|
+
joinTimes,
|
|
312
|
+
eventData: {
|
|
313
|
+
webClientDomain: window.location.hostname
|
|
314
|
+
},
|
|
294
315
|
sourceMetadata: {
|
|
295
316
|
applicationSoftwareType: CLIENT_NAME,
|
|
296
317
|
applicationSoftwareVersion: this.webex.version,
|
|
@@ -288,7 +288,12 @@ pc.addStream = (peerConnection, stream) => {
|
|
|
288
288
|
* @param {String} meetingId
|
|
289
289
|
* @returns {undefined}
|
|
290
290
|
*/
|
|
291
|
-
pc.setRemoteSessionDetails = (
|
|
291
|
+
pc.setRemoteSessionDetails = (
|
|
292
|
+
peerConnection,
|
|
293
|
+
typeStr,
|
|
294
|
+
remoteSdp,
|
|
295
|
+
meetingId,
|
|
296
|
+
) => {
|
|
292
297
|
LoggerProxy.logger.log(`PeerConnectionManager:index#setRemoteSessionDetails --> Setting the remote description type: ${typeStr}State: ${peerConnection.signalingState}`);
|
|
293
298
|
const sdp = remoteSdp;
|
|
294
299
|
|
|
@@ -314,7 +319,7 @@ pc.setRemoteSessionDetails = (peerConnection, typeStr, remoteSdp, meetingId) =>
|
|
|
314
319
|
})
|
|
315
320
|
)
|
|
316
321
|
.then(() => {
|
|
317
|
-
if (
|
|
322
|
+
if (peerConnection.signalingState === SDP.STABLE) {
|
|
318
323
|
Metrics.postEvent({
|
|
319
324
|
event: eventType.REMOTE_SDP_RECEIVED,
|
|
320
325
|
meetingId
|
|
@@ -519,7 +519,10 @@ skipInNode(describe)('plugin-meetings', () => {
|
|
|
519
519
|
.then((response) => {
|
|
520
520
|
assert.equal(response[0].result.memberId, alice.meeting.selfId);
|
|
521
521
|
}),
|
|
522
|
-
testUtils.waitForEvents([{scope: bob.meeting.members, event: 'members:update'}])
|
|
522
|
+
testUtils.waitForEvents([{scope: bob.meeting.members, event: 'members:update'}])
|
|
523
|
+
.then((response) => {
|
|
524
|
+
console.log('SCREEN SHARE RESPONSE ', JSON.stringify(response, testUtils.getCircularReplacer()));
|
|
525
|
+
}),
|
|
523
526
|
testUtils.waitForEvents([{scope: alice.meeting, event: 'media:ready'}])
|
|
524
527
|
.then((response) => {
|
|
525
528
|
console.log('MEDIA:READY event ', response[0].result);
|
|
@@ -549,7 +552,7 @@ skipInNode(describe)('plugin-meetings', () => {
|
|
|
549
552
|
}),
|
|
550
553
|
testUtils.waitForEvents([{scope: alice.meeting.members, event: 'members:update'}])
|
|
551
554
|
.then((response) => {
|
|
552
|
-
console.log('SCREEN SHARE RESPONSE ', JSON.stringify(response));
|
|
555
|
+
console.log('SCREEN SHARE RESPONSE ', JSON.stringify(response, testUtils.getCircularReplacer()));
|
|
553
556
|
}),
|
|
554
557
|
testUtils.waitForEvents([{scope: bob.meeting, event: 'media:ready'}])
|
|
555
558
|
.then((response) => {
|
|
@@ -601,7 +604,7 @@ skipInNode(describe)('plugin-meetings', () => {
|
|
|
601
604
|
}),
|
|
602
605
|
testUtils.waitForEvents([{scope: bob.meeting.members, event: 'members:update'}])
|
|
603
606
|
.then((response) => {
|
|
604
|
-
console.log('WHITEBOARD SHARE RESPONSE ', JSON.stringify(response));
|
|
607
|
+
console.log('WHITEBOARD SHARE RESPONSE ', JSON.stringify(response, testUtils.getCircularReplacer()));
|
|
605
608
|
})
|
|
606
609
|
])
|
|
607
610
|
.then(() => {
|
|
@@ -624,7 +627,7 @@ skipInNode(describe)('plugin-meetings', () => {
|
|
|
624
627
|
}),
|
|
625
628
|
testUtils.waitForEvents([{scope: alice.meeting.members, event: 'members:update'}])
|
|
626
629
|
.then((response) => {
|
|
627
|
-
console.log('WHITEBOARD SHARE RESPONSE ', JSON.stringify(response));
|
|
630
|
+
console.log('WHITEBOARD SHARE RESPONSE ', JSON.stringify(response, testUtils.getCircularReplacer()));
|
|
628
631
|
})
|
|
629
632
|
])
|
|
630
633
|
.then(() => {
|
|
@@ -660,7 +663,7 @@ skipInNode(describe)('plugin-meetings', () => {
|
|
|
660
663
|
}),
|
|
661
664
|
testUtils.waitForEvents([{scope: bob.meeting.members, event: 'members:update'}])
|
|
662
665
|
.then((response) => {
|
|
663
|
-
console.log('WHITEBOARD SHARE RESPONSE ', JSON.stringify(response));
|
|
666
|
+
console.log('WHITEBOARD SHARE RESPONSE ', JSON.stringify(response, testUtils.getCircularReplacer()));
|
|
664
667
|
})
|
|
665
668
|
])
|
|
666
669
|
.then(() => {
|
|
@@ -679,7 +682,7 @@ skipInNode(describe)('plugin-meetings', () => {
|
|
|
679
682
|
}),
|
|
680
683
|
testUtils.waitForEvents([{scope: alice.meeting.members, event: 'members:update'}])
|
|
681
684
|
.then((response) => {
|
|
682
|
-
console.log('SCREEN SHARE RESPONSE ', JSON.stringify(response));
|
|
685
|
+
console.log('SCREEN SHARE RESPONSE ', JSON.stringify(response, testUtils.getCircularReplacer()));
|
|
683
686
|
}),
|
|
684
687
|
testUtils.waitForEvents([{scope: bob.meeting, event: 'media:ready'}])
|
|
685
688
|
.then((response) => {
|
|
@@ -715,7 +718,7 @@ skipInNode(describe)('plugin-meetings', () => {
|
|
|
715
718
|
}),
|
|
716
719
|
testUtils.waitForEvents([{scope: alice.meeting.members, event: 'members:update'}])
|
|
717
720
|
.then((response) => {
|
|
718
|
-
console.log('WHITEBOARD SHARE RESPONSE ', JSON.stringify(response));
|
|
721
|
+
console.log('WHITEBOARD SHARE RESPONSE ', JSON.stringify(response, testUtils.getCircularReplacer()));
|
|
719
722
|
})
|
|
720
723
|
])
|
|
721
724
|
.then(() => {
|
package/test/utils/testUtils.js
CHANGED
|
@@ -236,6 +236,22 @@ const waitUntil = (waitTime) => new Promise((resolve) => {
|
|
|
236
236
|
|
|
237
237
|
const flushPromises = () => new Promise(setImmediate);
|
|
238
238
|
|
|
239
|
+
const getCircularReplacer = () => {
|
|
240
|
+
const seen = new WeakSet();
|
|
241
|
+
|
|
242
|
+
return (_, value) => {
|
|
243
|
+
if (typeof value === 'object' && value !== null) {
|
|
244
|
+
if (seen.has(value)) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
seen.add(value);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// eslint-disable-next-line consistent-return
|
|
251
|
+
return value;
|
|
252
|
+
};
|
|
253
|
+
};
|
|
254
|
+
|
|
239
255
|
export default {
|
|
240
256
|
waitForSpy,
|
|
241
257
|
waitForStateChange,
|
|
@@ -246,6 +262,7 @@ export default {
|
|
|
246
262
|
addMedia,
|
|
247
263
|
waitUntil,
|
|
248
264
|
delayedTest,
|
|
249
|
-
flushPromises
|
|
265
|
+
flushPromises,
|
|
266
|
+
getCircularReplacer
|
|
250
267
|
};
|
|
251
268
|
|