@webex/plugin-meetings 3.4.0 → 3.5.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/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 +6 -9
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/index.js +122 -49
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/util.js +1 -0
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +4 -2
- package/dist/meetings/index.js.map +1 -1
- package/dist/reachability/index.js +175 -103
- package/dist/reachability/index.js.map +1 -1
- package/dist/reconnection-manager/index.js +1 -1
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/rtcMetrics/index.js +26 -6
- package/dist/rtcMetrics/index.js.map +1 -1
- package/dist/types/meeting/index.d.ts +11 -2
- package/dist/types/meetings/index.d.ts +2 -1
- package/dist/types/reachability/index.d.ts +14 -2
- package/dist/types/rtcMetrics/index.d.ts +11 -1
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/media/index.ts +5 -9
- package/src/meeting/index.ts +54 -10
- package/src/meeting/util.ts +2 -0
- package/src/meetings/index.ts +4 -3
- package/src/reachability/index.ts +49 -4
- package/src/reconnection-manager/index.ts +1 -1
- package/src/rtcMetrics/index.ts +25 -5
- package/test/integration/spec/converged-space-meetings.js +1 -1
- package/test/unit/spec/breakouts/index.ts +1 -0
- package/test/unit/spec/interceptors/locusRetry.ts +11 -10
- package/test/unit/spec/media/MediaConnectionAwaiter.ts +1 -0
- package/test/unit/spec/media/index.ts +34 -7
- package/test/unit/spec/media/properties.ts +1 -1
- package/test/unit/spec/meeting/connectionStateHandler.ts +1 -0
- package/test/unit/spec/meeting/index.js +77 -6
- package/test/unit/spec/meeting/locusMediaRequest.ts +3 -2
- package/test/unit/spec/meeting/request.js +1 -0
- package/test/unit/spec/meeting/utils.js +4 -0
- package/test/unit/spec/meeting-info/meetinginfov2.js +10 -11
- package/test/unit/spec/meeting-info/request.js +1 -1
- package/test/unit/spec/meetings/index.js +30 -3
- package/test/unit/spec/members/request.js +2 -1
- package/test/unit/spec/multistream/mediaRequestManager.ts +1 -0
- package/test/unit/spec/multistream/receiveSlot.ts +1 -0
- package/test/unit/spec/multistream/receiveSlotManager.ts +1 -0
- package/test/unit/spec/multistream/remoteMedia.ts +1 -0
- package/test/unit/spec/multistream/remoteMediaGroup.ts +1 -0
- package/test/unit/spec/multistream/remoteMediaManager.ts +1 -0
- package/test/unit/spec/multistream/sendSlotManager.ts +1 -0
- package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +0 -1
- package/test/unit/spec/reachability/index.ts +211 -13
- package/test/unit/spec/reachability/request.js +1 -0
- package/test/unit/spec/roap/request.ts +1 -0
- package/test/unit/spec/rtcMetrics/index.ts +31 -0
- package/src/networkQualityMonitor/index.ts +0 -211
- package/test/unit/spec/networkQualityMonitor/index.js +0 -99
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_internalPluginMetrics","require","_uuid","_interopRequireDefault","_constants","parseJsonPayload","payload","JSON","parse","_","RtcMetrics","exports","default","webex","meetingId","correlationId","_classCallCheck2","_defineProperty2","intervalId","window","setInterval","sendMetricsInQueue","bind","
|
|
1
|
+
{"version":3,"names":["_internalPluginMetrics","require","_uuid","_interopRequireDefault","_constants","parseJsonPayload","payload","JSON","parse","_","RtcMetrics","exports","default","webex","meetingId","correlationId","_classCallCheck2","_defineProperty2","intervalId","window","setInterval","sendMetricsInQueue","bind","resetConnection","_createClass2","key","value","metricsQueue","length","sendMetrics","sendNextMetrics","shouldSendMetricsOnNextStatsReport","addMetrics","data","name","map","anonymizeIp","push","parsedPayload","e","console","error","closeMetrics","clearInterval","stats","type","ip","CallDiagnosticUtils","anonymizeIPAddress","undefined","address","relatedAddress","_stringify","connectionId","uuid","v4","request","method","service","resource","headers","appId","RTC_METRICS","APP_ID","body","metrics","version","userId","internal","device"],"sources":["index.ts"],"sourcesContent":["/* eslint-disable class-methods-use-this */\nimport {CallDiagnosticUtils} from '@webex/internal-plugin-metrics';\nimport uuid from 'uuid';\nimport RTC_METRICS from './constants';\n\nconst parseJsonPayload = (payload: any[]): any | null => {\n try {\n if (payload && payload[0]) {\n return JSON.parse(payload[0]);\n }\n\n return null;\n } catch (_) {\n return null;\n }\n};\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 connectionId: string;\n\n shouldSendMetricsOnNextStatsReport: boolean;\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 this.resetConnection();\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 * Forces sending metrics when we get the next stats-report\n *\n * This is useful for cases when something important happens that affects the media connection,\n * for example when we move from lobby into the meeting.\n *\n * @returns {void}\n */\n public sendNextMetrics() {\n this.shouldSendMetricsOnNextStatsReport = true;\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 if (data.name === 'stats-report') {\n data.payload = data.payload.map(this.anonymizeIp);\n }\n\n this.metricsQueue.push(data);\n\n if (this.shouldSendMetricsOnNextStatsReport && data.name === 'stats-report') {\n // this is the first useful set of data (WCME gives it to us after 5s), send it out immediately\n // in case the user is unhappy and closes the browser early\n this.sendMetricsInQueue();\n this.shouldSendMetricsOnNextStatsReport = false;\n }\n\n try {\n // If a connection fails, send the rest of the metrics in queue and get a new connection id.\n const parsedPayload = parseJsonPayload(data.payload);\n if (\n data.name === 'onconnectionstatechange' &&\n parsedPayload &&\n parsedPayload.value === 'failed'\n ) {\n this.sendMetricsInQueue();\n this.resetConnection();\n }\n } catch (e) {\n console.error(e);\n }\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 * Anonymize IP addresses.\n *\n * @param {array} stats - An RTCStatsReport organized into an array of strings.\n * @returns {string}\n */\n anonymizeIp(stats: string): string {\n const data = JSON.parse(stats);\n // on local and remote candidates, anonymize the last 4 bits.\n if (data.type === 'local-candidate' || data.type === 'remote-candidate') {\n data.ip = CallDiagnosticUtils.anonymizeIPAddress(data.ip) || undefined;\n data.address = CallDiagnosticUtils.anonymizeIPAddress(data.address) || undefined;\n data.relatedAddress =\n CallDiagnosticUtils.anonymizeIPAddress(data.relatedAddress) || undefined;\n }\n\n return JSON.stringify(data);\n }\n\n /**\n * Set a new connection id.\n *\n * @returns {void}\n */\n private resetConnection() {\n this.connectionId = uuid.v4();\n this.shouldSendMetricsOnNextStatsReport = true;\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.1.0',\n userId: this.webex.internal.device.userId,\n meetingId: this.meetingId,\n correlationId: this.correlationId,\n connectionId: this.connectionId,\n data: this.metricsQueue,\n },\n ],\n },\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
import { StatelessWebexPlugin } from '@webex/webex-core';
|
|
3
3
|
import { ClientEvent, ClientEventLeaveReason } from '@webex/internal-plugin-metrics';
|
|
4
4
|
import { ClientEvent as RawClientEvent } from '@webex/event-dictionary-ts';
|
|
5
|
-
import { MediaType, StatsAnalyzer } from '@webex/internal-media-core';
|
|
5
|
+
import { MediaType, StatsAnalyzer, NetworkQualityMonitor } from '@webex/internal-media-core';
|
|
6
6
|
import { LocalStream, LocalCameraStream, LocalDisplayStream, LocalSystemAudioStream, LocalMicrophoneStream } from '@webex/media-helpers';
|
|
7
|
-
import NetworkQualityMonitor from '../networkQualityMonitor';
|
|
8
7
|
import Roap, { type TurnServerInfo, type TurnDiscoverySkipReason } from '../roap/index';
|
|
9
8
|
import { type BundlePolicy } from '../media';
|
|
10
9
|
import MediaProperties from '../media/properties';
|
|
@@ -334,6 +333,7 @@ type FetchMeetingInfoParams = {
|
|
|
334
333
|
* @class Meeting
|
|
335
334
|
*/
|
|
336
335
|
export default class Meeting extends StatelessWebexPlugin {
|
|
336
|
+
#private;
|
|
337
337
|
attrs: any;
|
|
338
338
|
audio: any;
|
|
339
339
|
breakouts: any;
|
|
@@ -458,6 +458,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
458
458
|
private connectionStateHandler?;
|
|
459
459
|
private iceCandidateErrors;
|
|
460
460
|
private iceCandidatesCount;
|
|
461
|
+
private rtcMetrics?;
|
|
461
462
|
/**
|
|
462
463
|
* @param {Object} attrs
|
|
463
464
|
* @param {Object} options
|
|
@@ -487,6 +488,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
487
488
|
* @param {string} correlationId
|
|
488
489
|
*/
|
|
489
490
|
set correlationId(correlationId: string);
|
|
491
|
+
/**
|
|
492
|
+
* Getter - Returns isoLocalClientMeetingJoinTime
|
|
493
|
+
* This will be set once on meeting join, and not updated again
|
|
494
|
+
* @returns {string | undefined}
|
|
495
|
+
*/
|
|
496
|
+
get isoLocalClientMeetingJoinTime(): string | undefined;
|
|
490
497
|
/**
|
|
491
498
|
* Set meeting info and trigger `MEETING_INFO_AVAILABLE` event
|
|
492
499
|
* @param {any} info
|
|
@@ -1295,6 +1302,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1295
1302
|
*
|
|
1296
1303
|
* @private
|
|
1297
1304
|
* @static
|
|
1305
|
+
* @param {boolean} isAudioEnabled
|
|
1306
|
+
* @param {boolean} isVideoEnabled
|
|
1298
1307
|
* @returns {Promise<void>}
|
|
1299
1308
|
*/
|
|
1300
1309
|
private static handleDeviceLogging;
|
|
@@ -253,11 +253,12 @@ export default class Meetings extends WebexPlugin {
|
|
|
253
253
|
getReachability(): Reachability;
|
|
254
254
|
/**
|
|
255
255
|
* initializes and starts gathering reachability for Meetings
|
|
256
|
+
* @param {string} trigger - explains the reason for starting reachability
|
|
256
257
|
* @returns {Promise}
|
|
257
258
|
* @public
|
|
258
259
|
* @memberof Meetings
|
|
259
260
|
*/
|
|
260
|
-
startReachability(): Promise<import("../reachability").ReachabilityResults>;
|
|
261
|
+
startReachability(trigger?: string): Promise<import("../reachability").ReachabilityResults>;
|
|
261
262
|
/**
|
|
262
263
|
* Get geoHint for info for meetings
|
|
263
264
|
* @returns {Promise}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
3
|
*/
|
|
4
4
|
import { Defer } from '@webex/common';
|
|
5
|
-
import ReachabilityRequest from './request';
|
|
5
|
+
import ReachabilityRequest, { ClusterList } from './request';
|
|
6
6
|
import { ClusterReachability, ClusterReachabilityResult } from './clusterReachability';
|
|
7
7
|
import EventsScope from '../common/events/events-scope';
|
|
8
8
|
export type ReachabilityMetrics = {
|
|
@@ -73,19 +73,31 @@ export default class Reachability extends EventsScope {
|
|
|
73
73
|
xtls: number;
|
|
74
74
|
};
|
|
75
75
|
};
|
|
76
|
+
protected lastTrigger?: string;
|
|
76
77
|
/**
|
|
77
78
|
* Creates an instance of Reachability.
|
|
78
79
|
* @param {object} webex
|
|
79
80
|
* @memberof Reachability
|
|
80
81
|
*/
|
|
81
82
|
constructor(webex: object);
|
|
83
|
+
/**
|
|
84
|
+
* Fetches the list of media clusters from the backend
|
|
85
|
+
* @param {boolean} isRetry
|
|
86
|
+
* @private
|
|
87
|
+
* @returns {Promise<{clusters: ClusterList, joinCookie: any}>}
|
|
88
|
+
*/
|
|
89
|
+
getClusters(isRetry?: boolean): Promise<{
|
|
90
|
+
clusters: ClusterList;
|
|
91
|
+
joinCookie: any;
|
|
92
|
+
}>;
|
|
82
93
|
/**
|
|
83
94
|
* Gets a list of media clusters from the backend and performs reachability checks on all the clusters
|
|
95
|
+
* @param {string} trigger - explains the reason for starting reachability
|
|
84
96
|
* @returns {Promise<ReachabilityResults>} reachability results
|
|
85
97
|
* @public
|
|
86
98
|
* @memberof Reachability
|
|
87
99
|
*/
|
|
88
|
-
gatherReachability(): Promise<ReachabilityResults>;
|
|
100
|
+
gatherReachability(trigger: string): Promise<ReachabilityResults>;
|
|
89
101
|
/**
|
|
90
102
|
* Returns statistics about last reachability results. The returned value is an object
|
|
91
103
|
* with a flat list of properties so that it can be easily sent with metrics
|
|
@@ -11,6 +11,7 @@ export default class RtcMetrics {
|
|
|
11
11
|
meetingId: string;
|
|
12
12
|
correlationId: string;
|
|
13
13
|
connectionId: string;
|
|
14
|
+
shouldSendMetricsOnNextStatsReport: boolean;
|
|
14
15
|
/**
|
|
15
16
|
* Initialize the interval.
|
|
16
17
|
*
|
|
@@ -25,6 +26,15 @@ export default class RtcMetrics {
|
|
|
25
26
|
* @returns {void}
|
|
26
27
|
*/
|
|
27
28
|
sendMetricsInQueue(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Forces sending metrics when we get the next stats-report
|
|
31
|
+
*
|
|
32
|
+
* This is useful for cases when something important happens that affects the media connection,
|
|
33
|
+
* for example when we move from lobby into the meeting.
|
|
34
|
+
*
|
|
35
|
+
* @returns {void}
|
|
36
|
+
*/
|
|
37
|
+
sendNextMetrics(): void;
|
|
28
38
|
/**
|
|
29
39
|
* Add metrics items to the metrics queue.
|
|
30
40
|
*
|
|
@@ -51,7 +61,7 @@ export default class RtcMetrics {
|
|
|
51
61
|
*
|
|
52
62
|
* @returns {void}
|
|
53
63
|
*/
|
|
54
|
-
private
|
|
64
|
+
private resetConnection;
|
|
55
65
|
/**
|
|
56
66
|
* Send metrics to the metrics service.
|
|
57
67
|
*
|
package/dist/webinar/index.js
CHANGED
|
@@ -62,7 +62,7 @@ var Webinar = _webexCore.WebexPlugin.extend({
|
|
|
62
62
|
updateCanManageWebcast: function updateCanManageWebcast(canManageWebcast) {
|
|
63
63
|
this.set('canManageWebcast', canManageWebcast);
|
|
64
64
|
},
|
|
65
|
-
version: "3.
|
|
65
|
+
version: "3.5.0"
|
|
66
66
|
});
|
|
67
67
|
var _default = exports.default = Webinar;
|
|
68
68
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -43,13 +43,13 @@
|
|
|
43
43
|
"@webex/eslint-config-legacy": "0.0.0",
|
|
44
44
|
"@webex/jest-config-legacy": "0.0.0",
|
|
45
45
|
"@webex/legacy-tools": "0.0.0",
|
|
46
|
-
"@webex/plugin-meetings": "3.
|
|
47
|
-
"@webex/plugin-rooms": "3.
|
|
48
|
-
"@webex/test-helper-chai": "3.
|
|
49
|
-
"@webex/test-helper-mocha": "3.
|
|
50
|
-
"@webex/test-helper-mock-webex": "3.
|
|
51
|
-
"@webex/test-helper-retry": "3.
|
|
52
|
-
"@webex/test-helper-test-users": "3.
|
|
46
|
+
"@webex/plugin-meetings": "3.5.0",
|
|
47
|
+
"@webex/plugin-rooms": "3.5.0",
|
|
48
|
+
"@webex/test-helper-chai": "3.5.0",
|
|
49
|
+
"@webex/test-helper-mocha": "3.5.0",
|
|
50
|
+
"@webex/test-helper-mock-webex": "3.5.0",
|
|
51
|
+
"@webex/test-helper-retry": "3.5.0",
|
|
52
|
+
"@webex/test-helper-test-users": "3.5.0",
|
|
53
53
|
"chai": "^4.3.4",
|
|
54
54
|
"chai-as-promised": "^7.1.1",
|
|
55
55
|
"eslint": "^8.24.0",
|
|
@@ -61,21 +61,21 @@
|
|
|
61
61
|
"typescript": "^4.7.4"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@webex/common": "3.
|
|
65
|
-
"@webex/internal-media-core": "2.
|
|
66
|
-
"@webex/internal-plugin-conversation": "3.
|
|
67
|
-
"@webex/internal-plugin-device": "3.
|
|
68
|
-
"@webex/internal-plugin-llm": "3.
|
|
69
|
-
"@webex/internal-plugin-mercury": "3.
|
|
70
|
-
"@webex/internal-plugin-metrics": "3.
|
|
71
|
-
"@webex/internal-plugin-support": "3.
|
|
72
|
-
"@webex/internal-plugin-user": "3.
|
|
73
|
-
"@webex/internal-plugin-voicea": "3.
|
|
74
|
-
"@webex/media-helpers": "3.
|
|
75
|
-
"@webex/plugin-people": "3.
|
|
76
|
-
"@webex/plugin-rooms": "3.
|
|
64
|
+
"@webex/common": "3.5.0",
|
|
65
|
+
"@webex/internal-media-core": "2.11.1",
|
|
66
|
+
"@webex/internal-plugin-conversation": "3.5.0",
|
|
67
|
+
"@webex/internal-plugin-device": "3.5.0",
|
|
68
|
+
"@webex/internal-plugin-llm": "3.5.0",
|
|
69
|
+
"@webex/internal-plugin-mercury": "3.5.0",
|
|
70
|
+
"@webex/internal-plugin-metrics": "3.5.0",
|
|
71
|
+
"@webex/internal-plugin-support": "3.5.0",
|
|
72
|
+
"@webex/internal-plugin-user": "3.5.0",
|
|
73
|
+
"@webex/internal-plugin-voicea": "3.5.0",
|
|
74
|
+
"@webex/media-helpers": "3.5.0",
|
|
75
|
+
"@webex/plugin-people": "3.5.0",
|
|
76
|
+
"@webex/plugin-rooms": "3.5.0",
|
|
77
77
|
"@webex/web-capabilities": "^1.4.0",
|
|
78
|
-
"@webex/webex-core": "3.
|
|
78
|
+
"@webex/webex-core": "3.5.0",
|
|
79
79
|
"ampersand-collection": "^2.0.2",
|
|
80
80
|
"bowser": "^2.11.0",
|
|
81
81
|
"btoa": "^1.2.1",
|
|
@@ -91,5 +91,5 @@
|
|
|
91
91
|
"//": [
|
|
92
92
|
"TODO: upgrade jwt-decode when moving to node 18"
|
|
93
93
|
],
|
|
94
|
-
"version": "3.
|
|
94
|
+
"version": "3.5.0"
|
|
95
95
|
}
|
package/src/media/index.ts
CHANGED
|
@@ -104,9 +104,7 @@ Media.getDirection = (forceSendRecv: boolean, receive: boolean, send: boolean) =
|
|
|
104
104
|
*
|
|
105
105
|
* @param {boolean} isMultistream
|
|
106
106
|
* @param {string} debugId string useful for debugging (will appear in media connection logs)
|
|
107
|
-
* @param {object} webex main `webex` object.
|
|
108
107
|
* @param {string} meetingId id for the meeting using this connection
|
|
109
|
-
* @param {string} correlationId id used in requests to correlate to this session
|
|
110
108
|
* @param {Object} options
|
|
111
109
|
* @param {Object} [options.mediaProperties] contains mediaDirection and local tracks:
|
|
112
110
|
* audioTrack, videoTrack, shareVideoTrack, and shareAudioTrack
|
|
@@ -120,10 +118,9 @@ Media.getDirection = (forceSendRecv: boolean, receive: boolean, send: boolean) =
|
|
|
120
118
|
Media.createMediaConnection = (
|
|
121
119
|
isMultistream: boolean,
|
|
122
120
|
debugId: string,
|
|
123
|
-
webex: object,
|
|
124
121
|
meetingId: string,
|
|
125
|
-
correlationId: string,
|
|
126
122
|
options: {
|
|
123
|
+
rtcMetrics?: RtcMetrics;
|
|
127
124
|
mediaProperties: {
|
|
128
125
|
mediaDirection?: {
|
|
129
126
|
receiveAudio: boolean;
|
|
@@ -150,6 +147,7 @@ Media.createMediaConnection = (
|
|
|
150
147
|
}
|
|
151
148
|
) => {
|
|
152
149
|
const {
|
|
150
|
+
rtcMetrics,
|
|
153
151
|
mediaProperties,
|
|
154
152
|
remoteQualityLevel,
|
|
155
153
|
enableRtx,
|
|
@@ -192,15 +190,13 @@ Media.createMediaConnection = (
|
|
|
192
190
|
config.bundlePolicy = bundlePolicy;
|
|
193
191
|
}
|
|
194
192
|
|
|
195
|
-
const rtcMetrics = new RtcMetrics(webex, meetingId, correlationId);
|
|
196
|
-
|
|
197
193
|
return new MultistreamRoapMediaConnection(
|
|
198
194
|
config,
|
|
199
195
|
meetingId,
|
|
200
196
|
/* the rtc metrics objects callbacks */
|
|
201
|
-
(data) => rtcMetrics
|
|
202
|
-
() => rtcMetrics
|
|
203
|
-
() => rtcMetrics
|
|
197
|
+
(data) => rtcMetrics?.addMetrics(data),
|
|
198
|
+
() => rtcMetrics?.closeMetrics(),
|
|
199
|
+
() => rtcMetrics?.sendMetricsInQueue()
|
|
204
200
|
);
|
|
205
201
|
}
|
|
206
202
|
|
package/src/meeting/index.ts
CHANGED
|
@@ -24,6 +24,8 @@ import {
|
|
|
24
24
|
RoapMessage,
|
|
25
25
|
StatsAnalyzer,
|
|
26
26
|
StatsAnalyzerEventNames,
|
|
27
|
+
NetworkQualityEventNames,
|
|
28
|
+
NetworkQualityMonitor,
|
|
27
29
|
} from '@webex/internal-media-core';
|
|
28
30
|
|
|
29
31
|
import {
|
|
@@ -54,7 +56,6 @@ import {
|
|
|
54
56
|
AddMediaFailed,
|
|
55
57
|
} from '../common/errors/webex-errors';
|
|
56
58
|
|
|
57
|
-
import NetworkQualityMonitor from '../networkQualityMonitor';
|
|
58
59
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
59
60
|
import EventsUtil from '../common/events/util';
|
|
60
61
|
import Trigger from '../common/events/trigger-proxy';
|
|
@@ -154,6 +155,7 @@ import ControlsOptionsManager from '../controls-options-manager';
|
|
|
154
155
|
import PermissionError from '../common/errors/permission';
|
|
155
156
|
import {LocusMediaRequest} from './locusMediaRequest';
|
|
156
157
|
import {ConnectionStateHandler, ConnectionStateEvent} from './connectionStateHandler';
|
|
158
|
+
import RtcMetrics from '../rtcMetrics';
|
|
157
159
|
|
|
158
160
|
// default callback so we don't call an undefined function, but in practice it should never be used
|
|
159
161
|
const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
|
|
@@ -536,6 +538,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
536
538
|
id: string;
|
|
537
539
|
isMultistream: boolean;
|
|
538
540
|
locusUrl: string;
|
|
541
|
+
#isoLocalClientMeetingJoinTime?: string;
|
|
539
542
|
mediaConnections: any[];
|
|
540
543
|
mediaId?: string;
|
|
541
544
|
meetingFiniteStateMachine: any;
|
|
@@ -695,6 +698,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
695
698
|
private connectionStateHandler?: ConnectionStateHandler;
|
|
696
699
|
private iceCandidateErrors: Map<string, number>;
|
|
697
700
|
private iceCandidatesCount: number;
|
|
701
|
+
private rtcMetrics?: RtcMetrics;
|
|
698
702
|
|
|
699
703
|
/**
|
|
700
704
|
* @param {Object} attrs
|
|
@@ -1518,6 +1522,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1518
1522
|
* @memberof Meeting
|
|
1519
1523
|
*/
|
|
1520
1524
|
this.iceCandidatesCount = 0;
|
|
1525
|
+
|
|
1526
|
+
/**
|
|
1527
|
+
* Start time of meeting as an ISO string
|
|
1528
|
+
* based on browser time, so can only be used to compute durations client side
|
|
1529
|
+
* undefined if meeting has not been joined, set once on meeting join, and not updated again
|
|
1530
|
+
* @instance
|
|
1531
|
+
* @type {string}
|
|
1532
|
+
* @private
|
|
1533
|
+
* @memberof Meeting
|
|
1534
|
+
*/
|
|
1535
|
+
this.#isoLocalClientMeetingJoinTime = undefined;
|
|
1521
1536
|
}
|
|
1522
1537
|
|
|
1523
1538
|
/**
|
|
@@ -1566,6 +1581,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1566
1581
|
this.callStateForMetrics.correlationId = correlationId;
|
|
1567
1582
|
}
|
|
1568
1583
|
|
|
1584
|
+
/**
|
|
1585
|
+
* Getter - Returns isoLocalClientMeetingJoinTime
|
|
1586
|
+
* This will be set once on meeting join, and not updated again
|
|
1587
|
+
* @returns {string | undefined}
|
|
1588
|
+
*/
|
|
1589
|
+
get isoLocalClientMeetingJoinTime(): string | undefined {
|
|
1590
|
+
return this.#isoLocalClientMeetingJoinTime;
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1569
1593
|
/**
|
|
1570
1594
|
* Set meeting info and trigger `MEETING_INFO_AVAILABLE` event
|
|
1571
1595
|
* @param {any} info
|
|
@@ -3155,6 +3179,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3155
3179
|
options: {meetingId: this.id},
|
|
3156
3180
|
});
|
|
3157
3181
|
}
|
|
3182
|
+
this.rtcMetrics?.sendNextMetrics();
|
|
3158
3183
|
this.updateLLMConnection();
|
|
3159
3184
|
});
|
|
3160
3185
|
|
|
@@ -5228,6 +5253,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5228
5253
|
this.meetingFiniteStateMachine.join();
|
|
5229
5254
|
this.setupLocusMediaRequest();
|
|
5230
5255
|
|
|
5256
|
+
// @ts-ignore
|
|
5257
|
+
this.webex.internal.device.meetingStarted();
|
|
5258
|
+
|
|
5259
|
+
this.#isoLocalClientMeetingJoinTime = new Date().toISOString();
|
|
5260
|
+
|
|
5231
5261
|
LoggerProxy.logger.log('Meeting:index#join --> Success');
|
|
5232
5262
|
|
|
5233
5263
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_SUCCESS, {
|
|
@@ -6306,14 +6336,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6306
6336
|
* @returns {RoapMediaConnection | MultistreamRoapMediaConnection}
|
|
6307
6337
|
*/
|
|
6308
6338
|
private async createMediaConnection(turnServerInfo, bundlePolicy?: BundlePolicy) {
|
|
6339
|
+
this.rtcMetrics = this.isMultistream
|
|
6340
|
+
? // @ts-ignore
|
|
6341
|
+
new RtcMetrics(this.webex, this.id, this.correlationId)
|
|
6342
|
+
: undefined;
|
|
6343
|
+
|
|
6309
6344
|
const mc = Media.createMediaConnection(
|
|
6310
6345
|
this.isMultistream,
|
|
6311
6346
|
this.getMediaConnectionDebugId(),
|
|
6312
|
-
// @ts-ignore
|
|
6313
|
-
this.webex,
|
|
6314
6347
|
this.id,
|
|
6315
|
-
this.correlationId,
|
|
6316
6348
|
{
|
|
6349
|
+
rtcMetrics: this.rtcMetrics,
|
|
6317
6350
|
mediaProperties: this.mediaProperties,
|
|
6318
6351
|
remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
|
|
6319
6352
|
// @ts-ignore - config coming from registerPlugin
|
|
@@ -6500,7 +6533,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6500
6533
|
});
|
|
6501
6534
|
this.setupStatsAnalyzerEventHandlers();
|
|
6502
6535
|
this.networkQualityMonitor.on(
|
|
6503
|
-
|
|
6536
|
+
NetworkQualityEventNames.NETWORK_QUALITY,
|
|
6504
6537
|
this.sendNetworkQualityEvent.bind(this)
|
|
6505
6538
|
);
|
|
6506
6539
|
}
|
|
@@ -6511,12 +6544,21 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6511
6544
|
*
|
|
6512
6545
|
* @private
|
|
6513
6546
|
* @static
|
|
6547
|
+
* @param {boolean} isAudioEnabled
|
|
6548
|
+
* @param {boolean} isVideoEnabled
|
|
6514
6549
|
* @returns {Promise<void>}
|
|
6515
6550
|
*/
|
|
6516
|
-
private static async handleDeviceLogging(): Promise<void> {
|
|
6517
|
-
try {
|
|
6518
|
-
const devices = await getDevices();
|
|
6519
6551
|
|
|
6552
|
+
private static async handleDeviceLogging(isAudioEnabled, isVideoEnabled): Promise<void> {
|
|
6553
|
+
try {
|
|
6554
|
+
let devices = [];
|
|
6555
|
+
if (isVideoEnabled && isAudioEnabled) {
|
|
6556
|
+
devices = await getDevices();
|
|
6557
|
+
} else if (isVideoEnabled) {
|
|
6558
|
+
devices = await getDevices(Media.DeviceKind.VIDEO_INPUT);
|
|
6559
|
+
} else if (isAudioEnabled) {
|
|
6560
|
+
devices = await getDevices(Media.DeviceKind.AUDIO_INPUT);
|
|
6561
|
+
}
|
|
6520
6562
|
MeetingUtil.handleDeviceLogging(devices);
|
|
6521
6563
|
} catch {
|
|
6522
6564
|
// getDevices may fail if we don't have browser permissions, that's ok, we still can have a media connection
|
|
@@ -7009,7 +7051,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7009
7051
|
);
|
|
7010
7052
|
|
|
7011
7053
|
if (audioEnabled || videoEnabled) {
|
|
7012
|
-
await Meeting.handleDeviceLogging();
|
|
7054
|
+
await Meeting.handleDeviceLogging(audioEnabled, videoEnabled);
|
|
7013
7055
|
} else {
|
|
7014
7056
|
LoggerProxy.logger.info(`${LOG_HEADER} device logging not required`);
|
|
7015
7057
|
}
|
|
@@ -7022,6 +7064,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7022
7064
|
await this.mediaProperties.getCurrentConnectionInfo();
|
|
7023
7065
|
// @ts-ignore
|
|
7024
7066
|
const reachabilityStats = await this.webex.meetings.reachability.getReachabilityMetrics();
|
|
7067
|
+
const iceCandidateErrors = Object.fromEntries(this.iceCandidateErrors);
|
|
7025
7068
|
|
|
7026
7069
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS, {
|
|
7027
7070
|
correlation_id: this.correlationId,
|
|
@@ -7033,6 +7076,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7033
7076
|
retriedWithTurnServer: this.addMediaData.retriedWithTurnServer,
|
|
7034
7077
|
isJoinWithMediaRetry: this.joinWithMediaRetryInfo.isRetry,
|
|
7035
7078
|
...reachabilityStats,
|
|
7079
|
+
...iceCandidateErrors,
|
|
7036
7080
|
iceCandidatesCount: this.iceCandidatesCount,
|
|
7037
7081
|
});
|
|
7038
7082
|
// @ts-ignore
|
|
@@ -8191,7 +8235,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
8191
8235
|
* @private
|
|
8192
8236
|
* @memberof Meeting
|
|
8193
8237
|
*/
|
|
8194
|
-
private sendNetworkQualityEvent(res:
|
|
8238
|
+
private sendNetworkQualityEvent(res: {networkQualityScore: number; mediaType: string}) {
|
|
8195
8239
|
Trigger.trigger(
|
|
8196
8240
|
this,
|
|
8197
8241
|
{
|
package/src/meeting/util.ts
CHANGED
package/src/meetings/index.ts
CHANGED
|
@@ -765,7 +765,7 @@ export default class Meetings extends WebexPlugin {
|
|
|
765
765
|
return Promise.all([
|
|
766
766
|
this.fetchUserPreferredWebexSite(),
|
|
767
767
|
this.getGeoHint(),
|
|
768
|
-
this.startReachability().catch((error) => {
|
|
768
|
+
this.startReachability('registration').catch((error) => {
|
|
769
769
|
LoggerProxy.logger.error(`Meetings:index#register --> GDM error, ${error.message}`);
|
|
770
770
|
}),
|
|
771
771
|
// @ts-ignore
|
|
@@ -967,12 +967,13 @@ export default class Meetings extends WebexPlugin {
|
|
|
967
967
|
|
|
968
968
|
/**
|
|
969
969
|
* initializes and starts gathering reachability for Meetings
|
|
970
|
+
* @param {string} trigger - explains the reason for starting reachability
|
|
970
971
|
* @returns {Promise}
|
|
971
972
|
* @public
|
|
972
973
|
* @memberof Meetings
|
|
973
974
|
*/
|
|
974
|
-
startReachability() {
|
|
975
|
-
return this.getReachability().gatherReachability();
|
|
975
|
+
startReachability(trigger = 'client') {
|
|
976
|
+
return this.getReachability().gatherReachability(trigger);
|
|
976
977
|
}
|
|
977
978
|
|
|
978
979
|
/**
|
|
@@ -93,6 +93,8 @@ export default class Reachability extends EventsScope {
|
|
|
93
93
|
expectedResultsCount = {videoMesh: {udp: 0}, public: {udp: 0, tcp: 0, xtls: 0}};
|
|
94
94
|
resultsCount = {videoMesh: {udp: 0}, public: {udp: 0, tcp: 0, xtls: 0}};
|
|
95
95
|
|
|
96
|
+
protected lastTrigger?: string;
|
|
97
|
+
|
|
96
98
|
/**
|
|
97
99
|
* Creates an instance of Reachability.
|
|
98
100
|
* @param {object} webex
|
|
@@ -114,18 +116,50 @@ export default class Reachability extends EventsScope {
|
|
|
114
116
|
this.clusterReachability = {};
|
|
115
117
|
}
|
|
116
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Fetches the list of media clusters from the backend
|
|
121
|
+
* @param {boolean} isRetry
|
|
122
|
+
* @private
|
|
123
|
+
* @returns {Promise<{clusters: ClusterList, joinCookie: any}>}
|
|
124
|
+
*/
|
|
125
|
+
async getClusters(isRetry = false): Promise<{clusters: ClusterList; joinCookie: any}> {
|
|
126
|
+
try {
|
|
127
|
+
const {clusters, joinCookie} = await this.reachabilityRequest.getClusters(
|
|
128
|
+
MeetingUtil.getIpVersion(this.webex)
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
return {clusters, joinCookie};
|
|
132
|
+
} catch (error) {
|
|
133
|
+
if (isRetry) {
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
LoggerProxy.logger.error(
|
|
138
|
+
`Reachability:index#getClusters --> Failed with error: ${error}, retrying...`
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
return this.getClusters(true);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
117
145
|
/**
|
|
118
146
|
* Gets a list of media clusters from the backend and performs reachability checks on all the clusters
|
|
147
|
+
* @param {string} trigger - explains the reason for starting reachability
|
|
119
148
|
* @returns {Promise<ReachabilityResults>} reachability results
|
|
120
149
|
* @public
|
|
121
150
|
* @memberof Reachability
|
|
122
151
|
*/
|
|
123
|
-
public async gatherReachability(): Promise<ReachabilityResults> {
|
|
152
|
+
public async gatherReachability(trigger: string): Promise<ReachabilityResults> {
|
|
124
153
|
// Fetch clusters and measure latency
|
|
125
154
|
try {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
155
|
+
this.lastTrigger = trigger;
|
|
156
|
+
|
|
157
|
+
// kick off ip version detection. For now we don't await it, as we're doing it
|
|
158
|
+
// to gather the timings and send them with our reachability metrics
|
|
159
|
+
// @ts-ignore
|
|
160
|
+
this.webex.internal.device.ipNetworkDetector.detect();
|
|
161
|
+
|
|
162
|
+
const {clusters, joinCookie} = await this.getClusters();
|
|
129
163
|
|
|
130
164
|
// @ts-ignore
|
|
131
165
|
await this.webex.boundedStorage.put(
|
|
@@ -513,6 +547,17 @@ export default class Reachability extends EventsScope {
|
|
|
513
547
|
tcp: this.getStatistics(results, 'tcp', false),
|
|
514
548
|
xtls: this.getStatistics(results, 'xtls', false),
|
|
515
549
|
},
|
|
550
|
+
ipver: {
|
|
551
|
+
// @ts-ignore
|
|
552
|
+
firstIpV4: this.webex.internal.device.ipNetworkDetector.firstIpV4,
|
|
553
|
+
// @ts-ignore
|
|
554
|
+
firstIpV6: this.webex.internal.device.ipNetworkDetector.firstIpV6,
|
|
555
|
+
// @ts-ignore
|
|
556
|
+
firstMdns: this.webex.internal.device.ipNetworkDetector.firstMdns,
|
|
557
|
+
// @ts-ignore
|
|
558
|
+
totalTime: this.webex.internal.device.ipNetworkDetector.totalTime,
|
|
559
|
+
},
|
|
560
|
+
trigger: this.lastTrigger,
|
|
516
561
|
};
|
|
517
562
|
Metrics.sendBehavioralMetric(
|
|
518
563
|
BEHAVIORAL_METRICS.REACHABILITY_COMPLETED,
|
|
@@ -342,7 +342,7 @@ export default class ReconnectionManager {
|
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
try {
|
|
345
|
-
await this.webex.meetings.startReachability();
|
|
345
|
+
await this.webex.meetings.startReachability('reconnection');
|
|
346
346
|
} catch (err) {
|
|
347
347
|
LoggerProxy.logger.info(
|
|
348
348
|
'ReconnectionManager:index#reconnect --> Reachability failed, continuing with reconnection attempt, err: ',
|