@webex/plugin-meetings 3.0.0-beta.364 → 3.0.0-beta.365
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/rtcMetrics/index.js +38 -1
- package/dist/rtcMetrics/index.js.map +1 -1
- package/dist/types/rtcMetrics/index.d.ts +7 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +19 -19
- package/src/rtcMetrics/index.ts +43 -1
- package/test/unit/spec/rtcMetrics/index.ts +32 -3
package/dist/breakouts/index.js
CHANGED
|
@@ -1041,7 +1041,7 @@ var Breakouts = _webexCore.WebexPlugin.extend({
|
|
|
1041
1041
|
this.trigger(_constants.BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN);
|
|
1042
1042
|
}
|
|
1043
1043
|
},
|
|
1044
|
-
version: "3.0.0-beta.
|
|
1044
|
+
version: "3.0.0-beta.365"
|
|
1045
1045
|
});
|
|
1046
1046
|
var _default = Breakouts;
|
|
1047
1047
|
exports.default = _default;
|
package/dist/rtcMetrics/index.js
CHANGED
|
@@ -11,8 +11,21 @@ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/he
|
|
|
11
11
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
|
|
12
12
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
|
|
13
13
|
var _internalPluginMetrics = require("@webex/internal-plugin-metrics");
|
|
14
|
+
var _uuid = _interopRequireDefault(require("uuid"));
|
|
14
15
|
var _constants = _interopRequireDefault(require("./constants"));
|
|
15
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
|
+
|
|
16
29
|
/**
|
|
17
30
|
* Rtc Metrics
|
|
18
31
|
*/
|
|
@@ -35,11 +48,13 @@ var RtcMetrics = /*#__PURE__*/function () {
|
|
|
35
48
|
(0, _defineProperty2.default)(this, "webex", void 0);
|
|
36
49
|
(0, _defineProperty2.default)(this, "meetingId", void 0);
|
|
37
50
|
(0, _defineProperty2.default)(this, "correlationId", void 0);
|
|
51
|
+
(0, _defineProperty2.default)(this, "connectionId", void 0);
|
|
38
52
|
// `window` is used to prevent typescript from returning a NodeJS.Timer.
|
|
39
53
|
this.intervalId = window.setInterval(this.sendMetricsInQueue.bind(this), 30 * 1000);
|
|
40
54
|
this.meetingId = meetingId;
|
|
41
55
|
this.webex = webex;
|
|
42
56
|
this.correlationId = correlationId;
|
|
57
|
+
this.setNewConnectionId();
|
|
43
58
|
// Send the first set of metrics at 5 seconds in the case of a user leaving the call shortly after joining.
|
|
44
59
|
setTimeout(this.sendMetricsInQueue.bind(this), 5 * 1000);
|
|
45
60
|
}
|
|
@@ -73,6 +88,16 @@ var RtcMetrics = /*#__PURE__*/function () {
|
|
|
73
88
|
data.payload = data.payload.map(this.anonymizeIp);
|
|
74
89
|
}
|
|
75
90
|
this.metricsQueue.push(data);
|
|
91
|
+
try {
|
|
92
|
+
// If a connection fails, send the rest of the metrics in queue and get a new connection id.
|
|
93
|
+
var parsedPayload = parseJsonPayload(data.payload);
|
|
94
|
+
if (data.name === 'onconnectionstatechange' && parsedPayload && parsedPayload.value === 'failed') {
|
|
95
|
+
this.sendMetricsInQueue();
|
|
96
|
+
this.setNewConnectionId();
|
|
97
|
+
}
|
|
98
|
+
} catch (e) {
|
|
99
|
+
console.error(e);
|
|
100
|
+
}
|
|
76
101
|
}
|
|
77
102
|
}
|
|
78
103
|
|
|
@@ -107,6 +132,17 @@ var RtcMetrics = /*#__PURE__*/function () {
|
|
|
107
132
|
return (0, _stringify.default)(data);
|
|
108
133
|
}
|
|
109
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Set a new connection id.
|
|
137
|
+
*
|
|
138
|
+
* @returns {void}
|
|
139
|
+
*/
|
|
140
|
+
}, {
|
|
141
|
+
key: "setNewConnectionId",
|
|
142
|
+
value: function setNewConnectionId() {
|
|
143
|
+
this.connectionId = _uuid.default.v4();
|
|
144
|
+
}
|
|
145
|
+
|
|
110
146
|
/**
|
|
111
147
|
* Send metrics to the metrics service.
|
|
112
148
|
*
|
|
@@ -126,10 +162,11 @@ var RtcMetrics = /*#__PURE__*/function () {
|
|
|
126
162
|
body: {
|
|
127
163
|
metrics: [{
|
|
128
164
|
type: 'webrtc',
|
|
129
|
-
version: '1.0
|
|
165
|
+
version: '1.1.0',
|
|
130
166
|
userId: this.webex.internal.device.userId,
|
|
131
167
|
meetingId: this.meetingId,
|
|
132
168
|
correlationId: this.correlationId,
|
|
169
|
+
connectionId: this.connectionId,
|
|
133
170
|
data: this.metricsQueue
|
|
134
171
|
}]
|
|
135
172
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["RtcMetrics","webex","meetingId","correlationId","intervalId","window","setInterval","sendMetricsInQueue","bind","setTimeout","metricsQueue","length","sendMetrics","data","
|
|
1
|
+
{"version":3,"names":["parseJsonPayload","payload","JSON","parse","_","RtcMetrics","webex","meetingId","correlationId","intervalId","window","setInterval","sendMetricsInQueue","bind","setNewConnectionId","setTimeout","metricsQueue","length","sendMetrics","data","name","map","anonymizeIp","push","parsedPayload","value","e","console","error","clearInterval","stats","type","ip","CallDiagnosticUtils","anonymizeIPAddress","undefined","address","relatedAddress","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 /**\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.setNewConnectionId();\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 if (data.name === 'stats-report') {\n data.payload = data.payload.map(this.anonymizeIp);\n }\n\n this.metricsQueue.push(data);\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.setNewConnectionId();\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 setNewConnectionId() {\n this.connectionId = uuid.v4();\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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"}
|
|
@@ -10,6 +10,7 @@ export default class RtcMetrics {
|
|
|
10
10
|
webex: any;
|
|
11
11
|
meetingId: string;
|
|
12
12
|
correlationId: string;
|
|
13
|
+
connectionId: string;
|
|
13
14
|
/**
|
|
14
15
|
* Initialize the interval.
|
|
15
16
|
*
|
|
@@ -45,6 +46,12 @@ export default class RtcMetrics {
|
|
|
45
46
|
* @returns {string}
|
|
46
47
|
*/
|
|
47
48
|
anonymizeIp(stats: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* Set a new connection id.
|
|
51
|
+
*
|
|
52
|
+
* @returns {void}
|
|
53
|
+
*/
|
|
54
|
+
private setNewConnectionId;
|
|
48
55
|
/**
|
|
49
56
|
* Send metrics to the metrics service.
|
|
50
57
|
*
|
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.0.0-beta.
|
|
65
|
+
version: "3.0.0-beta.365"
|
|
66
66
|
});
|
|
67
67
|
var _default = Webinar;
|
|
68
68
|
exports.default = _default;
|
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.365",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
|
|
6
6
|
"contributors": [
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@peculiar/webcrypto": "^1.4.3",
|
|
36
|
-
"@webex/plugin-meetings": "3.0.0-beta.
|
|
37
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
38
|
-
"@webex/test-helper-mocha": "3.0.0-beta.
|
|
39
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
40
|
-
"@webex/test-helper-retry": "3.0.0-beta.
|
|
41
|
-
"@webex/test-helper-test-users": "3.0.0-beta.
|
|
36
|
+
"@webex/plugin-meetings": "3.0.0-beta.365",
|
|
37
|
+
"@webex/test-helper-chai": "3.0.0-beta.365",
|
|
38
|
+
"@webex/test-helper-mocha": "3.0.0-beta.365",
|
|
39
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.365",
|
|
40
|
+
"@webex/test-helper-retry": "3.0.0-beta.365",
|
|
41
|
+
"@webex/test-helper-test-users": "3.0.0-beta.365",
|
|
42
42
|
"chai": "^4.3.4",
|
|
43
43
|
"chai-as-promised": "^7.1.1",
|
|
44
44
|
"jsdom-global": "3.0.2",
|
|
@@ -47,19 +47,19 @@
|
|
|
47
47
|
"typescript": "^4.7.4"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@webex/common": "3.0.0-beta.
|
|
50
|
+
"@webex/common": "3.0.0-beta.365",
|
|
51
51
|
"@webex/internal-media-core": "2.2.7",
|
|
52
|
-
"@webex/internal-plugin-conversation": "3.0.0-beta.
|
|
53
|
-
"@webex/internal-plugin-device": "3.0.0-beta.
|
|
54
|
-
"@webex/internal-plugin-llm": "3.0.0-beta.
|
|
55
|
-
"@webex/internal-plugin-mercury": "3.0.0-beta.
|
|
56
|
-
"@webex/internal-plugin-metrics": "3.0.0-beta.
|
|
57
|
-
"@webex/internal-plugin-support": "3.0.0-beta.
|
|
58
|
-
"@webex/internal-plugin-user": "3.0.0-beta.
|
|
59
|
-
"@webex/media-helpers": "3.0.0-beta.
|
|
60
|
-
"@webex/plugin-people": "3.0.0-beta.
|
|
61
|
-
"@webex/plugin-rooms": "3.0.0-beta.
|
|
62
|
-
"@webex/webex-core": "3.0.0-beta.
|
|
52
|
+
"@webex/internal-plugin-conversation": "3.0.0-beta.365",
|
|
53
|
+
"@webex/internal-plugin-device": "3.0.0-beta.365",
|
|
54
|
+
"@webex/internal-plugin-llm": "3.0.0-beta.365",
|
|
55
|
+
"@webex/internal-plugin-mercury": "3.0.0-beta.365",
|
|
56
|
+
"@webex/internal-plugin-metrics": "3.0.0-beta.365",
|
|
57
|
+
"@webex/internal-plugin-support": "3.0.0-beta.365",
|
|
58
|
+
"@webex/internal-plugin-user": "3.0.0-beta.365",
|
|
59
|
+
"@webex/media-helpers": "3.0.0-beta.365",
|
|
60
|
+
"@webex/plugin-people": "3.0.0-beta.365",
|
|
61
|
+
"@webex/plugin-rooms": "3.0.0-beta.365",
|
|
62
|
+
"@webex/webex-core": "3.0.0-beta.365",
|
|
63
63
|
"ampersand-collection": "^2.0.2",
|
|
64
64
|
"bowser": "^2.11.0",
|
|
65
65
|
"btoa": "^1.2.1",
|
package/src/rtcMetrics/index.ts
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
/* eslint-disable class-methods-use-this */
|
|
2
2
|
import {CallDiagnosticUtils} from '@webex/internal-plugin-metrics';
|
|
3
|
+
import uuid from 'uuid';
|
|
3
4
|
import RTC_METRICS from './constants';
|
|
4
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
|
+
|
|
5
18
|
/**
|
|
6
19
|
* Rtc Metrics
|
|
7
20
|
*/
|
|
@@ -19,6 +32,8 @@ export default class RtcMetrics {
|
|
|
19
32
|
|
|
20
33
|
correlationId: string;
|
|
21
34
|
|
|
35
|
+
connectionId: string;
|
|
36
|
+
|
|
22
37
|
/**
|
|
23
38
|
* Initialize the interval.
|
|
24
39
|
*
|
|
@@ -32,6 +47,7 @@ export default class RtcMetrics {
|
|
|
32
47
|
this.meetingId = meetingId;
|
|
33
48
|
this.webex = webex;
|
|
34
49
|
this.correlationId = correlationId;
|
|
50
|
+
this.setNewConnectionId();
|
|
35
51
|
// Send the first set of metrics at 5 seconds in the case of a user leaving the call shortly after joining.
|
|
36
52
|
setTimeout(this.sendMetricsInQueue.bind(this), 5 * 1000);
|
|
37
53
|
}
|
|
@@ -60,7 +76,23 @@ export default class RtcMetrics {
|
|
|
60
76
|
if (data.name === 'stats-report') {
|
|
61
77
|
data.payload = data.payload.map(this.anonymizeIp);
|
|
62
78
|
}
|
|
79
|
+
|
|
63
80
|
this.metricsQueue.push(data);
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
// If a connection fails, send the rest of the metrics in queue and get a new connection id.
|
|
84
|
+
const parsedPayload = parseJsonPayload(data.payload);
|
|
85
|
+
if (
|
|
86
|
+
data.name === 'onconnectionstatechange' &&
|
|
87
|
+
parsedPayload &&
|
|
88
|
+
parsedPayload.value === 'failed'
|
|
89
|
+
) {
|
|
90
|
+
this.sendMetricsInQueue();
|
|
91
|
+
this.setNewConnectionId();
|
|
92
|
+
}
|
|
93
|
+
} catch (e) {
|
|
94
|
+
console.error(e);
|
|
95
|
+
}
|
|
64
96
|
}
|
|
65
97
|
}
|
|
66
98
|
|
|
@@ -93,6 +125,15 @@ export default class RtcMetrics {
|
|
|
93
125
|
return JSON.stringify(data);
|
|
94
126
|
}
|
|
95
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Set a new connection id.
|
|
130
|
+
*
|
|
131
|
+
* @returns {void}
|
|
132
|
+
*/
|
|
133
|
+
private setNewConnectionId() {
|
|
134
|
+
this.connectionId = uuid.v4();
|
|
135
|
+
}
|
|
136
|
+
|
|
96
137
|
/**
|
|
97
138
|
* Send metrics to the metrics service.
|
|
98
139
|
*
|
|
@@ -111,10 +152,11 @@ export default class RtcMetrics {
|
|
|
111
152
|
metrics: [
|
|
112
153
|
{
|
|
113
154
|
type: 'webrtc',
|
|
114
|
-
version: '1.0
|
|
155
|
+
version: '1.1.0',
|
|
115
156
|
userId: this.webex.internal.device.userId,
|
|
116
157
|
meetingId: this.meetingId,
|
|
117
158
|
correlationId: this.correlationId,
|
|
159
|
+
connectionId: this.connectionId,
|
|
118
160
|
data: this.metricsQueue,
|
|
119
161
|
},
|
|
120
162
|
],
|
|
@@ -4,10 +4,15 @@ import {assert} from '@webex/test-helper-chai';
|
|
|
4
4
|
import sinon from 'sinon';
|
|
5
5
|
import RTC_METRICS from '../../../../src/rtcMetrics/constants';
|
|
6
6
|
|
|
7
|
-
const FAKE_METRICS_ITEM = {payload: ['fake-metrics']};
|
|
7
|
+
const FAKE_METRICS_ITEM = {payload: ['{"type":"string","value":"fake-metrics","id":""}']};
|
|
8
|
+
const FAILURE_METRICS_ITEM = {
|
|
9
|
+
name: "onconnectionstatechange",
|
|
10
|
+
payload: ['{"type":"string","value":"failed","id":""}'],
|
|
11
|
+
timestamp: 1707929986667
|
|
12
|
+
};
|
|
8
13
|
|
|
9
|
-
const STATS_WITH_IP = '{
|
|
10
|
-
const STATS_WITH_IP_RESULT = '{
|
|
14
|
+
const STATS_WITH_IP = '{"id":"RTCIceCandidate_/kQs0ZNU","type":"remote-candidate","transportId":"RTCTransport_0_1","isRemote":true,"ip":"11.22.111.255","address":"11.22.111.255","port":5004,"protocol":"udp","candidateType":"host","priority":2130706431}';
|
|
15
|
+
const STATS_WITH_IP_RESULT = '{"id":"RTCIceCandidate_/kQs0ZNU","type":"remote-candidate","transportId":"RTCTransport_0_1","isRemote":true,"ip":"11.22.111.240","address":"11.22.111.240","port":5004,"protocol":"udp","candidateType":"host","priority":2130706431}';
|
|
11
16
|
|
|
12
17
|
describe('RtcMetrics', () => {
|
|
13
18
|
let metrics: RtcMetrics;
|
|
@@ -82,6 +87,30 @@ describe('RtcMetrics', () => {
|
|
|
82
87
|
assert.callCount(webex.request, 1);
|
|
83
88
|
});
|
|
84
89
|
|
|
90
|
+
it('should clear out metrics on failure', () => {
|
|
91
|
+
assert.notCalled(webex.request);
|
|
92
|
+
|
|
93
|
+
metrics.addMetrics(FAILURE_METRICS_ITEM);
|
|
94
|
+
|
|
95
|
+
assert.callCount(webex.request, 1);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should have the same connectionId on success', () => {
|
|
99
|
+
const originalId = metrics.connectionId;
|
|
100
|
+
|
|
101
|
+
metrics.addMetrics(FAKE_METRICS_ITEM);
|
|
102
|
+
|
|
103
|
+
assert.strictEqual(originalId, metrics.connectionId);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should have a new connectionId on failure', () => {
|
|
107
|
+
const originalId = metrics.connectionId;
|
|
108
|
+
|
|
109
|
+
metrics.addMetrics(FAILURE_METRICS_ITEM);
|
|
110
|
+
|
|
111
|
+
assert.notEqual(originalId, metrics.connectionId);
|
|
112
|
+
});
|
|
113
|
+
|
|
85
114
|
it('should anonymize IP addresses', () => {
|
|
86
115
|
assert.strictEqual(metrics.anonymizeIp(STATS_WITH_IP), STATS_WITH_IP_RESULT);
|
|
87
116
|
});
|