@webex/plugin-meetings 3.5.0-next.7 → 3.5.0-next.8

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.
@@ -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.5.0-next.7"
65
+ version: "3.5.0-next.8"
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.5.0-next.7",
47
- "@webex/plugin-rooms": "3.5.0-next.4",
48
- "@webex/test-helper-chai": "3.5.0-next.4",
49
- "@webex/test-helper-mocha": "3.5.0-next.4",
50
- "@webex/test-helper-mock-webex": "3.5.0-next.4",
51
- "@webex/test-helper-retry": "3.5.0-next.4",
52
- "@webex/test-helper-test-users": "3.5.0-next.4",
46
+ "@webex/plugin-meetings": "3.5.0-next.8",
47
+ "@webex/plugin-rooms": "3.5.0-next.5",
48
+ "@webex/test-helper-chai": "3.5.0-next.5",
49
+ "@webex/test-helper-mocha": "3.5.0-next.5",
50
+ "@webex/test-helper-mock-webex": "3.5.0-next.5",
51
+ "@webex/test-helper-retry": "3.5.0-next.5",
52
+ "@webex/test-helper-test-users": "3.5.0-next.5",
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.5.0-next.4",
64
+ "@webex/common": "3.5.0-next.5",
65
65
  "@webex/internal-media-core": "2.11.3",
66
- "@webex/internal-plugin-conversation": "3.5.0-next.4",
67
- "@webex/internal-plugin-device": "3.5.0-next.4",
68
- "@webex/internal-plugin-llm": "3.5.0-next.4",
69
- "@webex/internal-plugin-mercury": "3.5.0-next.4",
70
- "@webex/internal-plugin-metrics": "3.5.0-next.4",
71
- "@webex/internal-plugin-support": "3.5.0-next.4",
72
- "@webex/internal-plugin-user": "3.5.0-next.4",
73
- "@webex/internal-plugin-voicea": "3.5.0-next.7",
74
- "@webex/media-helpers": "3.5.0-next.5",
75
- "@webex/plugin-people": "3.5.0-next.4",
76
- "@webex/plugin-rooms": "3.5.0-next.4",
66
+ "@webex/internal-plugin-conversation": "3.5.0-next.5",
67
+ "@webex/internal-plugin-device": "3.5.0-next.5",
68
+ "@webex/internal-plugin-llm": "3.5.0-next.5",
69
+ "@webex/internal-plugin-mercury": "3.5.0-next.5",
70
+ "@webex/internal-plugin-metrics": "3.5.0-next.5",
71
+ "@webex/internal-plugin-support": "3.5.0-next.5",
72
+ "@webex/internal-plugin-user": "3.5.0-next.5",
73
+ "@webex/internal-plugin-voicea": "3.5.0-next.8",
74
+ "@webex/media-helpers": "3.5.0-next.6",
75
+ "@webex/plugin-people": "3.5.0-next.5",
76
+ "@webex/plugin-rooms": "3.5.0-next.5",
77
77
  "@webex/web-capabilities": "^1.4.0",
78
- "@webex/webex-core": "3.5.0-next.4",
78
+ "@webex/webex-core": "3.5.0-next.5",
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.5.0-next.7"
94
+ "version": "3.5.0-next.8"
95
95
  }
@@ -15,12 +15,12 @@ import {
15
15
  LocalSystemAudioStream,
16
16
  LocalMicrophoneStream,
17
17
  } from '@webex/media-helpers';
18
+ import {RtcMetrics} from '@webex/internal-plugin-metrics';
18
19
  import LoggerProxy from '../common/logs/logger-proxy';
19
20
  import {MEDIA_TRACK_CONSTRAINT} from '../constants';
20
21
  import Config from '../config';
21
22
  import StaticConfig from '../common/config';
22
23
  import BrowserDetection from '../common/browser-detection';
23
- import RtcMetrics from '../rtcMetrics';
24
24
 
25
25
  const {isBrowser} = BrowserDetection();
26
26
 
@@ -10,6 +10,7 @@ import {
10
10
  ClientEventLeaveReason,
11
11
  CallDiagnosticUtils,
12
12
  CALL_DIAGNOSTIC_CONFIG,
13
+ RtcMetrics,
13
14
  } from '@webex/internal-plugin-metrics';
14
15
  import {ClientEvent as RawClientEvent} from '@webex/event-dictionary-ts';
15
16
 
@@ -155,7 +156,6 @@ import ControlsOptionsManager from '../controls-options-manager';
155
156
  import PermissionError from '../common/errors/permission';
156
157
  import {LocusMediaRequest} from './locusMediaRequest';
157
158
  import {ConnectionStateHandler, ConnectionStateEvent} from './connectionStateHandler';
158
- import RtcMetrics from '../rtcMetrics';
159
159
 
160
160
  // default callback so we don't call an undefined function, but in practice it should never be used
161
161
  const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
@@ -5,7 +5,6 @@ import 'jsdom-global/register';
5
5
  import {cloneDeep, forEach, isEqual, isUndefined} from 'lodash';
6
6
  import sinon from 'sinon';
7
7
  import * as InternalMediaCoreModule from '@webex/internal-media-core';
8
- import * as RtcMetricsModule from '@webex/plugin-meetings/src/rtcMetrics';
9
8
  import * as RemoteMediaManagerModule from '@webex/plugin-meetings/src/multistream/remoteMediaManager';
10
9
  import StateMachine from 'javascript-state-machine';
11
10
  import uuid from 'uuid';
@@ -2487,8 +2486,8 @@ describe('plugin-meetings', () => {
2487
2486
  });
2488
2487
 
2489
2488
  it('should create rtcMetrics and pass them to Media.createMediaConnection()', async () => {
2490
- const fakeRtcMetrics = {id: 'fake rtc metrics object'};
2491
- const rtcMetricsCtor = sinon.stub(RtcMetricsModule, 'default').returns(fakeRtcMetrics);
2489
+ const setIntervalOriginal = window.setInterval;
2490
+ window.setInterval = sinon.stub().returns(1);
2492
2491
 
2493
2492
  // setup the minimum mocks required for multistream connection
2494
2493
  fakeMediaConnection.createSendSlot = sinon.stub().returns({
@@ -2509,8 +2508,6 @@ describe('plugin-meetings', () => {
2509
2508
  mediaSettings: {},
2510
2509
  });
2511
2510
 
2512
- assert.calledOnceWithExactly(rtcMetricsCtor, webex, meeting.id, meeting.correlationId);
2513
-
2514
2511
  // check that rtcMetrics was passed to Media.createMediaConnection
2515
2512
  assert.calledOnce(Media.createMediaConnection);
2516
2513
  assert.calledWith(
@@ -2518,10 +2515,10 @@ describe('plugin-meetings', () => {
2518
2515
  true,
2519
2516
  meeting.getMediaConnectionDebugId(),
2520
2517
  meeting.id,
2521
- sinon.match({
2522
- rtcMetrics: fakeRtcMetrics,
2523
- })
2518
+ sinon.match.hasNested('rtcMetrics.webex', webex)
2524
2519
  );
2520
+
2521
+ window.setInterval = setIntervalOriginal;
2525
2522
  });
2526
2523
 
2527
2524
  it('should pass the turn server info to the peer connection', async () => {
@@ -1,11 +0,0 @@
1
- "use strict";
2
-
3
- var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
4
- _Object$defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.default = void 0;
8
- var RTC_METRICS = exports.default = {
9
- APP_ID: 'FFB51ED5-4319-4C55-8303-B1F2FCCDE231'
10
- };
11
- //# sourceMappingURL=constants.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["RTC_METRICS","exports","default","APP_ID"],"sources":["constants.ts"],"sourcesContent":["const RTC_METRICS = {APP_ID: 'FFB51ED5-4319-4C55-8303-B1F2FCCDE231'};\n\nexport {RTC_METRICS as default};\n"],"mappings":";;;;;;;AAAA,IAAMA,WAAW,GAAAC,OAAA,CAAAC,OAAA,GAAG;EAACC,MAAM,EAAE;AAAsC,CAAC"}
@@ -1,197 +0,0 @@
1
- "use strict";
2
-
3
- var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
4
- var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
5
- _Object$defineProperty(exports, "__esModule", {
6
- value: true
7
- });
8
- exports.default = void 0;
9
- var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
10
- var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
11
- var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
12
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
13
- var _internalPluginMetrics = require("@webex/internal-plugin-metrics");
14
- var _uuid = _interopRequireDefault(require("uuid"));
15
- var _constants = _interopRequireDefault(require("./constants"));
16
- /* eslint-disable class-methods-use-this */
17
-
18
- var parseJsonPayload = function parseJsonPayload(payload) {
19
- try {
20
- if (payload && payload[0]) {
21
- return JSON.parse(payload[0]);
22
- }
23
- return null;
24
- } catch (_) {
25
- return null;
26
- }
27
- };
28
-
29
- /**
30
- * Rtc Metrics
31
- */
32
- var RtcMetrics = exports.default = /*#__PURE__*/function () {
33
- /**
34
- * Initialize the interval.
35
- *
36
- * @param {object} webex - The main `webex` object.
37
- * @param {string} meetingId - The meeting id.
38
- * @param {string} correlationId - The correlation id.
39
- */
40
- function RtcMetrics(webex, meetingId, correlationId) {
41
- (0, _classCallCheck2.default)(this, RtcMetrics);
42
- /**
43
- * Array of MetricData items to be sent to the metrics service.
44
- */
45
- (0, _defineProperty2.default)(this, "metricsQueue", []);
46
- (0, _defineProperty2.default)(this, "intervalId", void 0);
47
- (0, _defineProperty2.default)(this, "webex", void 0);
48
- (0, _defineProperty2.default)(this, "meetingId", void 0);
49
- (0, _defineProperty2.default)(this, "correlationId", void 0);
50
- (0, _defineProperty2.default)(this, "connectionId", void 0);
51
- (0, _defineProperty2.default)(this, "shouldSendMetricsOnNextStatsReport", void 0);
52
- // `window` is used to prevent typescript from returning a NodeJS.Timer.
53
- this.intervalId = window.setInterval(this.sendMetricsInQueue.bind(this), 30 * 1000);
54
- this.meetingId = meetingId;
55
- this.webex = webex;
56
- this.correlationId = correlationId;
57
- this.resetConnection();
58
- }
59
-
60
- /**
61
- * Check to see if the metrics queue has any items.
62
- *
63
- * @returns {void}
64
- */
65
- (0, _createClass2.default)(RtcMetrics, [{
66
- key: "sendMetricsInQueue",
67
- value: function sendMetricsInQueue() {
68
- if (this.metricsQueue.length) {
69
- this.sendMetrics();
70
- this.metricsQueue = [];
71
- }
72
- }
73
-
74
- /**
75
- * Forces sending metrics when we get the next stats-report
76
- *
77
- * This is useful for cases when something important happens that affects the media connection,
78
- * for example when we move from lobby into the meeting.
79
- *
80
- * @returns {void}
81
- */
82
- }, {
83
- key: "sendNextMetrics",
84
- value: function sendNextMetrics() {
85
- this.shouldSendMetricsOnNextStatsReport = true;
86
- }
87
-
88
- /**
89
- * Add metrics items to the metrics queue.
90
- *
91
- * @param {object} data - An object with a payload array of metrics items.
92
- *
93
- * @returns {void}
94
- */
95
- }, {
96
- key: "addMetrics",
97
- value: function addMetrics(data) {
98
- if (data.payload.length) {
99
- if (data.name === 'stats-report') {
100
- data.payload = data.payload.map(this.anonymizeIp);
101
- }
102
- this.metricsQueue.push(data);
103
- if (this.shouldSendMetricsOnNextStatsReport && data.name === 'stats-report') {
104
- // this is the first useful set of data (WCME gives it to us after 5s), send it out immediately
105
- // in case the user is unhappy and closes the browser early
106
- this.sendMetricsInQueue();
107
- this.shouldSendMetricsOnNextStatsReport = false;
108
- }
109
- try {
110
- // If a connection fails, send the rest of the metrics in queue and get a new connection id.
111
- var parsedPayload = parseJsonPayload(data.payload);
112
- if (data.name === 'onconnectionstatechange' && parsedPayload && parsedPayload.value === 'failed') {
113
- this.sendMetricsInQueue();
114
- this.resetConnection();
115
- }
116
- } catch (e) {
117
- console.error(e);
118
- }
119
- }
120
- }
121
-
122
- /**
123
- * Clear the metrics interval.
124
- *
125
- * @returns {void}
126
- */
127
- }, {
128
- key: "closeMetrics",
129
- value: function closeMetrics() {
130
- this.sendMetricsInQueue();
131
- clearInterval(this.intervalId);
132
- }
133
-
134
- /**
135
- * Anonymize IP addresses.
136
- *
137
- * @param {array} stats - An RTCStatsReport organized into an array of strings.
138
- * @returns {string}
139
- */
140
- }, {
141
- key: "anonymizeIp",
142
- value: function anonymizeIp(stats) {
143
- var data = JSON.parse(stats);
144
- // on local and remote candidates, anonymize the last 4 bits.
145
- if (data.type === 'local-candidate' || data.type === 'remote-candidate') {
146
- data.ip = _internalPluginMetrics.CallDiagnosticUtils.anonymizeIPAddress(data.ip) || undefined;
147
- data.address = _internalPluginMetrics.CallDiagnosticUtils.anonymizeIPAddress(data.address) || undefined;
148
- data.relatedAddress = _internalPluginMetrics.CallDiagnosticUtils.anonymizeIPAddress(data.relatedAddress) || undefined;
149
- }
150
- return (0, _stringify.default)(data);
151
- }
152
-
153
- /**
154
- * Set a new connection id.
155
- *
156
- * @returns {void}
157
- */
158
- }, {
159
- key: "resetConnection",
160
- value: function resetConnection() {
161
- this.connectionId = _uuid.default.v4();
162
- this.shouldSendMetricsOnNextStatsReport = true;
163
- }
164
-
165
- /**
166
- * Send metrics to the metrics service.
167
- *
168
- * @returns {void}
169
- */
170
- }, {
171
- key: "sendMetrics",
172
- value: function sendMetrics() {
173
- this.webex.request({
174
- method: 'POST',
175
- service: 'unifiedTelemetry',
176
- resource: 'metric/v2',
177
- headers: {
178
- type: 'webrtcMedia',
179
- appId: _constants.default.APP_ID
180
- },
181
- body: {
182
- metrics: [{
183
- type: 'webrtc',
184
- version: '1.1.0',
185
- userId: this.webex.internal.device.userId,
186
- meetingId: this.meetingId,
187
- correlationId: this.correlationId,
188
- connectionId: this.connectionId,
189
- data: this.metricsQueue
190
- }]
191
- }
192
- });
193
- }
194
- }]);
195
- return RtcMetrics;
196
- }();
197
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
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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"}
@@ -1,4 +0,0 @@
1
- declare const RTC_METRICS: {
2
- APP_ID: string;
3
- };
4
- export { RTC_METRICS as default };
@@ -1,71 +0,0 @@
1
- /**
2
- * Rtc Metrics
3
- */
4
- export default class RtcMetrics {
5
- /**
6
- * Array of MetricData items to be sent to the metrics service.
7
- */
8
- metricsQueue: any[];
9
- intervalId: number;
10
- webex: any;
11
- meetingId: string;
12
- correlationId: string;
13
- connectionId: string;
14
- shouldSendMetricsOnNextStatsReport: boolean;
15
- /**
16
- * Initialize the interval.
17
- *
18
- * @param {object} webex - The main `webex` object.
19
- * @param {string} meetingId - The meeting id.
20
- * @param {string} correlationId - The correlation id.
21
- */
22
- constructor(webex: any, meetingId: any, correlationId: any);
23
- /**
24
- * Check to see if the metrics queue has any items.
25
- *
26
- * @returns {void}
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;
38
- /**
39
- * Add metrics items to the metrics queue.
40
- *
41
- * @param {object} data - An object with a payload array of metrics items.
42
- *
43
- * @returns {void}
44
- */
45
- addMetrics(data: any): void;
46
- /**
47
- * Clear the metrics interval.
48
- *
49
- * @returns {void}
50
- */
51
- closeMetrics(): void;
52
- /**
53
- * Anonymize IP addresses.
54
- *
55
- * @param {array} stats - An RTCStatsReport organized into an array of strings.
56
- * @returns {string}
57
- */
58
- anonymizeIp(stats: string): string;
59
- /**
60
- * Set a new connection id.
61
- *
62
- * @returns {void}
63
- */
64
- private resetConnection;
65
- /**
66
- * Send metrics to the metrics service.
67
- *
68
- * @returns {void}
69
- */
70
- private sendMetrics;
71
- }
@@ -1,3 +0,0 @@
1
- const RTC_METRICS = {APP_ID: 'FFB51ED5-4319-4C55-8303-B1F2FCCDE231'};
2
-
3
- export {RTC_METRICS as default};
@@ -1,186 +0,0 @@
1
- /* eslint-disable class-methods-use-this */
2
- import {CallDiagnosticUtils} from '@webex/internal-plugin-metrics';
3
- import uuid from 'uuid';
4
- import RTC_METRICS from './constants';
5
-
6
- const parseJsonPayload = (payload: any[]): any | null => {
7
- try {
8
- if (payload && payload[0]) {
9
- return JSON.parse(payload[0]);
10
- }
11
-
12
- return null;
13
- } catch (_) {
14
- return null;
15
- }
16
- };
17
-
18
- /**
19
- * Rtc Metrics
20
- */
21
- export default class RtcMetrics {
22
- /**
23
- * Array of MetricData items to be sent to the metrics service.
24
- */
25
- metricsQueue = [];
26
-
27
- intervalId: number;
28
-
29
- webex: any;
30
-
31
- meetingId: string;
32
-
33
- correlationId: string;
34
-
35
- connectionId: string;
36
-
37
- shouldSendMetricsOnNextStatsReport: boolean;
38
-
39
- /**
40
- * Initialize the interval.
41
- *
42
- * @param {object} webex - The main `webex` object.
43
- * @param {string} meetingId - The meeting id.
44
- * @param {string} correlationId - The correlation id.
45
- */
46
- constructor(webex, meetingId, correlationId) {
47
- // `window` is used to prevent typescript from returning a NodeJS.Timer.
48
- this.intervalId = window.setInterval(this.sendMetricsInQueue.bind(this), 30 * 1000);
49
- this.meetingId = meetingId;
50
- this.webex = webex;
51
- this.correlationId = correlationId;
52
- this.resetConnection();
53
- }
54
-
55
- /**
56
- * Check to see if the metrics queue has any items.
57
- *
58
- * @returns {void}
59
- */
60
- public sendMetricsInQueue() {
61
- if (this.metricsQueue.length) {
62
- this.sendMetrics();
63
- this.metricsQueue = [];
64
- }
65
- }
66
-
67
- /**
68
- * Forces sending metrics when we get the next stats-report
69
- *
70
- * This is useful for cases when something important happens that affects the media connection,
71
- * for example when we move from lobby into the meeting.
72
- *
73
- * @returns {void}
74
- */
75
- public sendNextMetrics() {
76
- this.shouldSendMetricsOnNextStatsReport = true;
77
- }
78
-
79
- /**
80
- * Add metrics items to the metrics queue.
81
- *
82
- * @param {object} data - An object with a payload array of metrics items.
83
- *
84
- * @returns {void}
85
- */
86
- addMetrics(data) {
87
- if (data.payload.length) {
88
- if (data.name === 'stats-report') {
89
- data.payload = data.payload.map(this.anonymizeIp);
90
- }
91
-
92
- this.metricsQueue.push(data);
93
-
94
- if (this.shouldSendMetricsOnNextStatsReport && data.name === 'stats-report') {
95
- // this is the first useful set of data (WCME gives it to us after 5s), send it out immediately
96
- // in case the user is unhappy and closes the browser early
97
- this.sendMetricsInQueue();
98
- this.shouldSendMetricsOnNextStatsReport = false;
99
- }
100
-
101
- try {
102
- // If a connection fails, send the rest of the metrics in queue and get a new connection id.
103
- const parsedPayload = parseJsonPayload(data.payload);
104
- if (
105
- data.name === 'onconnectionstatechange' &&
106
- parsedPayload &&
107
- parsedPayload.value === 'failed'
108
- ) {
109
- this.sendMetricsInQueue();
110
- this.resetConnection();
111
- }
112
- } catch (e) {
113
- console.error(e);
114
- }
115
- }
116
- }
117
-
118
- /**
119
- * Clear the metrics interval.
120
- *
121
- * @returns {void}
122
- */
123
- closeMetrics() {
124
- this.sendMetricsInQueue();
125
- clearInterval(this.intervalId);
126
- }
127
-
128
- /**
129
- * Anonymize IP addresses.
130
- *
131
- * @param {array} stats - An RTCStatsReport organized into an array of strings.
132
- * @returns {string}
133
- */
134
- anonymizeIp(stats: string): string {
135
- const data = JSON.parse(stats);
136
- // on local and remote candidates, anonymize the last 4 bits.
137
- if (data.type === 'local-candidate' || data.type === 'remote-candidate') {
138
- data.ip = CallDiagnosticUtils.anonymizeIPAddress(data.ip) || undefined;
139
- data.address = CallDiagnosticUtils.anonymizeIPAddress(data.address) || undefined;
140
- data.relatedAddress =
141
- CallDiagnosticUtils.anonymizeIPAddress(data.relatedAddress) || undefined;
142
- }
143
-
144
- return JSON.stringify(data);
145
- }
146
-
147
- /**
148
- * Set a new connection id.
149
- *
150
- * @returns {void}
151
- */
152
- private resetConnection() {
153
- this.connectionId = uuid.v4();
154
- this.shouldSendMetricsOnNextStatsReport = true;
155
- }
156
-
157
- /**
158
- * Send metrics to the metrics service.
159
- *
160
- * @returns {void}
161
- */
162
- private sendMetrics() {
163
- this.webex.request({
164
- method: 'POST',
165
- service: 'unifiedTelemetry',
166
- resource: 'metric/v2',
167
- headers: {
168
- type: 'webrtcMedia',
169
- appId: RTC_METRICS.APP_ID,
170
- },
171
- body: {
172
- metrics: [
173
- {
174
- type: 'webrtc',
175
- version: '1.1.0',
176
- userId: this.webex.internal.device.userId,
177
- meetingId: this.meetingId,
178
- correlationId: this.correlationId,
179
- connectionId: this.connectionId,
180
- data: this.metricsQueue,
181
- },
182
- ],
183
- },
184
- });
185
- }
186
- }