@webex/internal-plugin-metrics 3.0.0-beta.42 → 3.0.0-beta.421
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/batcher.js +40 -1
- package/dist/batcher.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +65 -0
- package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -0
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +552 -0
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.js +863 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js +371 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -0
- package/dist/call-diagnostic/config.js +627 -0
- package/dist/call-diagnostic/config.js.map +1 -0
- package/dist/client-metrics-batcher.js +2 -1
- package/dist/client-metrics-batcher.js.map +1 -1
- package/dist/client-metrics-prelogin-batcher.js +33 -0
- package/dist/client-metrics-prelogin-batcher.js.map +1 -0
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -1
- package/dist/metrics.js +30 -50
- package/dist/metrics.js.map +1 -1
- package/dist/metrics.types.js +7 -0
- package/dist/metrics.types.js.map +1 -0
- package/dist/new-metrics.js +300 -0
- package/dist/new-metrics.js.map +1 -0
- package/dist/prelogin-metrics-batcher.js +82 -0
- package/dist/prelogin-metrics-batcher.js.map +1 -0
- package/dist/types/batcher.d.ts +7 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics-batcher.d.ts +2 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +237 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +425 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +103 -0
- package/dist/types/call-diagnostic/config.d.ts +178 -0
- package/dist/types/client-metrics-batcher.d.ts +2 -0
- package/dist/types/client-metrics-prelogin-batcher.d.ts +2 -0
- package/dist/types/config.d.ts +36 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/metrics.d.ts +3 -0
- package/dist/types/metrics.types.d.ts +107 -0
- package/dist/types/new-metrics.d.ts +131 -0
- package/dist/types/prelogin-metrics-batcher.d.ts +2 -0
- package/dist/types/utils.d.ts +6 -0
- package/dist/utils.js +27 -0
- package/dist/utils.js.map +1 -0
- package/package.json +15 -8
- package/src/batcher.js +38 -0
- package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +72 -0
- package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +511 -0
- package/src/call-diagnostic/call-diagnostic-metrics.ts +925 -0
- package/src/call-diagnostic/call-diagnostic-metrics.util.ts +399 -0
- package/src/call-diagnostic/config.ts +685 -0
- package/src/client-metrics-batcher.js +1 -0
- package/src/client-metrics-prelogin-batcher.ts +26 -0
- package/src/config.js +1 -0
- package/src/index.ts +56 -0
- package/src/metrics.js +26 -47
- package/src/metrics.types.ts +179 -0
- package/src/new-metrics.ts +278 -0
- package/src/prelogin-metrics-batcher.ts +95 -0
- package/src/utils.ts +17 -0
- package/test/unit/spec/batcher.js +2 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +469 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +718 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +2371 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +637 -0
- package/test/unit/spec/client-metrics-batcher.js +2 -0
- package/test/unit/spec/client-metrics-prelogin-batcher.ts +54 -0
- package/test/unit/spec/metrics.js +78 -129
- package/test/unit/spec/new-metrics.ts +231 -0
- package/test/unit/spec/prelogin-metrics-batcher.ts +253 -0
- package/test/unit/spec/utils.ts +22 -0
- package/tsconfig.json +6 -0
- package/dist/call-diagnostic-events-batcher.js +0 -60
- package/dist/call-diagnostic-events-batcher.js.map +0 -1
- package/src/call-diagnostic-events-batcher.js +0 -62
- package/src/index.js +0 -17
- package/test/unit/spec/call-diagnostic-events-batcher.js +0 -195
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {uniqueId} from 'lodash';
|
|
2
|
+
import Batcher from './batcher';
|
|
3
|
+
import {prepareDiagnosticMetricItem} from './call-diagnostic/call-diagnostic-metrics.util';
|
|
4
|
+
import {generateCommonErrorMetadata} from './utils';
|
|
5
|
+
|
|
6
|
+
const PRE_LOGIN_METRICS_IDENTIFIER = 'Pre Login Metrics -->';
|
|
7
|
+
|
|
8
|
+
const PreLoginMetricsBatcher = Batcher.extend({
|
|
9
|
+
namespace: 'Metrics',
|
|
10
|
+
preLoginId: undefined,
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Save the pre-login ID.
|
|
14
|
+
* @param {string} preLoginId The pre-login ID to be saved.
|
|
15
|
+
* @returns {void}
|
|
16
|
+
*/
|
|
17
|
+
savePreLoginId(preLoginId) {
|
|
18
|
+
this.preLoginId = preLoginId;
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Prepare item
|
|
23
|
+
* @param {any} item
|
|
24
|
+
* @returns {Promise<any>}
|
|
25
|
+
*/
|
|
26
|
+
prepareItem(item) {
|
|
27
|
+
return Promise.resolve(prepareDiagnosticMetricItem(this.webex, item));
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Prepare request, add time sensitive date etc.
|
|
32
|
+
* @param {any[]} queue
|
|
33
|
+
* @returns {Promise<any[]>}
|
|
34
|
+
*/
|
|
35
|
+
prepareRequest(queue) {
|
|
36
|
+
// Add sent timestamp
|
|
37
|
+
queue.forEach((item) => {
|
|
38
|
+
item.eventPayload.originTime = item.eventPayload.originTime || {};
|
|
39
|
+
item.eventPayload.originTime.sent = new Date().toISOString();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return Promise.resolve(queue);
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
*
|
|
47
|
+
* @param {any} payload
|
|
48
|
+
* @returns {Promise<any>}
|
|
49
|
+
*/
|
|
50
|
+
submitHttpRequest(payload: any) {
|
|
51
|
+
const batchId = uniqueId('prelogin-batch-');
|
|
52
|
+
if (this.preLoginId === undefined) {
|
|
53
|
+
this.webex.logger.error(
|
|
54
|
+
PRE_LOGIN_METRICS_IDENTIFIER,
|
|
55
|
+
`PreLoginMetricsBatcher: @submitHttpRequest#${batchId}. PreLoginId is not set.`
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
return Promise.reject(new Error('PreLoginId is not set.'));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return this.webex
|
|
62
|
+
.request({
|
|
63
|
+
method: 'POST',
|
|
64
|
+
service: 'metrics',
|
|
65
|
+
resource: 'clientmetrics-prelogin',
|
|
66
|
+
headers: {
|
|
67
|
+
authorization: false,
|
|
68
|
+
'x-prelogin-userid': this.preLoginId,
|
|
69
|
+
},
|
|
70
|
+
body: {
|
|
71
|
+
metrics: payload,
|
|
72
|
+
},
|
|
73
|
+
waitForServiceTimeout: this.webex.config.metrics.waitForServiceTimeout,
|
|
74
|
+
})
|
|
75
|
+
.then((res) => {
|
|
76
|
+
this.webex.logger.log(
|
|
77
|
+
PRE_LOGIN_METRICS_IDENTIFIER,
|
|
78
|
+
`PreLoginMetricsBatcher: @submitHttpRequest#${batchId}. Request successful.`
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
return res;
|
|
82
|
+
})
|
|
83
|
+
.catch((err) => {
|
|
84
|
+
this.webex.logger.error(
|
|
85
|
+
PRE_LOGIN_METRICS_IDENTIFIER,
|
|
86
|
+
`PreLoginMetricsBatcher: @submitHttpRequest#${batchId}. Request failed:`,
|
|
87
|
+
`error: ${generateCommonErrorMetadata(err)}`
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return Promise.reject(err);
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
export default PreLoginMetricsBatcher;
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* eslint-disable import/prefer-default-export */
|
|
2
|
+
/**
|
|
3
|
+
* Generates common metadata for errors
|
|
4
|
+
* @param {any} error
|
|
5
|
+
* @returns {object}
|
|
6
|
+
*/
|
|
7
|
+
export const generateCommonErrorMetadata = (error) => {
|
|
8
|
+
if (error instanceof Error) {
|
|
9
|
+
return JSON.stringify({
|
|
10
|
+
message: error?.message,
|
|
11
|
+
name: error?.name,
|
|
12
|
+
stack: error?.stack,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return error;
|
|
17
|
+
};
|
|
@@ -37,6 +37,7 @@ describe('plugin-metrics', () => {
|
|
|
37
37
|
return Promise.resolve({
|
|
38
38
|
statusCode: 204,
|
|
39
39
|
body: undefined,
|
|
40
|
+
waitForServiceTimeout: 30,
|
|
40
41
|
options,
|
|
41
42
|
});
|
|
42
43
|
};
|
|
@@ -97,6 +98,7 @@ describe('plugin-metrics', () => {
|
|
|
97
98
|
return Promise.resolve({
|
|
98
99
|
statusCode: 204,
|
|
99
100
|
body: undefined,
|
|
101
|
+
waitForServiceTimeout: 30,
|
|
100
102
|
options,
|
|
101
103
|
});
|
|
102
104
|
});
|
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {assert} from '@webex/test-helper-chai';
|
|
6
|
+
import {config, Utils} from '@webex/internal-plugin-metrics';
|
|
7
|
+
import {CallDiagnosticUtils} from '@webex/internal-plugin-metrics';
|
|
8
|
+
import MockWebex from '@webex/test-helper-mock-webex';
|
|
9
|
+
import sinon from 'sinon';
|
|
10
|
+
import FakeTimers from '@sinonjs/fake-timers';
|
|
11
|
+
import {NewMetrics} from '@webex/internal-plugin-metrics';
|
|
12
|
+
import {uniqueId} from 'lodash';
|
|
13
|
+
|
|
14
|
+
const flushPromises = () => new Promise(setImmediate);
|
|
15
|
+
|
|
16
|
+
function promiseTick(count) {
|
|
17
|
+
let promise = Promise.resolve();
|
|
18
|
+
|
|
19
|
+
while (count > 1) {
|
|
20
|
+
promise = promise.then(() => promiseTick(1));
|
|
21
|
+
count -= 1;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return promise;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe('plugin-metrics', () => {
|
|
28
|
+
describe('CallDiagnosticEventsBatcher', () => {
|
|
29
|
+
let webex;
|
|
30
|
+
let clock;
|
|
31
|
+
let now;
|
|
32
|
+
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
now = new Date();
|
|
35
|
+
clock = FakeTimers.install({now});
|
|
36
|
+
|
|
37
|
+
//@ts-ignore
|
|
38
|
+
webex = new MockWebex({
|
|
39
|
+
children: {
|
|
40
|
+
newMetrics: NewMetrics,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
webex.request = (options) =>
|
|
45
|
+
Promise.resolve({body: {items: []}, waitForServiceTimeout: 15, options});
|
|
46
|
+
sinon.spy(webex, 'request');
|
|
47
|
+
|
|
48
|
+
webex.emit('ready');
|
|
49
|
+
|
|
50
|
+
webex.config.metrics = config.metrics;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
afterEach(() => {
|
|
54
|
+
sinon.restore();
|
|
55
|
+
clock.uninstall();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe('#request()', () => {
|
|
59
|
+
describe('when the request completes successfully', () => {
|
|
60
|
+
it('clears the queue', async () => {
|
|
61
|
+
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
62
|
+
//@ts-ignore
|
|
63
|
+
{event: {name: 'client.interstitial-window.launched'}}
|
|
64
|
+
);
|
|
65
|
+
await flushPromises();
|
|
66
|
+
clock.tick(config.metrics.batcherWait);
|
|
67
|
+
|
|
68
|
+
await promise;
|
|
69
|
+
|
|
70
|
+
//@ts-ignore
|
|
71
|
+
assert.calledOnce(webex.request);
|
|
72
|
+
assert.lengthOf(
|
|
73
|
+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue,
|
|
74
|
+
0
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('doesnt include any joinTimes for other events', async () => {
|
|
79
|
+
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
80
|
+
//@ts-ignore
|
|
81
|
+
{event: {name: 'client.alert.displayed'}}
|
|
82
|
+
);
|
|
83
|
+
await flushPromises();
|
|
84
|
+
clock.tick(config.metrics.batcherWait);
|
|
85
|
+
|
|
86
|
+
await promise;
|
|
87
|
+
|
|
88
|
+
//@ts-ignore
|
|
89
|
+
assert.calledOnce(webex.request);
|
|
90
|
+
assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
|
|
91
|
+
name: 'client.alert.displayed',
|
|
92
|
+
});
|
|
93
|
+
assert.lengthOf(
|
|
94
|
+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue,
|
|
95
|
+
0
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('appends the correct join times to the request for client.interstitial-window.launched', async () => {
|
|
100
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon
|
|
101
|
+
.stub()
|
|
102
|
+
.returns(10);
|
|
103
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitial = sinon
|
|
104
|
+
.stub()
|
|
105
|
+
.returns(10);
|
|
106
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getRefreshCaptchaReqResp = sinon
|
|
107
|
+
.stub()
|
|
108
|
+
.returns(10);
|
|
109
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getDownloadIntelligenceModelsReqResp =
|
|
110
|
+
sinon.stub().returns(42);
|
|
111
|
+
|
|
112
|
+
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
113
|
+
//@ts-ignore
|
|
114
|
+
{event: {name: 'client.interstitial-window.launched'}}
|
|
115
|
+
);
|
|
116
|
+
await flushPromises();
|
|
117
|
+
clock.tick(config.metrics.batcherWait);
|
|
118
|
+
|
|
119
|
+
await promise;
|
|
120
|
+
|
|
121
|
+
//@ts-ignore
|
|
122
|
+
assert.calledOnce(webex.request);
|
|
123
|
+
assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
|
|
124
|
+
name: 'client.interstitial-window.launched',
|
|
125
|
+
joinTimes: {
|
|
126
|
+
clickToInterstitial: 10,
|
|
127
|
+
meetingInfoReqResp: 10,
|
|
128
|
+
refreshCaptchaServiceReqResp: 10,
|
|
129
|
+
downloadIntelligenceModelsReqResp: 42,
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
assert.lengthOf(
|
|
133
|
+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue,
|
|
134
|
+
0
|
|
135
|
+
);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('appends the correct join times to the request for client.call.initiated', async () => {
|
|
139
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon
|
|
140
|
+
.stub()
|
|
141
|
+
.returns(10);
|
|
142
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getU2CTime = sinon
|
|
143
|
+
.stub()
|
|
144
|
+
.returns(20);
|
|
145
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getReachabilityClustersReqResp = sinon
|
|
146
|
+
.stub()
|
|
147
|
+
.returns(10);
|
|
148
|
+
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
149
|
+
//@ts-ignore
|
|
150
|
+
{event: {name: 'client.call.initiated'}}
|
|
151
|
+
);
|
|
152
|
+
await flushPromises();
|
|
153
|
+
clock.tick(config.metrics.batcherWait);
|
|
154
|
+
|
|
155
|
+
await promise;
|
|
156
|
+
//@ts-ignore
|
|
157
|
+
assert.calledOnce(webex.request);
|
|
158
|
+
assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
|
|
159
|
+
name: 'client.call.initiated',
|
|
160
|
+
joinTimes: {
|
|
161
|
+
meetingInfoReqResp: 10,
|
|
162
|
+
registerWDMDeviceJMT: 10,
|
|
163
|
+
showInterstitialTime: 10,
|
|
164
|
+
getU2CTime: 20,
|
|
165
|
+
getReachabilityClustersReqResp: 10
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
assert.lengthOf(
|
|
169
|
+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue,
|
|
170
|
+
0
|
|
171
|
+
);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('appends the correct join times to the request for client.locus.join.response', async () => {
|
|
175
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon
|
|
176
|
+
.stub()
|
|
177
|
+
.returns(10);
|
|
178
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getPageJMT = sinon.stub().returns(30);
|
|
179
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getClientJMT = sinon.stub().returns(5);
|
|
180
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitial = sinon
|
|
181
|
+
.stub()
|
|
182
|
+
.returns(10);
|
|
183
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getCallInitJoinReq = sinon
|
|
184
|
+
.stub()
|
|
185
|
+
.returns(10);
|
|
186
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getDownloadTimeJMT = sinon
|
|
187
|
+
.stub()
|
|
188
|
+
.returns(100);
|
|
189
|
+
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
190
|
+
//@ts-ignore
|
|
191
|
+
{event: {name: 'client.locus.join.response'}}
|
|
192
|
+
);
|
|
193
|
+
await flushPromises();
|
|
194
|
+
clock.tick(config.metrics.batcherWait);
|
|
195
|
+
|
|
196
|
+
await promise;
|
|
197
|
+
|
|
198
|
+
//@ts-ignore
|
|
199
|
+
assert.calledOnce(webex.request);
|
|
200
|
+
assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
|
|
201
|
+
name: 'client.locus.join.response',
|
|
202
|
+
joinTimes: {
|
|
203
|
+
callInitJoinReq: 10,
|
|
204
|
+
clickToInterstitial: 10,
|
|
205
|
+
interstitialToJoinOK: 10,
|
|
206
|
+
joinReqResp: 10,
|
|
207
|
+
meetingInfoReqResp: 10,
|
|
208
|
+
pageJmt: 30,
|
|
209
|
+
totalJmt: 20,
|
|
210
|
+
clientJmt: 5,
|
|
211
|
+
downloadTime: 100,
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
assert.lengthOf(
|
|
215
|
+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue,
|
|
216
|
+
0
|
|
217
|
+
);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('appends the correct join times to the request for client.ice.end', async () => {
|
|
221
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon
|
|
222
|
+
.stub()
|
|
223
|
+
.returns(10);
|
|
224
|
+
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
225
|
+
//@ts-ignore
|
|
226
|
+
{event: {name: 'client.ice.end'}}
|
|
227
|
+
);
|
|
228
|
+
await flushPromises();
|
|
229
|
+
clock.tick(config.metrics.batcherWait);
|
|
230
|
+
|
|
231
|
+
await promise;
|
|
232
|
+
|
|
233
|
+
//@ts-ignore
|
|
234
|
+
assert.calledOnce(webex.request);
|
|
235
|
+
assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
|
|
236
|
+
name: 'client.ice.end',
|
|
237
|
+
joinTimes: {
|
|
238
|
+
ICESetupTime: 10,
|
|
239
|
+
audioICESetupTime: 10,
|
|
240
|
+
shareICESetupTime: 10,
|
|
241
|
+
videoICESetupTime: 10,
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
assert.lengthOf(
|
|
245
|
+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue,
|
|
246
|
+
0
|
|
247
|
+
);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('appends the correct join times to the request for client.media.rx.start', async () => {
|
|
251
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon
|
|
252
|
+
.stub()
|
|
253
|
+
.returns(10);
|
|
254
|
+
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
255
|
+
//@ts-ignore
|
|
256
|
+
{event: {name: 'client.media.rx.start'}}
|
|
257
|
+
);
|
|
258
|
+
await flushPromises();
|
|
259
|
+
clock.tick(config.metrics.batcherWait);
|
|
260
|
+
|
|
261
|
+
await promise;
|
|
262
|
+
|
|
263
|
+
//@ts-ignore
|
|
264
|
+
assert.calledOnce(webex.request);
|
|
265
|
+
assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
|
|
266
|
+
name: 'client.media.rx.start',
|
|
267
|
+
joinTimes: {
|
|
268
|
+
localSDPGenRemoteSDPRecv: 10,
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
assert.lengthOf(
|
|
272
|
+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue,
|
|
273
|
+
0
|
|
274
|
+
);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('appends the correct join times to the request for client.media-engine.ready', async () => {
|
|
278
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon
|
|
279
|
+
.stub()
|
|
280
|
+
.returns(10);
|
|
281
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getInterstitialToMediaOKJMT = sinon
|
|
282
|
+
.stub()
|
|
283
|
+
.returns(10);
|
|
284
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitial = sinon
|
|
285
|
+
.stub()
|
|
286
|
+
.returns(10);
|
|
287
|
+
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
288
|
+
//@ts-ignore
|
|
289
|
+
{event: {name: 'client.media-engine.ready'}}
|
|
290
|
+
);
|
|
291
|
+
await flushPromises();
|
|
292
|
+
clock.tick(config.metrics.batcherWait);
|
|
293
|
+
|
|
294
|
+
await promise;
|
|
295
|
+
|
|
296
|
+
//@ts-ignore
|
|
297
|
+
assert.calledOnce(webex.request);
|
|
298
|
+
assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
|
|
299
|
+
name: 'client.media-engine.ready',
|
|
300
|
+
joinTimes: {
|
|
301
|
+
totalMediaJMT: 30,
|
|
302
|
+
interstitialToMediaOKJMT: 10,
|
|
303
|
+
callInitMediaEngineReady: 10,
|
|
304
|
+
stayLobbyTime: 10,
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
assert.lengthOf(
|
|
308
|
+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue,
|
|
309
|
+
0
|
|
310
|
+
);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it('appends the correct audio and video setup delays to the request for client.mediaquality.event', async () => {
|
|
314
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getDiffBetweenTimestamps = sinon
|
|
315
|
+
.stub()
|
|
316
|
+
.returns(10);
|
|
317
|
+
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
318
|
+
//@ts-ignore
|
|
319
|
+
{event: {name: 'client.mediaquality.event'}}
|
|
320
|
+
);
|
|
321
|
+
await flushPromises();
|
|
322
|
+
clock.tick(config.metrics.batcherWait);
|
|
323
|
+
|
|
324
|
+
await promise;
|
|
325
|
+
|
|
326
|
+
//@ts-ignore
|
|
327
|
+
assert.calledOnce(webex.request);
|
|
328
|
+
assert.deepEqual(webex.request.getCalls()[0].args[0].body.metrics[0].eventPayload.event, {
|
|
329
|
+
name: 'client.mediaquality.event',
|
|
330
|
+
audioSetupDelay: {
|
|
331
|
+
joinRespRxStart: 10,
|
|
332
|
+
joinRespTxStart: 10,
|
|
333
|
+
},
|
|
334
|
+
videoSetupDelay: {
|
|
335
|
+
joinRespRxStart: 10,
|
|
336
|
+
joinRespTxStart: 10,
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
assert.lengthOf(
|
|
340
|
+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue,
|
|
341
|
+
0
|
|
342
|
+
);
|
|
343
|
+
});
|
|
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
|
+
});
|
|
371
|
+
|
|
372
|
+
describe('when the request fails', () => {
|
|
373
|
+
it('does not clear the queue', async () => {
|
|
374
|
+
// avoid setting .sent timestamp
|
|
375
|
+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.prepareRequest =
|
|
376
|
+
(q) => Promise.resolve(q);
|
|
377
|
+
|
|
378
|
+
const err = new Error('error');
|
|
379
|
+
webex.request = sinon.stub().returns(Promise.reject(err));
|
|
380
|
+
|
|
381
|
+
webex.logger.error = sinon.stub();
|
|
382
|
+
webex.logger.log = sinon.stub();
|
|
383
|
+
sinon.stub(Utils, 'generateCommonErrorMetadata').returns('formattedError');
|
|
384
|
+
|
|
385
|
+
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics({
|
|
386
|
+
event: 'my.event',
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
await flushPromises();
|
|
390
|
+
clock.tick(config.metrics.batcherWait);
|
|
391
|
+
|
|
392
|
+
let error;
|
|
393
|
+
|
|
394
|
+
// catch the expected error and store it
|
|
395
|
+
await promise.catch((e) => {
|
|
396
|
+
error = e;
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// This is horrific, but stubbing lodash is proving difficult
|
|
400
|
+
const expectedBatchId = parseInt(uniqueId()) - 1;
|
|
401
|
+
|
|
402
|
+
// check that promise was rejected with the original error of the webex.request
|
|
403
|
+
assert.deepEqual(err, error);
|
|
404
|
+
|
|
405
|
+
assert.calledOnceWithExactly(
|
|
406
|
+
webex.logger.error,
|
|
407
|
+
'call-diagnostic-events -> ',
|
|
408
|
+
`CallDiagnosticEventsBatcher: @submitHttpRequest#ca-batch-${expectedBatchId}. Request failed:`,
|
|
409
|
+
`error: formattedError`
|
|
410
|
+
);
|
|
411
|
+
assert.lengthOf(
|
|
412
|
+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.queue,
|
|
413
|
+
0
|
|
414
|
+
);
|
|
415
|
+
});
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
describe('prepareItem', () => {
|
|
420
|
+
it('calls prepareDiagnosticMetricItem correctly', async () => {
|
|
421
|
+
// avoid setting .sent timestamp
|
|
422
|
+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.prepareRequest =
|
|
423
|
+
(q) => Promise.resolve(q);
|
|
424
|
+
|
|
425
|
+
const prepareItemSpy = sinon.spy(
|
|
426
|
+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher,
|
|
427
|
+
'prepareItem'
|
|
428
|
+
);
|
|
429
|
+
const prepareDiagnosticMetricItemSpy = sinon.spy(
|
|
430
|
+
CallDiagnosticUtils,
|
|
431
|
+
'prepareDiagnosticMetricItem'
|
|
432
|
+
);
|
|
433
|
+
|
|
434
|
+
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics({
|
|
435
|
+
event: 'my.event',
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
await flushPromises();
|
|
439
|
+
|
|
440
|
+
clock.tick(config.metrics.batcherWait);
|
|
441
|
+
|
|
442
|
+
await promise;
|
|
443
|
+
|
|
444
|
+
const calls = prepareItemSpy.getCalls()[0];
|
|
445
|
+
|
|
446
|
+
// item also gets assigned a delay property but the key is a Symbol and haven't been able to test that..
|
|
447
|
+
assert.deepEqual(calls.args[0].eventPayload, {
|
|
448
|
+
event: 'my.event',
|
|
449
|
+
origin: {buildType: 'test', networkType: 'unknown'},
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
assert.deepEqual(calls.args[0].type, ['diagnostic-event']);
|
|
453
|
+
|
|
454
|
+
const prepareDiagnosticMetricItemCalls = prepareDiagnosticMetricItemSpy.getCalls();
|
|
455
|
+
|
|
456
|
+
// second argument (item) also gets assigned a delay property but the key is a Symbol and haven't been able to test that..
|
|
457
|
+
assert.deepEqual(prepareDiagnosticMetricItemCalls[0].args[0], webex);
|
|
458
|
+
assert.deepEqual(prepareDiagnosticMetricItemCalls[0].args[1].eventPayload, {
|
|
459
|
+
event: 'my.event',
|
|
460
|
+
origin: {
|
|
461
|
+
buildType: 'test',
|
|
462
|
+
networkType: 'unknown',
|
|
463
|
+
},
|
|
464
|
+
});
|
|
465
|
+
assert.deepEqual(prepareDiagnosticMetricItemCalls[0].args[1].type, ['diagnostic-event']);
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
});
|