@webex/internal-plugin-metrics 3.3.1 → 3.4.0-next.2
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/behavioral-metrics.js +63 -0
- package/dist/behavioral-metrics.js.map +1 -0
- package/dist/business-metrics.js +62 -0
- package/dist/business-metrics.js.map +1 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.js +3 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js +14 -11
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
- package/dist/call-diagnostic/config.js +19 -13
- package/dist/call-diagnostic/config.js.map +1 -1
- package/dist/generic-metrics.js +184 -0
- package/dist/generic-metrics.js.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -1
- package/dist/metrics.js +1 -1
- package/dist/metrics.types.js.map +1 -1
- package/dist/new-metrics.js +116 -23
- package/dist/new-metrics.js.map +1 -1
- package/dist/operational-metrics.js +56 -0
- package/dist/operational-metrics.js.map +1 -0
- package/dist/types/behavioral-metrics.d.ts +25 -0
- package/dist/types/business-metrics.d.ts +19 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +2 -2
- package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +3 -2
- package/dist/types/call-diagnostic/config.d.ts +2 -0
- package/dist/types/generic-metrics.d.ts +63 -0
- package/dist/types/index.d.ts +4 -1
- package/dist/types/metrics.types.d.ts +47 -15
- package/dist/types/new-metrics.d.ts +39 -11
- package/dist/types/operational-metrics.d.ts +19 -0
- package/package.json +11 -11
- package/src/behavioral-metrics.ts +40 -0
- package/src/business-metrics.ts +30 -0
- package/src/call-diagnostic/call-diagnostic-metrics.ts +3 -0
- package/src/call-diagnostic/call-diagnostic-metrics.util.ts +16 -17
- package/src/call-diagnostic/config.ts +9 -2
- package/src/generic-metrics.ts +146 -0
- package/src/index.ts +6 -0
- package/src/metrics.types.ts +82 -18
- package/src/new-metrics.ts +95 -18
- package/src/operational-metrics.ts +24 -0
- package/test/unit/spec/behavioral/behavioral-metrics.ts +205 -0
- package/test/unit/spec/business/business-metrics.ts +120 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +48 -52
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +1 -1
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +9 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +41 -22
- package/test/unit/spec/operational/operational-metrics.ts +115 -0
- package/test/unit/spec/prelogin-metrics-batcher.ts +1 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import sinon from 'sinon';
|
|
2
|
+
import {assert} from '@webex/test-helper-chai';
|
|
3
|
+
import {BrowserDetection} from '@webex/common';
|
|
4
|
+
import {BehavioralMetrics, config, getOSNameInternal} from '@webex/internal-plugin-metrics';
|
|
5
|
+
import uuid from 'uuid';
|
|
6
|
+
import {merge} from 'lodash';
|
|
7
|
+
|
|
8
|
+
//@ts-ignore
|
|
9
|
+
global.window = {location: {hostname: 'whatever'}, navigator: {language: 'language'}};
|
|
10
|
+
process.env.NODE_ENV = 'test';
|
|
11
|
+
|
|
12
|
+
const {getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
|
|
13
|
+
|
|
14
|
+
describe('internal-plugin-metrics', () => {
|
|
15
|
+
describe('BehavioralMetrics', () => {
|
|
16
|
+
let webex;
|
|
17
|
+
let now;
|
|
18
|
+
let behavioralMetrics: BehavioralMetrics;
|
|
19
|
+
|
|
20
|
+
const tags = {key: 'val'};
|
|
21
|
+
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
now = new Date();
|
|
24
|
+
|
|
25
|
+
webex = {
|
|
26
|
+
canAuthorize: true,
|
|
27
|
+
version: 'webex-version',
|
|
28
|
+
internal: {
|
|
29
|
+
services: {
|
|
30
|
+
get: () => 'locus-url',
|
|
31
|
+
},
|
|
32
|
+
metrics: {
|
|
33
|
+
submitClientMetrics: sinon.stub(),
|
|
34
|
+
config: {...config.metrics},
|
|
35
|
+
},
|
|
36
|
+
newMetrics: {},
|
|
37
|
+
device: {
|
|
38
|
+
userId: 'userId',
|
|
39
|
+
url: 'https://wdm-intb.ciscospark.com/wdm/api/v1/devices/deviceId',
|
|
40
|
+
orgId: 'orgId',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
meetings: {
|
|
44
|
+
config: {
|
|
45
|
+
metrics: {
|
|
46
|
+
clientType: 'TEAMS_CLIENT',
|
|
47
|
+
subClientType: 'WEB_APP',
|
|
48
|
+
clientName: 'Cantina',
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
geoHintInfo: {
|
|
52
|
+
clientAddress: '1.3.4.5',
|
|
53
|
+
countryCode: 'UK',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
credentials: {
|
|
57
|
+
isUnverifiedGuest: false,
|
|
58
|
+
},
|
|
59
|
+
prepareFetchOptions: sinon.stub().callsFake((opts: any) => ({...opts, foo: 'bar'})),
|
|
60
|
+
request: sinon.stub().resolves({body: {}}),
|
|
61
|
+
logger: {
|
|
62
|
+
log: sinon.stub(),
|
|
63
|
+
error: sinon.stub(),
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
sinon.createSandbox();
|
|
68
|
+
sinon.useFakeTimers(now.getTime());
|
|
69
|
+
behavioralMetrics = new BehavioralMetrics({}, {parent: webex});
|
|
70
|
+
sinon.stub(uuid, 'v4').returns('my-fake-id');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
afterEach(() => {
|
|
74
|
+
sinon.restore();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('#sendEvent', () => {
|
|
78
|
+
it('should send correctly shaped behavioral event (check name building and internal tagged event building)', () => {
|
|
79
|
+
// For some reasons `jest` isn't available when testing form build server - so can't use `jest.fn()` here...
|
|
80
|
+
const requestCalls = [];
|
|
81
|
+
const request = function(arg) { requestCalls.push(arg) }
|
|
82
|
+
|
|
83
|
+
behavioralMetrics.clientMetricsBatcher.request = request;
|
|
84
|
+
|
|
85
|
+
assert.equal(requestCalls.length, 0)
|
|
86
|
+
behavioralMetrics.submitBehavioralEvent({ product: "webex", agent: "user", target: "foo", verb: "get", payload: {bar:"gee"} })
|
|
87
|
+
assert.equal(requestCalls.length, 1)
|
|
88
|
+
assert.deepEqual(requestCalls[0], {
|
|
89
|
+
context: {
|
|
90
|
+
app: {version: 'webex-version'},
|
|
91
|
+
device: {id: 'deviceId'},
|
|
92
|
+
locale: 'language',
|
|
93
|
+
os: {
|
|
94
|
+
name: getOSNameInternal(),
|
|
95
|
+
version: getOSVersion(),
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
metricName: 'webex.user.foo.get',
|
|
99
|
+
tags: {
|
|
100
|
+
browser: getBrowserName(),
|
|
101
|
+
browserHeight: window.innerHeight,
|
|
102
|
+
browserVersion: getBrowserVersion(),
|
|
103
|
+
browserWidth: window.innerWidth,
|
|
104
|
+
domain: window.location.hostname,
|
|
105
|
+
inIframe: false,
|
|
106
|
+
locale: window.navigator.language,
|
|
107
|
+
os: getOSNameInternal(),
|
|
108
|
+
bar:"gee"
|
|
109
|
+
},
|
|
110
|
+
timestamp: requestCalls[0].timestamp, // This is to bypass time check, which is correctly tested below.
|
|
111
|
+
type: ['behavioral'],
|
|
112
|
+
});
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
describe('#getContext', () => {
|
|
117
|
+
it('should build context correctly', () => {
|
|
118
|
+
const res = behavioralMetrics.getContext();
|
|
119
|
+
|
|
120
|
+
assert.deepEqual(res, {
|
|
121
|
+
app: {
|
|
122
|
+
version: 'webex-version',
|
|
123
|
+
},
|
|
124
|
+
device: {
|
|
125
|
+
id: 'deviceId',
|
|
126
|
+
},
|
|
127
|
+
locale: 'language',
|
|
128
|
+
os: {
|
|
129
|
+
name: getOSNameInternal(),
|
|
130
|
+
version: getOSVersion(),
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
describe('#getDefaultTags', () => {
|
|
137
|
+
it('should build tags correctly', () => {
|
|
138
|
+
const res = behavioralMetrics.getBrowserDetails();
|
|
139
|
+
|
|
140
|
+
assert.deepEqual(res, {
|
|
141
|
+
browser: getBrowserName(),
|
|
142
|
+
browserHeight: window.innerHeight,
|
|
143
|
+
browserVersion: getBrowserVersion(),
|
|
144
|
+
browserWidth: window.innerWidth,
|
|
145
|
+
domain: window.location.hostname,
|
|
146
|
+
inIframe: false,
|
|
147
|
+
locale: window.navigator.language,
|
|
148
|
+
os: getOSNameInternal(),
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe('#isReadyToSubmitEvents', () => {
|
|
154
|
+
it('should return true when we have a deviceId, false when deviceId is empty or undefined', async () => {
|
|
155
|
+
let deviceIdUrl = webex.internal.device.url;
|
|
156
|
+
|
|
157
|
+
// testing case w/o device id url first, as the internal deviceId cache would bypass that flow.
|
|
158
|
+
webex.internal.device.url = "";
|
|
159
|
+
assert.equal(false, behavioralMetrics.isReadyToSubmitEvents());
|
|
160
|
+
|
|
161
|
+
delete webex.internal.device.url;
|
|
162
|
+
assert.equal(false, behavioralMetrics.isReadyToSubmitEvents());
|
|
163
|
+
|
|
164
|
+
webex.internal.device.url = deviceIdUrl;
|
|
165
|
+
assert.equal(true, behavioralMetrics.isReadyToSubmitEvents());
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
describe('#createEventObject', () => {
|
|
170
|
+
it('should build event object correctly', async () => {
|
|
171
|
+
const res = behavioralMetrics.createTaggedEventObject({
|
|
172
|
+
type:['behavioral'],
|
|
173
|
+
name:'webex.user.target.create',
|
|
174
|
+
payload: tags,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
assert.deepEqual(res, {
|
|
178
|
+
context: {
|
|
179
|
+
app: {
|
|
180
|
+
version: 'webex-version',
|
|
181
|
+
},
|
|
182
|
+
device: {
|
|
183
|
+
id: 'deviceId',
|
|
184
|
+
},
|
|
185
|
+
locale: 'language',
|
|
186
|
+
os: {
|
|
187
|
+
name: getOSNameInternal(),
|
|
188
|
+
version: getOSVersion(),
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
metricName: 'webex.user.target.create',
|
|
192
|
+
tags: merge(tags, {
|
|
193
|
+
browser: getBrowserName(),
|
|
194
|
+
browserVersion: getBrowserVersion(),
|
|
195
|
+
domain: window.location.hostname,
|
|
196
|
+
locale: window.navigator.language,
|
|
197
|
+
os: getOSNameInternal(),
|
|
198
|
+
}),
|
|
199
|
+
timestamp: res.timestamp,
|
|
200
|
+
type: ['behavioral'],
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
});
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import sinon from 'sinon';
|
|
2
|
+
import {assert} from '@webex/test-helper-chai';
|
|
3
|
+
import {BrowserDetection} from '@webex/common';
|
|
4
|
+
import {BusinessMetrics, config, getOSNameInternal} from '@webex/internal-plugin-metrics';
|
|
5
|
+
import uuid from 'uuid';
|
|
6
|
+
|
|
7
|
+
//@ts-ignore
|
|
8
|
+
global.window = {location: {hostname: 'whatever'}, navigator: {language: 'language'}};
|
|
9
|
+
process.env.NODE_ENV = 'test';
|
|
10
|
+
|
|
11
|
+
const {getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
|
|
12
|
+
|
|
13
|
+
describe('internal-plugin-metrics', () => {
|
|
14
|
+
describe('BusinessMetrics', () => {
|
|
15
|
+
let webex;
|
|
16
|
+
let now;
|
|
17
|
+
let businessMetrics: BusinessMetrics;
|
|
18
|
+
|
|
19
|
+
const tags = {key: 'val'};
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
now = new Date();
|
|
23
|
+
|
|
24
|
+
webex = {
|
|
25
|
+
canAuthorize: true,
|
|
26
|
+
version: 'webex-version',
|
|
27
|
+
internal: {
|
|
28
|
+
services: {
|
|
29
|
+
get: () => 'locus-url',
|
|
30
|
+
},
|
|
31
|
+
metrics: {
|
|
32
|
+
submitClientMetrics: sinon.stub(),
|
|
33
|
+
config: {...config.metrics},
|
|
34
|
+
},
|
|
35
|
+
newMetrics: {},
|
|
36
|
+
device: {
|
|
37
|
+
userId: 'userId',
|
|
38
|
+
url: 'https://wdm-intb.ciscospark.com/wdm/api/v1/devices/deviceId',
|
|
39
|
+
orgId: 'orgId',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
meetings: {
|
|
43
|
+
config: {
|
|
44
|
+
metrics: {
|
|
45
|
+
clientType: 'TEAMS_CLIENT',
|
|
46
|
+
subClientType: 'WEB_APP',
|
|
47
|
+
clientName: 'Cantina',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
geoHintInfo: {
|
|
51
|
+
clientAddress: '1.3.4.5',
|
|
52
|
+
countryCode: 'UK',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
credentials: {
|
|
56
|
+
isUnverifiedGuest: false,
|
|
57
|
+
},
|
|
58
|
+
prepareFetchOptions: sinon.stub().callsFake((opts: any) => ({...opts, foo: 'bar'})),
|
|
59
|
+
request: sinon.stub().resolves({body: {}}),
|
|
60
|
+
logger: {
|
|
61
|
+
log: sinon.stub(),
|
|
62
|
+
error: sinon.stub(),
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
sinon.createSandbox();
|
|
67
|
+
sinon.useFakeTimers(now.getTime());
|
|
68
|
+
businessMetrics = new BusinessMetrics({}, {parent: webex});
|
|
69
|
+
sinon.stub(uuid, 'v4').returns('my-fake-id');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
afterEach(() => {
|
|
73
|
+
sinon.restore();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe('#sendEvent', () => {
|
|
77
|
+
it('should send correctly shaped business event (check name building and internal tagged event building)', () => {
|
|
78
|
+
// For some reasons `jest` isn't available when testing form build server - so can't use `jest.fn()` here...
|
|
79
|
+
const requestCalls = [];
|
|
80
|
+
const request = function(arg) { requestCalls.push(arg) }
|
|
81
|
+
|
|
82
|
+
businessMetrics.clientMetricsBatcher.request = request;
|
|
83
|
+
|
|
84
|
+
assert.equal(requestCalls.length, 0)
|
|
85
|
+
businessMetrics.submitBusinessEvent({ name: "foobar", payload: {bar:"gee"} })
|
|
86
|
+
assert.equal(requestCalls.length, 1)
|
|
87
|
+
assert.deepEqual(requestCalls[0], {
|
|
88
|
+
eventPayload: {
|
|
89
|
+
context: {
|
|
90
|
+
app: {version: 'webex-version'},
|
|
91
|
+
device: {id: 'deviceId'},
|
|
92
|
+
locale: 'language',
|
|
93
|
+
os: {
|
|
94
|
+
name: getOSNameInternal(),
|
|
95
|
+
version: getOSVersion(),
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
metricName: 'foobar',
|
|
99
|
+
browserDetails: {
|
|
100
|
+
browser: getBrowserName(),
|
|
101
|
+
browserHeight: window.innerHeight,
|
|
102
|
+
browserVersion: getBrowserVersion(),
|
|
103
|
+
browserWidth: window.innerWidth,
|
|
104
|
+
domain: window.location.hostname,
|
|
105
|
+
inIframe: false,
|
|
106
|
+
locale: window.navigator.language,
|
|
107
|
+
os: getOSNameInternal(),
|
|
108
|
+
},
|
|
109
|
+
timestamp: requestCalls[0].eventPayload.timestamp, // This is to bypass time check, which is checked below.
|
|
110
|
+
value: {
|
|
111
|
+
bar: "gee"
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
type: ['business'],
|
|
115
|
+
});
|
|
116
|
+
assert.isNumber(requestCalls[0].eventPayload.timestamp)
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -248,9 +248,15 @@ describe('plugin-metrics', () => {
|
|
|
248
248
|
});
|
|
249
249
|
|
|
250
250
|
it('appends the correct join times to the request for client.media.rx.start', async () => {
|
|
251
|
-
webex.internal.newMetrics.callDiagnosticLatencies.
|
|
251
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getLocalSDPGenRemoteSDPRecv = sinon
|
|
252
|
+
.stub()
|
|
253
|
+
.returns(5);
|
|
254
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getAudioJoinRespRxStart = sinon
|
|
252
255
|
.stub()
|
|
253
256
|
.returns(10);
|
|
257
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getVideoJoinRespRxStart = sinon
|
|
258
|
+
.stub()
|
|
259
|
+
.returns(20);
|
|
254
260
|
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
255
261
|
//@ts-ignore
|
|
256
262
|
{event: {name: 'client.media.rx.start'}}
|
|
@@ -265,7 +271,13 @@ describe('plugin-metrics', () => {
|
|
|
265
271
|
assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
|
|
266
272
|
name: 'client.media.rx.start',
|
|
267
273
|
joinTimes: {
|
|
268
|
-
localSDPGenRemoteSDPRecv:
|
|
274
|
+
localSDPGenRemoteSDPRecv: 5,
|
|
275
|
+
},
|
|
276
|
+
audioSetupDelay: {
|
|
277
|
+
joinRespRxStart: 10,
|
|
278
|
+
},
|
|
279
|
+
videoSetupDelay: {
|
|
280
|
+
joinRespRxStart: 20,
|
|
269
281
|
},
|
|
270
282
|
});
|
|
271
283
|
assert.lengthOf(
|
|
@@ -274,19 +286,16 @@ describe('plugin-metrics', () => {
|
|
|
274
286
|
);
|
|
275
287
|
});
|
|
276
288
|
|
|
277
|
-
it('appends the correct join times to the request for client.media
|
|
278
|
-
webex.internal.newMetrics.callDiagnosticLatencies.
|
|
279
|
-
.stub()
|
|
280
|
-
.returns(10);
|
|
281
|
-
webex.internal.newMetrics.callDiagnosticLatencies.getInterstitialToMediaOKJMT = sinon
|
|
289
|
+
it('appends the correct join times to the request for client.media.tx.start', async () => {
|
|
290
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getAudioJoinRespTxStart = sinon
|
|
282
291
|
.stub()
|
|
283
292
|
.returns(10);
|
|
284
|
-
webex.internal.newMetrics.callDiagnosticLatencies.
|
|
293
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getVideoJoinRespTxStart = sinon
|
|
285
294
|
.stub()
|
|
286
|
-
.returns(
|
|
295
|
+
.returns(20);
|
|
287
296
|
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
288
297
|
//@ts-ignore
|
|
289
|
-
{event: {name: 'client.media
|
|
298
|
+
{event: {name: 'client.media.tx.start'}}
|
|
290
299
|
);
|
|
291
300
|
await flushPromises();
|
|
292
301
|
clock.tick(config.metrics.batcherWait);
|
|
@@ -296,12 +305,12 @@ describe('plugin-metrics', () => {
|
|
|
296
305
|
//@ts-ignore
|
|
297
306
|
assert.calledOnce(webex.request);
|
|
298
307
|
assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
|
|
299
|
-
name: 'client.media
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
308
|
+
name: 'client.media.tx.start',
|
|
309
|
+
audioSetupDelay: {
|
|
310
|
+
joinRespTxStart: 10,
|
|
311
|
+
},
|
|
312
|
+
videoSetupDelay: {
|
|
313
|
+
joinRespTxStart: 20,
|
|
305
314
|
},
|
|
306
315
|
});
|
|
307
316
|
assert.lengthOf(
|
|
@@ -310,13 +319,28 @@ describe('plugin-metrics', () => {
|
|
|
310
319
|
);
|
|
311
320
|
});
|
|
312
321
|
|
|
313
|
-
it('appends the correct
|
|
322
|
+
it('appends the correct join times to the request for client.media-engine.ready', async () => {
|
|
314
323
|
webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon
|
|
315
324
|
.stub()
|
|
316
325
|
.returns(10);
|
|
326
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getInterstitialToMediaOKJMT = sinon
|
|
327
|
+
.stub()
|
|
328
|
+
.returns(22);
|
|
329
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitial = sinon
|
|
330
|
+
.stub()
|
|
331
|
+
.returns(35);
|
|
332
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getInterstitialToJoinOK = sinon
|
|
333
|
+
.stub()
|
|
334
|
+
.returns(5);
|
|
335
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getInterstitialToJoinOK = sinon
|
|
336
|
+
.stub()
|
|
337
|
+
.returns(7);
|
|
338
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getStayLobbyTime = sinon
|
|
339
|
+
.stub()
|
|
340
|
+
.returns(1);
|
|
317
341
|
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
318
342
|
//@ts-ignore
|
|
319
|
-
{event: {name: 'client.
|
|
343
|
+
{event: {name: 'client.media-engine.ready'}}
|
|
320
344
|
);
|
|
321
345
|
await flushPromises();
|
|
322
346
|
clock.tick(config.metrics.batcherWait);
|
|
@@ -326,14 +350,12 @@ describe('plugin-metrics', () => {
|
|
|
326
350
|
//@ts-ignore
|
|
327
351
|
assert.calledOnce(webex.request);
|
|
328
352
|
assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
|
|
329
|
-
name: 'client.
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
joinRespRxStart: 10,
|
|
336
|
-
joinRespTxStart: 10,
|
|
353
|
+
name: 'client.media-engine.ready',
|
|
354
|
+
joinTimes: {
|
|
355
|
+
totalMediaJMT: 61,
|
|
356
|
+
interstitialToMediaOKJMT: 22,
|
|
357
|
+
callInitMediaEngineReady: 10,
|
|
358
|
+
stayLobbyTime: 1,
|
|
337
359
|
},
|
|
338
360
|
});
|
|
339
361
|
assert.lengthOf(
|
|
@@ -341,32 +363,6 @@ describe('plugin-metrics', () => {
|
|
|
341
363
|
0
|
|
342
364
|
);
|
|
343
365
|
});
|
|
344
|
-
|
|
345
|
-
it('doesnt include audioSetup and videoSetup delays for other events', async () => {
|
|
346
|
-
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
347
|
-
//@ts-ignore
|
|
348
|
-
{event: {name: 'client.alert.displayed'}}
|
|
349
|
-
);
|
|
350
|
-
await flushPromises();
|
|
351
|
-
clock.tick(config.metrics.batcherWait);
|
|
352
|
-
|
|
353
|
-
await promise;
|
|
354
|
-
|
|
355
|
-
//@ts-ignore
|
|
356
|
-
assert.calledOnce(webex.request);
|
|
357
|
-
assert.deepEqual(
|
|
358
|
-
webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event.audioSetupDelay,
|
|
359
|
-
undefined
|
|
360
|
-
);
|
|
361
|
-
assert.deepEqual(
|
|
362
|
-
webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event.videoSetupDelay,
|
|
363
|
-
undefined
|
|
364
|
-
);
|
|
365
|
-
assert.lengthOf(
|
|
366
|
-
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue,
|
|
367
|
-
0
|
|
368
|
-
);
|
|
369
|
-
});
|
|
370
366
|
});
|
|
371
367
|
|
|
372
368
|
describe('when the request fails', () => {
|
|
@@ -668,7 +668,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
668
668
|
assert.deepEqual(cdl.getInterstitialToMediaOKJMT(), 10);
|
|
669
669
|
});
|
|
670
670
|
|
|
671
|
-
|
|
671
|
+
describe('calculates getU2CTime correctly', () => {
|
|
672
672
|
it('returns undefined when no precomputed value available', () => {
|
|
673
673
|
assert.deepEqual(cdl.getU2CTime(), undefined);
|
|
674
674
|
});
|
|
@@ -1454,6 +1454,9 @@ describe('internal-plugin-metrics', () => {
|
|
|
1454
1454
|
eventData: {webClientDomain: 'whatever'},
|
|
1455
1455
|
intervals: [{}],
|
|
1456
1456
|
callingServiceType: 'LOCUS',
|
|
1457
|
+
meetingJoinInfo: {
|
|
1458
|
+
clientSignallingProtocol: 'WebRTC',
|
|
1459
|
+
},
|
|
1457
1460
|
sourceMetadata: {
|
|
1458
1461
|
applicationSoftwareType: 'webex-js-sdk',
|
|
1459
1462
|
applicationSoftwareVersion: 'webex-version',
|
|
@@ -1490,6 +1493,9 @@ describe('internal-plugin-metrics', () => {
|
|
|
1490
1493
|
eventData: {webClientDomain: 'whatever'},
|
|
1491
1494
|
intervals: [{}],
|
|
1492
1495
|
callingServiceType: 'LOCUS',
|
|
1496
|
+
meetingJoinInfo: {
|
|
1497
|
+
clientSignallingProtocol: 'WebRTC',
|
|
1498
|
+
},
|
|
1493
1499
|
sourceMetadata: {
|
|
1494
1500
|
applicationSoftwareType: 'webex-js-sdk',
|
|
1495
1501
|
applicationSoftwareVersion: 'webex-version',
|
|
@@ -1524,6 +1530,9 @@ describe('internal-plugin-metrics', () => {
|
|
|
1524
1530
|
eventData: {webClientDomain: 'whatever'},
|
|
1525
1531
|
intervals: [{}],
|
|
1526
1532
|
callingServiceType: 'LOCUS',
|
|
1533
|
+
meetingJoinInfo: {
|
|
1534
|
+
clientSignallingProtocol: 'WebRTC',
|
|
1535
|
+
},
|
|
1527
1536
|
sourceMetadata: {
|
|
1528
1537
|
applicationSoftwareType: 'webex-js-sdk',
|
|
1529
1538
|
applicationSoftwareVersion: 'webex-version',
|
|
@@ -7,6 +7,7 @@ import CallDiagnosticLatencies from '../../../../src/call-diagnostic/call-diagno
|
|
|
7
7
|
import {
|
|
8
8
|
DTLS_HANDSHAKE_FAILED_CLIENT_CODE,
|
|
9
9
|
ICE_FAILED_WITHOUT_TURN_TLS_CLIENT_CODE,
|
|
10
|
+
ICE_AND_REACHABILITY_FAILED_CLIENT_CODE,
|
|
10
11
|
ICE_FAILED_WITH_TURN_TLS_CLIENT_CODE,
|
|
11
12
|
MISSING_ROAP_ANSWER_CLIENT_CODE,
|
|
12
13
|
} from '../../../../src/call-diagnostic/config';
|
|
@@ -374,6 +375,12 @@ describe('internal-plugin-metrics', () => {
|
|
|
374
375
|
joinTimes: {
|
|
375
376
|
localSDPGenRemoteSDPRecv: undefined,
|
|
376
377
|
},
|
|
378
|
+
audioSetupDelay: {
|
|
379
|
+
joinRespRxStart: undefined,
|
|
380
|
+
},
|
|
381
|
+
videoSetupDelay: {
|
|
382
|
+
joinRespRxStart: undefined,
|
|
383
|
+
},
|
|
377
384
|
},
|
|
378
385
|
],
|
|
379
386
|
[
|
|
@@ -388,14 +395,12 @@ describe('internal-plugin-metrics', () => {
|
|
|
388
395
|
},
|
|
389
396
|
],
|
|
390
397
|
[
|
|
391
|
-
'client.
|
|
398
|
+
'client.media.tx.start',
|
|
392
399
|
{
|
|
393
400
|
audioSetupDelay: {
|
|
394
|
-
joinRespRxStart: undefined,
|
|
395
401
|
joinRespTxStart: undefined,
|
|
396
402
|
},
|
|
397
403
|
videoSetupDelay: {
|
|
398
|
-
joinRespRxStart: undefined,
|
|
399
404
|
joinRespTxStart: undefined,
|
|
400
405
|
},
|
|
401
406
|
},
|
|
@@ -406,20 +411,28 @@ describe('internal-plugin-metrics', () => {
|
|
|
406
411
|
});
|
|
407
412
|
});
|
|
408
413
|
|
|
409
|
-
it('
|
|
410
|
-
const
|
|
411
|
-
const markAsTestEvent = true;
|
|
412
|
-
const webClientDomain = 'https://web.webex.com';
|
|
413
|
-
|
|
414
|
-
// just submit any event
|
|
415
|
-
prepareDiagnosticMetricItem(webex, {
|
|
414
|
+
it('getBuildType returns correct value', () => {
|
|
415
|
+
const item: any = {
|
|
416
416
|
eventPayload: {
|
|
417
|
-
event: {
|
|
417
|
+
event: {
|
|
418
|
+
name: 'client.exit.app',
|
|
419
|
+
eventData: {
|
|
420
|
+
markAsTestEvent: true,
|
|
421
|
+
webClientDomain: 'https://web.webex.com'
|
|
422
|
+
}
|
|
423
|
+
},
|
|
418
424
|
},
|
|
419
425
|
type: ['diagnostic-event'],
|
|
420
|
-
}
|
|
426
|
+
};
|
|
421
427
|
|
|
422
|
-
|
|
428
|
+
// just submit any event
|
|
429
|
+
prepareDiagnosticMetricItem(webex, item);
|
|
430
|
+
assert.deepEqual(item.eventPayload.origin.buildType, 'test');
|
|
431
|
+
|
|
432
|
+
delete item.eventPayload.origin.buildType;
|
|
433
|
+
item.eventPayload.event.eventData.markAsTestEvent = false;
|
|
434
|
+
prepareDiagnosticMetricItem(webex, item);
|
|
435
|
+
assert.deepEqual(item.eventPayload.origin.buildType, 'prod');
|
|
423
436
|
});
|
|
424
437
|
});
|
|
425
438
|
|
|
@@ -605,41 +618,47 @@ describe('internal-plugin-metrics', () => {
|
|
|
605
618
|
[
|
|
606
619
|
{
|
|
607
620
|
signalingState: 'have-local-offer',
|
|
608
|
-
|
|
621
|
+
iceConnected: false,
|
|
609
622
|
turnServerUsed: true,
|
|
610
623
|
errorCode: MISSING_ROAP_ANSWER_CLIENT_CODE,
|
|
624
|
+
unreachable: false,
|
|
611
625
|
},
|
|
612
626
|
{
|
|
613
627
|
signalingState: 'stable',
|
|
614
|
-
|
|
628
|
+
iceConnected: true,
|
|
615
629
|
turnServerUsed: true,
|
|
616
630
|
errorCode: DTLS_HANDSHAKE_FAILED_CLIENT_CODE,
|
|
631
|
+
unreachable: false,
|
|
617
632
|
},
|
|
618
633
|
{
|
|
619
634
|
signalingState: 'stable',
|
|
620
|
-
|
|
635
|
+
iceConnected: false,
|
|
621
636
|
turnServerUsed: true,
|
|
622
|
-
errorCode:
|
|
637
|
+
errorCode: ICE_FAILED_WITH_TURN_TLS_CLIENT_CODE,
|
|
638
|
+
unreachable: false,
|
|
623
639
|
},
|
|
624
640
|
{
|
|
625
641
|
signalingState: 'stable',
|
|
626
|
-
|
|
642
|
+
iceConnected: false,
|
|
627
643
|
turnServerUsed: true,
|
|
628
|
-
errorCode:
|
|
644
|
+
errorCode: ICE_AND_REACHABILITY_FAILED_CLIENT_CODE,
|
|
645
|
+
unreachable: true,
|
|
629
646
|
},
|
|
630
647
|
{
|
|
631
648
|
signalingState: 'stable',
|
|
632
|
-
|
|
649
|
+
iceConnected: false,
|
|
633
650
|
turnServerUsed: false,
|
|
634
651
|
errorCode: ICE_FAILED_WITHOUT_TURN_TLS_CLIENT_CODE,
|
|
652
|
+
unreachable: false,
|
|
635
653
|
},
|
|
636
|
-
].forEach(({signalingState,
|
|
654
|
+
].forEach(({signalingState, iceConnected, turnServerUsed, errorCode, unreachable}: any) => {
|
|
637
655
|
it('returns expected result', () => {
|
|
638
656
|
assert.deepEqual(
|
|
639
657
|
generateClientErrorCodeForIceFailure({
|
|
640
658
|
signalingState,
|
|
641
|
-
|
|
659
|
+
iceConnected,
|
|
642
660
|
turnServerUsed,
|
|
661
|
+
unreachable,
|
|
643
662
|
}),
|
|
644
663
|
errorCode
|
|
645
664
|
);
|