@webex/plugin-meetings 3.0.0-beta.280 → 3.0.0-beta.281
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/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/media/index.js +4 -1
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/index.js +473 -429
- package/dist/meeting/index.js.map +1 -1
- package/dist/rtcMetrics/index.js +5 -5
- package/dist/rtcMetrics/index.js.map +1 -1
- package/dist/types/meeting/index.d.ts +7 -0
- package/dist/types/rtcMetrics/index.d.ts +1 -1
- package/package.json +20 -20
- package/src/media/index.ts +3 -1
- package/src/meeting/index.ts +22 -0
- package/src/rtcMetrics/index.ts +4 -4
- package/test/unit/spec/meeting/index.js +6 -0
- package/test/unit/spec/rtcMetrics/index.ts +7 -2
package/dist/rtcMetrics/index.js
CHANGED
|
@@ -33,12 +33,12 @@ var RtcMetrics = /*#__PURE__*/function () {
|
|
|
33
33
|
(0, _defineProperty2.default)(this, "meetingId", void 0);
|
|
34
34
|
(0, _defineProperty2.default)(this, "correlationId", void 0);
|
|
35
35
|
// `window` is used to prevent typescript from returning a NodeJS.Timer.
|
|
36
|
-
this.intervalId = window.setInterval(this.
|
|
36
|
+
this.intervalId = window.setInterval(this.sendMetricsInQueue.bind(this), 30 * 1000);
|
|
37
37
|
this.meetingId = meetingId;
|
|
38
38
|
this.webex = webex;
|
|
39
39
|
this.correlationId = correlationId;
|
|
40
40
|
// Send the first set of metrics at 5 seconds in the case of a user leaving the call shortly after joining.
|
|
41
|
-
setTimeout(this.
|
|
41
|
+
setTimeout(this.sendMetricsInQueue.bind(this), 5 * 1000);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
/**
|
|
@@ -47,8 +47,8 @@ var RtcMetrics = /*#__PURE__*/function () {
|
|
|
47
47
|
* @returns {void}
|
|
48
48
|
*/
|
|
49
49
|
(0, _createClass2.default)(RtcMetrics, [{
|
|
50
|
-
key: "
|
|
51
|
-
value: function
|
|
50
|
+
key: "sendMetricsInQueue",
|
|
51
|
+
value: function sendMetricsInQueue() {
|
|
52
52
|
if (this.metricsQueue.length) {
|
|
53
53
|
this.sendMetrics();
|
|
54
54
|
this.metricsQueue = [];
|
|
@@ -78,7 +78,7 @@ var RtcMetrics = /*#__PURE__*/function () {
|
|
|
78
78
|
}, {
|
|
79
79
|
key: "closeMetrics",
|
|
80
80
|
value: function closeMetrics() {
|
|
81
|
-
this.
|
|
81
|
+
this.sendMetricsInQueue();
|
|
82
82
|
clearInterval(this.intervalId);
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["RtcMetrics","webex","meetingId","correlationId","intervalId","window","setInterval","
|
|
1
|
+
{"version":3,"names":["RtcMetrics","webex","meetingId","correlationId","intervalId","window","setInterval","sendMetricsInQueue","bind","setTimeout","metricsQueue","length","sendMetrics","data","payload","push","clearInterval","request","method","service","resource","headers","type","appId","RTC_METRICS","APP_ID","body","metrics","version","userId","internal","device"],"sources":["index.ts"],"sourcesContent":["import RTC_METRICS from './constants';\n\n/**\n * Rtc Metrics\n */\nexport default class RtcMetrics {\n /**\n * Array of MetricData items to be sent to the metrics service.\n */\n metricsQueue = [];\n\n intervalId: number;\n\n webex: any;\n\n meetingId: string;\n\n correlationId: string;\n\n /**\n * Initialize the interval.\n *\n * @param {object} webex - The main `webex` object.\n * @param {string} meetingId - The meeting id.\n * @param {string} correlationId - The correlation id.\n */\n constructor(webex, meetingId, correlationId) {\n // `window` is used to prevent typescript from returning a NodeJS.Timer.\n this.intervalId = window.setInterval(this.sendMetricsInQueue.bind(this), 30 * 1000);\n this.meetingId = meetingId;\n this.webex = webex;\n this.correlationId = correlationId;\n // Send the first set of metrics at 5 seconds in the case of a user leaving the call shortly after joining.\n setTimeout(this.sendMetricsInQueue.bind(this), 5 * 1000);\n }\n\n /**\n * Check to see if the metrics queue has any items.\n *\n * @returns {void}\n */\n public sendMetricsInQueue() {\n if (this.metricsQueue.length) {\n this.sendMetrics();\n this.metricsQueue = [];\n }\n }\n\n /**\n * Add metrics items to the metrics queue.\n *\n * @param {object} data - An object with a payload array of metrics items.\n *\n * @returns {void}\n */\n addMetrics(data) {\n if (data.payload.length) {\n this.metricsQueue.push(data);\n }\n }\n\n /**\n * Clear the metrics interval.\n *\n * @returns {void}\n */\n closeMetrics() {\n this.sendMetricsInQueue();\n clearInterval(this.intervalId);\n }\n\n /**\n * Send metrics to the metrics service.\n *\n * @returns {void}\n */\n private sendMetrics() {\n this.webex.request({\n method: 'POST',\n service: 'unifiedTelemetry',\n resource: 'metric/v2',\n headers: {\n type: 'webrtcMedia',\n appId: RTC_METRICS.APP_ID,\n },\n body: {\n metrics: [\n {\n type: 'webrtc',\n version: '1.0.1',\n userId: this.webex.internal.device.userId,\n meetingId: this.meetingId,\n correlationId: this.correlationId,\n data: this.metricsQueue,\n },\n ],\n },\n });\n }\n}\n"],"mappings":";;;;;;;;;;;AAAA;AAEA;AACA;AACA;AAFA,IAGqBA,UAAU;EAC7B;AACF;AACA;;EAWE;AACF;AACA;AACA;AACA;AACA;AACA;EACE,oBAAYC,KAAK,EAAEC,SAAS,EAAEC,aAAa,EAAE;IAAA;IAAA,oDAjB9B,EAAE;IAAA;IAAA;IAAA;IAAA;IAkBf;IACA,IAAI,CAACC,UAAU,GAAGC,MAAM,CAACC,WAAW,CAAC,IAAI,CAACC,kBAAkB,CAACC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC;IACnF,IAAI,CAACN,SAAS,GAAGA,SAAS;IAC1B,IAAI,CAACD,KAAK,GAAGA,KAAK;IAClB,IAAI,CAACE,aAAa,GAAGA,aAAa;IAClC;IACAM,UAAU,CAAC,IAAI,CAACF,kBAAkB,CAACC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;EAC1D;;EAEA;AACF;AACA;AACA;AACA;EAJE;IAAA;IAAA,OAKA,8BAA4B;MAC1B,IAAI,IAAI,CAACE,YAAY,CAACC,MAAM,EAAE;QAC5B,IAAI,CAACC,WAAW,EAAE;QAClB,IAAI,CAACF,YAAY,GAAG,EAAE;MACxB;IACF;;IAEA;AACF;AACA;AACA;AACA;AACA;AACA;EANE;IAAA;IAAA,OAOA,oBAAWG,IAAI,EAAE;MACf,IAAIA,IAAI,CAACC,OAAO,CAACH,MAAM,EAAE;QACvB,IAAI,CAACD,YAAY,CAACK,IAAI,CAACF,IAAI,CAAC;MAC9B;IACF;;IAEA;AACF;AACA;AACA;AACA;EAJE;IAAA;IAAA,OAKA,wBAAe;MACb,IAAI,CAACN,kBAAkB,EAAE;MACzBS,aAAa,CAAC,IAAI,CAACZ,UAAU,CAAC;IAChC;;IAEA;AACF;AACA;AACA;AACA;EAJE;IAAA;IAAA,OAKA,uBAAsB;MACpB,IAAI,CAACH,KAAK,CAACgB,OAAO,CAAC;QACjBC,MAAM,EAAE,MAAM;QACdC,OAAO,EAAE,kBAAkB;QAC3BC,QAAQ,EAAE,WAAW;QACrBC,OAAO,EAAE;UACPC,IAAI,EAAE,aAAa;UACnBC,KAAK,EAAEC,kBAAW,CAACC;QACrB,CAAC;QACDC,IAAI,EAAE;UACJC,OAAO,EAAE,CACP;YACEL,IAAI,EAAE,QAAQ;YACdM,OAAO,EAAE,OAAO;YAChBC,MAAM,EAAE,IAAI,CAAC5B,KAAK,CAAC6B,QAAQ,CAACC,MAAM,CAACF,MAAM;YACzC3B,SAAS,EAAE,IAAI,CAACA,SAAS;YACzBC,aAAa,EAAE,IAAI,CAACA,aAAa;YACjCU,IAAI,EAAE,IAAI,CAACH;UACb,CAAC;QAEL;MACF,CAAC,CAAC;IACJ;EAAC;EAAA;AAAA;AAAA"}
|
|
@@ -1144,6 +1144,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1144
1144
|
* @returns {Boolean}
|
|
1145
1145
|
*/
|
|
1146
1146
|
canUpdateMedia(): boolean;
|
|
1147
|
+
/**
|
|
1148
|
+
* media failed, so collect a stats report from webrtc using the wcme connection to grab the rtc stats report
|
|
1149
|
+
* send a webrtc telemetry dump to the configured server using the internal media core check metrics configured callback
|
|
1150
|
+
* @param {String} callFrom - the function calling this function, optional.
|
|
1151
|
+
* @returns {Promise<void>}
|
|
1152
|
+
*/
|
|
1153
|
+
private forceSendStatsReport;
|
|
1147
1154
|
/**
|
|
1148
1155
|
* Enqueues a media update operation.
|
|
1149
1156
|
* @param {String} mediaUpdateType one of MEDIA_UPDATE_TYPE values
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/plugin-meetings",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.281",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
|
|
6
6
|
"contributors": [
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"build": "yarn run -T tsc --declaration true --declarationDir ./dist/types"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@webex/plugin-meetings": "3.0.0-beta.
|
|
36
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
37
|
-
"@webex/test-helper-mocha": "3.0.0-beta.
|
|
38
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
39
|
-
"@webex/test-helper-retry": "3.0.0-beta.
|
|
40
|
-
"@webex/test-helper-test-users": "3.0.0-beta.
|
|
35
|
+
"@webex/plugin-meetings": "3.0.0-beta.281",
|
|
36
|
+
"@webex/test-helper-chai": "3.0.0-beta.281",
|
|
37
|
+
"@webex/test-helper-mocha": "3.0.0-beta.281",
|
|
38
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.281",
|
|
39
|
+
"@webex/test-helper-retry": "3.0.0-beta.281",
|
|
40
|
+
"@webex/test-helper-test-users": "3.0.0-beta.281",
|
|
41
41
|
"chai": "^4.3.4",
|
|
42
42
|
"chai-as-promised": "^7.1.1",
|
|
43
43
|
"jsdom-global": "3.0.2",
|
|
@@ -46,19 +46,19 @@
|
|
|
46
46
|
"typescript": "^4.7.4"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@webex/common": "3.0.0-beta.
|
|
50
|
-
"@webex/internal-media-core": "2.0
|
|
51
|
-
"@webex/internal-plugin-conversation": "3.0.0-beta.
|
|
52
|
-
"@webex/internal-plugin-device": "3.0.0-beta.
|
|
53
|
-
"@webex/internal-plugin-llm": "3.0.0-beta.
|
|
54
|
-
"@webex/internal-plugin-mercury": "3.0.0-beta.
|
|
55
|
-
"@webex/internal-plugin-metrics": "3.0.0-beta.
|
|
56
|
-
"@webex/internal-plugin-support": "3.0.0-beta.
|
|
57
|
-
"@webex/internal-plugin-user": "3.0.0-beta.
|
|
58
|
-
"@webex/media-helpers": "3.0.0-beta.
|
|
59
|
-
"@webex/plugin-people": "3.0.0-beta.
|
|
60
|
-
"@webex/plugin-rooms": "3.0.0-beta.
|
|
61
|
-
"@webex/webex-core": "3.0.0-beta.
|
|
49
|
+
"@webex/common": "3.0.0-beta.281",
|
|
50
|
+
"@webex/internal-media-core": "2.1.0",
|
|
51
|
+
"@webex/internal-plugin-conversation": "3.0.0-beta.281",
|
|
52
|
+
"@webex/internal-plugin-device": "3.0.0-beta.281",
|
|
53
|
+
"@webex/internal-plugin-llm": "3.0.0-beta.281",
|
|
54
|
+
"@webex/internal-plugin-mercury": "3.0.0-beta.281",
|
|
55
|
+
"@webex/internal-plugin-metrics": "3.0.0-beta.281",
|
|
56
|
+
"@webex/internal-plugin-support": "3.0.0-beta.281",
|
|
57
|
+
"@webex/internal-plugin-user": "3.0.0-beta.281",
|
|
58
|
+
"@webex/media-helpers": "3.0.0-beta.281",
|
|
59
|
+
"@webex/plugin-people": "3.0.0-beta.281",
|
|
60
|
+
"@webex/plugin-rooms": "3.0.0-beta.281",
|
|
61
|
+
"@webex/webex-core": "3.0.0-beta.281",
|
|
62
62
|
"ampersand-collection": "^2.0.2",
|
|
63
63
|
"bowser": "^2.11.0",
|
|
64
64
|
"btoa": "^1.2.1",
|
package/src/media/index.ts
CHANGED
|
@@ -182,8 +182,10 @@ Media.createMediaConnection = (
|
|
|
182
182
|
return new MultistreamRoapMediaConnection(
|
|
183
183
|
config,
|
|
184
184
|
meetingId,
|
|
185
|
+
/* the rtc metrics objects callbacks */
|
|
185
186
|
(data) => rtcMetrics.addMetrics(data),
|
|
186
|
-
() => rtcMetrics.closeMetrics()
|
|
187
|
+
() => rtcMetrics.closeMetrics(),
|
|
188
|
+
() => rtcMetrics.sendMetricsInQueue()
|
|
187
189
|
);
|
|
188
190
|
}
|
|
189
191
|
|
package/src/meeting/index.ts
CHANGED
|
@@ -5944,6 +5944,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5944
5944
|
|
|
5945
5945
|
this.statsAnalyzer = null;
|
|
5946
5946
|
|
|
5947
|
+
// when media fails, we want to upload a webrtc dump to see whats going on
|
|
5948
|
+
// this function is async, but returns once the stats have been gathered
|
|
5949
|
+
await this.forceSendStatsReport({callFrom: 'addMedia'});
|
|
5950
|
+
|
|
5947
5951
|
if (this.mediaProperties.webrtcMediaConnection) {
|
|
5948
5952
|
this.closePeerConnections();
|
|
5949
5953
|
this.unsetPeerConnections();
|
|
@@ -5979,6 +5983,24 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5979
5983
|
return !this.isRoapInProgress;
|
|
5980
5984
|
}
|
|
5981
5985
|
|
|
5986
|
+
/**
|
|
5987
|
+
* media failed, so collect a stats report from webrtc using the wcme connection to grab the rtc stats report
|
|
5988
|
+
* send a webrtc telemetry dump to the configured server using the internal media core check metrics configured callback
|
|
5989
|
+
* @param {String} callFrom - the function calling this function, optional.
|
|
5990
|
+
* @returns {Promise<void>}
|
|
5991
|
+
*/
|
|
5992
|
+
private forceSendStatsReport = async ({callFrom}: {callFrom?: string}) => {
|
|
5993
|
+
const LOG_HEADER = `Meeting:index#forceSendStatsReport --> called from ${callFrom} : `;
|
|
5994
|
+
try {
|
|
5995
|
+
await this.mediaProperties?.webrtcMediaConnection?.forceRtcMetricsSend();
|
|
5996
|
+
LoggerProxy.logger.info(
|
|
5997
|
+
`${LOG_HEADER} successfully uploaded available webrtc telemetry statistics`
|
|
5998
|
+
);
|
|
5999
|
+
} catch (e) {
|
|
6000
|
+
LoggerProxy.logger.error(`${LOG_HEADER} failed to upload webrtc telemetry statistics: `, e);
|
|
6001
|
+
}
|
|
6002
|
+
};
|
|
6003
|
+
|
|
5982
6004
|
/**
|
|
5983
6005
|
* Enqueues a media update operation.
|
|
5984
6006
|
* @param {String} mediaUpdateType one of MEDIA_UPDATE_TYPE values
|
package/src/rtcMetrics/index.ts
CHANGED
|
@@ -26,12 +26,12 @@ export default class RtcMetrics {
|
|
|
26
26
|
*/
|
|
27
27
|
constructor(webex, meetingId, correlationId) {
|
|
28
28
|
// `window` is used to prevent typescript from returning a NodeJS.Timer.
|
|
29
|
-
this.intervalId = window.setInterval(this.
|
|
29
|
+
this.intervalId = window.setInterval(this.sendMetricsInQueue.bind(this), 30 * 1000);
|
|
30
30
|
this.meetingId = meetingId;
|
|
31
31
|
this.webex = webex;
|
|
32
32
|
this.correlationId = correlationId;
|
|
33
33
|
// Send the first set of metrics at 5 seconds in the case of a user leaving the call shortly after joining.
|
|
34
|
-
setTimeout(this.
|
|
34
|
+
setTimeout(this.sendMetricsInQueue.bind(this), 5 * 1000);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
/**
|
|
@@ -39,7 +39,7 @@ export default class RtcMetrics {
|
|
|
39
39
|
*
|
|
40
40
|
* @returns {void}
|
|
41
41
|
*/
|
|
42
|
-
|
|
42
|
+
public sendMetricsInQueue() {
|
|
43
43
|
if (this.metricsQueue.length) {
|
|
44
44
|
this.sendMetrics();
|
|
45
45
|
this.metricsQueue = [];
|
|
@@ -65,7 +65,7 @@ export default class RtcMetrics {
|
|
|
65
65
|
* @returns {void}
|
|
66
66
|
*/
|
|
67
67
|
closeMetrics() {
|
|
68
|
-
this.
|
|
68
|
+
this.sendMetricsInQueue();
|
|
69
69
|
clearInterval(this.intervalId);
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -1186,6 +1186,7 @@ describe('plugin-meetings', () => {
|
|
|
1186
1186
|
|
|
1187
1187
|
it('should send metrics and reset the statsAnalyzer to null if addMedia throws an error', async () => {
|
|
1188
1188
|
meeting.meetingState = 'ACTIVE';
|
|
1189
|
+
|
|
1189
1190
|
meeting.webex.meetings.reachability = {
|
|
1190
1191
|
getReachabilityMetrics: sinon.stub().resolves({
|
|
1191
1192
|
someReachabilityMetric1: 'some value1',
|
|
@@ -1193,15 +1194,20 @@ describe('plugin-meetings', () => {
|
|
|
1193
1194
|
}),
|
|
1194
1195
|
};
|
|
1195
1196
|
|
|
1197
|
+
const forceRtcMetricsSend = sinon.stub().resolves();
|
|
1198
|
+
|
|
1196
1199
|
// setup the mock to return an incomplete object - this will cause addMedia to fail
|
|
1197
1200
|
// because some methods (like on() or initiateOffer()) are missing
|
|
1198
1201
|
Media.createMediaConnection = sinon.stub().returns({
|
|
1199
1202
|
close: sinon.stub(),
|
|
1203
|
+
forceRtcMetricsSend,
|
|
1200
1204
|
});
|
|
1201
1205
|
// set a statsAnalyzer on the meeting so that we can check that it gets reset to null
|
|
1202
1206
|
meeting.statsAnalyzer = {stopAnalyzer: sinon.stub().resolves()};
|
|
1203
1207
|
const error = await assert.isRejected(meeting.addMedia());
|
|
1204
1208
|
|
|
1209
|
+
assert.calledOnce(forceRtcMetricsSend);
|
|
1210
|
+
|
|
1205
1211
|
assert.isNull(meeting.statsAnalyzer);
|
|
1206
1212
|
assert(webex.internal.newMetrics.submitInternalEvent.calledTwice);
|
|
1207
1213
|
assert.calledWith(webex.internal.newMetrics.submitInternalEvent.firstCall, {
|
|
@@ -33,6 +33,11 @@ describe('RtcMetrics', () => {
|
|
|
33
33
|
assert.calledWithMatch(webex.request, sinon.match.hasNested('body.metrics[0].correlationId', 'mock-correlation-id'));
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
+
it('should have a defined sendMetricsInQueue function which is public', () => {
|
|
37
|
+
assert.isDefined(metrics.sendMetricsInQueue);
|
|
38
|
+
assert.isFunction(metrics.sendMetricsInQueue);
|
|
39
|
+
});
|
|
40
|
+
|
|
36
41
|
it('should send metrics requests over time', () => {
|
|
37
42
|
assert.notCalled(webex.request);
|
|
38
43
|
|
|
@@ -48,11 +53,11 @@ describe('RtcMetrics', () => {
|
|
|
48
53
|
assert.notCalled(webex.request);
|
|
49
54
|
});
|
|
50
55
|
|
|
51
|
-
it('
|
|
56
|
+
it('sendMetricsInQueue should send metrics if any exist in the queue', () => {
|
|
52
57
|
assert.notCalled(webex.request);
|
|
53
58
|
|
|
54
59
|
metrics.addMetrics(FAKE_METRICS_ITEM);
|
|
55
|
-
(metrics as any).
|
|
60
|
+
(metrics as any).sendMetricsInQueue();
|
|
56
61
|
|
|
57
62
|
assert.callCount(webex.request, 1);
|
|
58
63
|
});
|