@webex/internal-plugin-metrics 3.11.0 → 3.12.0-llmrefactor.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/automated-user.js +19 -0
- package/dist/automated-user.js.map +1 -0
- package/dist/batcher.js +3 -0
- package/dist/batcher.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +639 -65
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.js +168 -76
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js +18 -4
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
- package/dist/call-diagnostic/config.js +17 -3
- package/dist/call-diagnostic/config.js.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/generic-metrics.js +8 -6
- package/dist/generic-metrics.js.map +1 -1
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/metrics.js +1 -1
- package/dist/metrics.types.js +4 -0
- package/dist/metrics.types.js.map +1 -1
- package/dist/new-metrics.js +105 -26
- package/dist/new-metrics.js.map +1 -1
- package/dist/prelogin-metrics.js +106 -0
- package/dist/prelogin-metrics.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/constants.js +18 -0
- package/dist/privacy-and-security-permission-enricher/constants.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/index.js +143 -0
- package/dist/privacy-and-security-permission-enricher/index.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/types.js +7 -0
- package/dist/privacy-and-security-permission-enricher/types.js.map +1 -0
- package/dist/privacy-and-security-permission-enricher/utils.js +71 -0
- package/dist/privacy-and-security-permission-enricher/utils.js.map +1 -0
- package/dist/types/automated-user.d.ts +2 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +208 -5
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +79 -15
- package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +5 -0
- package/dist/types/call-diagnostic/config.d.ts +5 -0
- package/dist/types/config.d.ts +1 -0
- package/dist/types/index.d.ts +6 -3
- package/dist/types/metrics.types.d.ts +9 -4
- package/dist/types/new-metrics.d.ts +29 -1
- package/dist/types/prelogin-metrics.d.ts +47 -0
- package/dist/types/privacy-and-security-permission-enricher/constants.d.ts +6 -0
- package/dist/types/privacy-and-security-permission-enricher/index.d.ts +40 -0
- package/dist/types/privacy-and-security-permission-enricher/types.d.ts +14 -0
- package/dist/types/privacy-and-security-permission-enricher/utils.d.ts +5 -0
- package/package.json +12 -11
- package/src/automated-user.ts +16 -0
- package/src/batcher.js +4 -0
- package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +800 -75
- package/src/call-diagnostic/call-diagnostic-metrics.ts +102 -15
- package/src/call-diagnostic/call-diagnostic-metrics.util.ts +22 -2
- package/src/call-diagnostic/config.ts +15 -0
- package/src/config.js +1 -0
- package/src/generic-metrics.ts +6 -6
- package/src/index.ts +9 -0
- package/src/metrics.types.ts +27 -5
- package/src/new-metrics.ts +95 -6
- package/src/prelogin-metrics.ts +94 -0
- package/src/privacy-and-security-permission-enricher/constants.ts +33 -0
- package/src/privacy-and-security-permission-enricher/index.ts +142 -0
- package/src/privacy-and-security-permission-enricher/types.ts +21 -0
- package/src/privacy-and-security-permission-enricher/utils.ts +82 -0
- package/test/unit/spec/automated-user.ts +43 -0
- package/test/unit/spec/batcher.js +43 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +47 -11
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +1550 -416
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +887 -159
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +61 -3
- package/test/unit/spec/new-metrics.ts +183 -50
- package/test/unit/spec/prelogin-metrics-batcher.ts +71 -36
- package/test/unit/spec/prelogin-metrics.ts +132 -0
- package/test/unit/spec/privacy-and-security-permission-enricher.ts +318 -0
|
@@ -27,6 +27,7 @@ const {
|
|
|
27
27
|
isUnauthorizedError,
|
|
28
28
|
generateClientErrorCodeForIceFailure,
|
|
29
29
|
isSdpOfferCreationError,
|
|
30
|
+
isWebrtcApiNotAvailableError,
|
|
30
31
|
} = CallDiagnosticUtils;
|
|
31
32
|
|
|
32
33
|
describe('internal-plugin-metrics', () => {
|
|
@@ -206,6 +207,29 @@ describe('internal-plugin-metrics', () => {
|
|
|
206
207
|
});
|
|
207
208
|
});
|
|
208
209
|
|
|
210
|
+
describe('isWebrtcApiNotAvailableError', () => {
|
|
211
|
+
type TestWebrtcApiNotAvailableError = {
|
|
212
|
+
code: number;
|
|
213
|
+
message: string;
|
|
214
|
+
name: string;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const error: TestWebrtcApiNotAvailableError = {
|
|
218
|
+
code: 30007,
|
|
219
|
+
name: 'WebrtcApiNotAvailableError',
|
|
220
|
+
message: 'RTCPeerConnection API is not available in this environment',
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
[
|
|
224
|
+
['WebrtcApiNotAvailableError', error, true],
|
|
225
|
+
['generic error', new Error('this is an error'), false],
|
|
226
|
+
].forEach(([errorType, rawError, expected]) => {
|
|
227
|
+
it(`for ${errorType} rawError returns the correct result`, () => {
|
|
228
|
+
assert.strictEqual(isWebrtcApiNotAvailableError(rawError), expected);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
209
233
|
describe('isBrowserMediaErrorName', () => {
|
|
210
234
|
[
|
|
211
235
|
['PermissionDeniedError', true],
|
|
@@ -287,7 +311,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
287
311
|
origin: {
|
|
288
312
|
buildType: 'prod',
|
|
289
313
|
networkType: 'unknown',
|
|
290
|
-
upgradeChannel: expectedUpgradeChannel
|
|
314
|
+
upgradeChannel: expectedUpgradeChannel,
|
|
291
315
|
},
|
|
292
316
|
event: {name: eventName, ...expectedEvent},
|
|
293
317
|
},
|
|
@@ -369,7 +393,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
369
393
|
totalJmt: undefined,
|
|
370
394
|
clientJmt: undefined,
|
|
371
395
|
downloadTime: undefined,
|
|
372
|
-
clickToInterstitialWithUserDelay:
|
|
396
|
+
clickToInterstitialWithUserDelay: undefined,
|
|
373
397
|
totalJMTWithUserDelay: undefined,
|
|
374
398
|
},
|
|
375
399
|
},
|
|
@@ -406,7 +430,6 @@ describe('internal-plugin-metrics', () => {
|
|
|
406
430
|
totalMediaJMT: undefined,
|
|
407
431
|
interstitialToMediaOKJMT: undefined,
|
|
408
432
|
callInitMediaEngineReady: undefined,
|
|
409
|
-
stayLobbyTime: undefined,
|
|
410
433
|
totalMediaJMTWithUserDelay: undefined,
|
|
411
434
|
totalJMTWithUserDelay: undefined,
|
|
412
435
|
},
|
|
@@ -423,12 +446,47 @@ describe('internal-plugin-metrics', () => {
|
|
|
423
446
|
},
|
|
424
447
|
},
|
|
425
448
|
],
|
|
449
|
+
[
|
|
450
|
+
'client.lobby.exited',
|
|
451
|
+
{
|
|
452
|
+
joinTimes: {
|
|
453
|
+
stayLobbyTime: undefined,
|
|
454
|
+
},
|
|
455
|
+
},
|
|
456
|
+
],
|
|
426
457
|
].forEach(([eventName, expectedEvent]) => {
|
|
427
458
|
it(`returns expected result for ${eventName}`, () => {
|
|
428
459
|
check(eventName as string, expectedEvent, 'gold');
|
|
429
460
|
});
|
|
430
461
|
});
|
|
431
462
|
|
|
463
|
+
it('logs a Milestone entry when event name is present', () => {
|
|
464
|
+
const logSpy = sinon.spy(webex.logger, 'log');
|
|
465
|
+
const eventName = 'client.call.initiated';
|
|
466
|
+
const eventPayload = {event: {name: eventName}};
|
|
467
|
+
|
|
468
|
+
prepareDiagnosticMetricItem(webex, {eventPayload, type: ['diagnostic-event']});
|
|
469
|
+
|
|
470
|
+
assert.isTrue(
|
|
471
|
+
logSpy.calledWith('Milestone,CallDiagnostic', eventName),
|
|
472
|
+
'expected logger.log to be called with Milestone,CallDiagnostic and the event name'
|
|
473
|
+
);
|
|
474
|
+
sinon.restore();
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
it('does not log a Milestone entry when event name is absent', () => {
|
|
478
|
+
const logSpy = sinon.spy(webex.logger, 'log');
|
|
479
|
+
const eventPayload = {event: {}};
|
|
480
|
+
|
|
481
|
+
prepareDiagnosticMetricItem(webex, {eventPayload, type: ['diagnostic-event']});
|
|
482
|
+
|
|
483
|
+
assert.isFalse(
|
|
484
|
+
logSpy.calledWith('Milestone,CallDiagnostic', sinon.match.any),
|
|
485
|
+
'expected logger.log not to be called with Milestone,CallDiagnostic when event name is absent'
|
|
486
|
+
);
|
|
487
|
+
sinon.restore();
|
|
488
|
+
});
|
|
489
|
+
|
|
432
490
|
it('sets buildType and upgradeChannel correctly', () => {
|
|
433
491
|
const item: any = {
|
|
434
492
|
eventPayload: {
|
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
import {assert} from '@webex/test-helper-chai';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
NewMetrics,
|
|
4
|
+
CallDiagnosticLatencies,
|
|
5
|
+
AutomatedUserUtils,
|
|
6
|
+
Utils,
|
|
7
|
+
} from '@webex/internal-plugin-metrics';
|
|
3
8
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
4
9
|
import sinon from 'sinon';
|
|
5
|
-
import {Utils} from '@webex/internal-plugin-metrics';
|
|
6
10
|
|
|
7
11
|
describe('internal-plugin-metrics', () => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
const mockWebex = () =>
|
|
13
|
+
new MockWebex({
|
|
14
|
+
children: {
|
|
15
|
+
newMetrics: NewMetrics,
|
|
16
|
+
},
|
|
17
|
+
meetings: {
|
|
18
|
+
getBasicMeetingInformation: sinon.stub().callsFake((meetingId) => ({
|
|
19
|
+
id: meetingId,
|
|
20
|
+
correlationId: `correlation-${meetingId}`,
|
|
21
|
+
})),
|
|
22
|
+
},
|
|
23
|
+
request: sinon.stub().resolves({}),
|
|
24
|
+
logger: {
|
|
25
|
+
log: sinon.stub(),
|
|
26
|
+
error: sinon.stub(),
|
|
27
|
+
},
|
|
28
|
+
});
|
|
21
29
|
|
|
22
30
|
describe('check submitClientEvent, submitFeatureEvent when webex is not ready', () => {
|
|
23
31
|
let webex;
|
|
@@ -46,12 +54,14 @@ describe('internal-plugin-metrics', () => {
|
|
|
46
54
|
payload: {
|
|
47
55
|
meetingSummaryInfo: {
|
|
48
56
|
featureName: 'syncSystemMuteStatus',
|
|
49
|
-
featureActions: [
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
featureActions: [
|
|
58
|
+
{
|
|
59
|
+
actionName: 'syncMeetingMicUnmuteStatusToSystem',
|
|
60
|
+
actionId: '14200',
|
|
61
|
+
isInitialValue: false,
|
|
62
|
+
clickCount: '1',
|
|
63
|
+
},
|
|
64
|
+
],
|
|
55
65
|
},
|
|
56
66
|
},
|
|
57
67
|
});
|
|
@@ -64,11 +74,36 @@ describe('internal-plugin-metrics', () => {
|
|
|
64
74
|
|
|
65
75
|
describe('new-metrics contstructor', () => {
|
|
66
76
|
it('checks callDiagnosticLatencies is defined before ready emit', () => {
|
|
67
|
-
|
|
68
77
|
const webex = mockWebex();
|
|
69
78
|
|
|
70
79
|
assert.instanceOf(webex.internal.newMetrics.callDiagnosticLatencies, CallDiagnosticLatencies);
|
|
71
80
|
});
|
|
81
|
+
|
|
82
|
+
it('checks callDiagnosticMetrics is defined before ready emit', () => {
|
|
83
|
+
const webex = mockWebex();
|
|
84
|
+
|
|
85
|
+
assert.isDefined(webex.internal.newMetrics.callDiagnosticMetrics);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('can call buildClientEventFetchRequestOptions before ready', async () => {
|
|
89
|
+
const webex = mockWebex();
|
|
90
|
+
const stub = sinon.stub(
|
|
91
|
+
webex.internal.newMetrics.callDiagnosticMetrics,
|
|
92
|
+
'buildClientEventFetchRequestOptions'
|
|
93
|
+
).resolves({url: 'https://metrics.example.com'});
|
|
94
|
+
|
|
95
|
+
const result = await webex.internal.newMetrics.buildClientEventFetchRequestOptions({
|
|
96
|
+
name: 'client.alert.displayed',
|
|
97
|
+
options: {correlationId: 'test-id'},
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
assert.calledOnceWithExactly(stub, {
|
|
101
|
+
name: 'client.alert.displayed',
|
|
102
|
+
payload: undefined,
|
|
103
|
+
options: {correlationId: 'test-id'},
|
|
104
|
+
});
|
|
105
|
+
assert.deepEqual(result, {url: 'https://metrics.example.com'});
|
|
106
|
+
});
|
|
72
107
|
});
|
|
73
108
|
|
|
74
109
|
describe('new-metrics', () => {
|
|
@@ -94,7 +129,7 @@ describe('internal-plugin-metrics', () => {
|
|
|
94
129
|
|
|
95
130
|
afterEach(() => {
|
|
96
131
|
sinon.restore();
|
|
97
|
-
})
|
|
132
|
+
});
|
|
98
133
|
|
|
99
134
|
it('lazy metrics backend initialization when checking if backend ready', () => {
|
|
100
135
|
assert.isUndefined(webex.internal.newMetrics.behavioralMetrics);
|
|
@@ -105,13 +140,20 @@ describe('internal-plugin-metrics', () => {
|
|
|
105
140
|
webex.internal.newMetrics.isReadyToSubmitOperationalEvents();
|
|
106
141
|
assert.isDefined(webex.internal.newMetrics.operationalMetrics);
|
|
107
142
|
|
|
108
|
-
assert.isUndefined(webex.internal.newMetrics.businessMetrics)
|
|
143
|
+
assert.isUndefined(webex.internal.newMetrics.businessMetrics);
|
|
109
144
|
webex.internal.newMetrics.isReadyToSubmitBusinessEvents();
|
|
110
145
|
assert.isDefined(webex.internal.newMetrics.businessMetrics);
|
|
111
|
-
})
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('returns the automated user classification', () => {
|
|
149
|
+
assert.strictEqual(
|
|
150
|
+
webex.internal.newMetrics.isAutomatedUser(),
|
|
151
|
+
AutomatedUserUtils.isAutomatedUser()
|
|
152
|
+
);
|
|
153
|
+
});
|
|
112
154
|
|
|
113
155
|
it('passes the table through to the business metrics', () => {
|
|
114
|
-
assert.isUndefined(webex.internal.newMetrics.businessMetrics)
|
|
156
|
+
assert.isUndefined(webex.internal.newMetrics.businessMetrics);
|
|
115
157
|
webex.internal.newMetrics.isReadyToSubmitBusinessEvents();
|
|
116
158
|
assert.isDefined(webex.internal.newMetrics.businessMetrics);
|
|
117
159
|
webex.internal.newMetrics.businessMetrics.submitBusinessEvent = sinon.stub();
|
|
@@ -119,14 +161,14 @@ describe('internal-plugin-metrics', () => {
|
|
|
119
161
|
name: 'foobar',
|
|
120
162
|
payload: {},
|
|
121
163
|
table: 'test',
|
|
122
|
-
metadata: {
|
|
164
|
+
metadata: {foo: 'bar'},
|
|
123
165
|
});
|
|
124
166
|
|
|
125
167
|
assert.calledWith(webex.internal.newMetrics.businessMetrics.submitBusinessEvent, {
|
|
126
168
|
name: 'foobar',
|
|
127
169
|
payload: {},
|
|
128
170
|
table: 'test',
|
|
129
|
-
metadata: {
|
|
171
|
+
metadata: {foo: 'bar'},
|
|
130
172
|
});
|
|
131
173
|
});
|
|
132
174
|
|
|
@@ -150,6 +192,87 @@ describe('internal-plugin-metrics', () => {
|
|
|
150
192
|
});
|
|
151
193
|
});
|
|
152
194
|
|
|
195
|
+
describe('privacy and security permission enrichment', () => {
|
|
196
|
+
const permission = {
|
|
197
|
+
camera: {status: 'GRANTED' as const},
|
|
198
|
+
microphone: {status: 'DENIED' as const, reason: 'DENIED_BY_USER' as const},
|
|
199
|
+
contentShare: {status: 'REQUESTING' as const},
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
it('enriches an eligible client event through the public metrics API', () => {
|
|
203
|
+
webex.internal.newMetrics.setPrivacyAndSecurityPermission(permission);
|
|
204
|
+
webex.internal.newMetrics.submitClientEvent({name: 'client.call.initiated'});
|
|
205
|
+
|
|
206
|
+
const submittedPayload =
|
|
207
|
+
webex.internal.newMetrics.callDiagnosticMetrics.submitClientEvent.firstCall.args[0]
|
|
208
|
+
.payload;
|
|
209
|
+
|
|
210
|
+
assert.deepEqual(submittedPayload.privacyAndSecurityPermission, {
|
|
211
|
+
camera: permission.camera,
|
|
212
|
+
microphone: permission.microphone,
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('uses the meeting correlation id to preserve history across identifier transitions', () => {
|
|
217
|
+
webex.meetings.getBasicMeetingInformation
|
|
218
|
+
.withArgs('meeting-1')
|
|
219
|
+
.returns({id: 'meeting-1', correlationId: 'correlation-1'});
|
|
220
|
+
webex.internal.newMetrics.setPrivacyAndSecurityPermission(permission);
|
|
221
|
+
|
|
222
|
+
webex.internal.newMetrics.submitClientEvent({
|
|
223
|
+
name: 'client.call.initiated',
|
|
224
|
+
options: {correlationId: 'correlation-1'},
|
|
225
|
+
});
|
|
226
|
+
webex.internal.newMetrics.submitClientEvent({
|
|
227
|
+
name: 'client.ice.end',
|
|
228
|
+
payload: {},
|
|
229
|
+
options: {meetingId: 'meeting-1'},
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
const submissions = webex.internal.newMetrics.callDiagnosticMetrics.submitClientEvent.args;
|
|
233
|
+
|
|
234
|
+
assert.property(submissions[0][0].payload, 'privacyAndSecurityPermission');
|
|
235
|
+
assert.notProperty(submissions[1][0].payload, 'privacyAndSecurityPermission');
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('uses the default scope when no correlation id can be resolved', () => {
|
|
239
|
+
webex.internal.newMetrics.setPrivacyAndSecurityPermission(permission);
|
|
240
|
+
|
|
241
|
+
webex.internal.newMetrics.submitClientEvent({
|
|
242
|
+
name: 'client.call.initiated',
|
|
243
|
+
options: {sessionCorrelationId: 'session-1'},
|
|
244
|
+
});
|
|
245
|
+
webex.internal.newMetrics.submitClientEvent({
|
|
246
|
+
name: 'client.ice.end',
|
|
247
|
+
payload: {},
|
|
248
|
+
options: {sessionCorrelationId: 'session-2'},
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
const submissions = webex.internal.newMetrics.callDiagnosticMetrics.submitClientEvent.args;
|
|
252
|
+
|
|
253
|
+
assert.property(submissions[0][0].payload, 'privacyAndSecurityPermission');
|
|
254
|
+
assert.notProperty(submissions[1][0].payload, 'privacyAndSecurityPermission');
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('captures the permission snapshot before a delayed event is queued', () => {
|
|
258
|
+
webex.internal.newMetrics.setPrivacyAndSecurityPermission(permission);
|
|
259
|
+
webex.internal.newMetrics.setDelaySubmitClientEvents({shouldDelay: true});
|
|
260
|
+
webex.internal.newMetrics.submitClientEvent({name: 'client.call.initiated'});
|
|
261
|
+
webex.internal.newMetrics.setPrivacyAndSecurityPermission({
|
|
262
|
+
camera: {status: 'DENIED' as const},
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
const submission =
|
|
266
|
+
webex.internal.newMetrics.callDiagnosticMetrics.submitClientEvent.firstCall.args[0];
|
|
267
|
+
|
|
268
|
+
assert.isTrue(submission.delaySubmitEvent);
|
|
269
|
+
assert.deepEqual(submission.payload.privacyAndSecurityPermission, {
|
|
270
|
+
camera: permission.camera,
|
|
271
|
+
microphone: permission.microphone,
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
153
276
|
it('submits feature Event successfully', () => {
|
|
154
277
|
webex.internal.newMetrics.submitFeatureEvent({
|
|
155
278
|
name: 'client.feature.meeting.summary',
|
|
@@ -159,12 +282,14 @@ describe('internal-plugin-metrics', () => {
|
|
|
159
282
|
payload: {
|
|
160
283
|
meetingSummaryInfo: {
|
|
161
284
|
featureName: 'syncSystemMuteStatus',
|
|
162
|
-
featureActions: [
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
285
|
+
featureActions: [
|
|
286
|
+
{
|
|
287
|
+
actionName: 'syncMeetingMicUnmuteStatusToSystem',
|
|
288
|
+
actionId: '14200',
|
|
289
|
+
isInitialValue: false,
|
|
290
|
+
clickCount: '1',
|
|
291
|
+
},
|
|
292
|
+
],
|
|
168
293
|
},
|
|
169
294
|
},
|
|
170
295
|
});
|
|
@@ -178,12 +303,14 @@ describe('internal-plugin-metrics', () => {
|
|
|
178
303
|
payload: {
|
|
179
304
|
meetingSummaryInfo: {
|
|
180
305
|
featureName: 'syncSystemMuteStatus',
|
|
181
|
-
featureActions: [
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
306
|
+
featureActions: [
|
|
307
|
+
{
|
|
308
|
+
actionName: 'syncMeetingMicUnmuteStatusToSystem',
|
|
309
|
+
actionId: '14200',
|
|
310
|
+
isInitialValue: false,
|
|
311
|
+
clickCount: '1',
|
|
312
|
+
},
|
|
313
|
+
],
|
|
187
314
|
},
|
|
188
315
|
},
|
|
189
316
|
options: {meetingId: '123'},
|
|
@@ -244,9 +371,9 @@ describe('internal-plugin-metrics', () => {
|
|
|
244
371
|
method: 'POST',
|
|
245
372
|
api: 'metrics',
|
|
246
373
|
resource: 'clientmetrics',
|
|
247
|
-
headers: {
|
|
374
|
+
headers: {'x-prelogin-userid': 'my-id'},
|
|
248
375
|
body: {},
|
|
249
|
-
qs: {
|
|
376
|
+
qs: {alias: true},
|
|
250
377
|
});
|
|
251
378
|
assert.calledWith(
|
|
252
379
|
webex.logger.log,
|
|
@@ -255,8 +382,8 @@ describe('internal-plugin-metrics', () => {
|
|
|
255
382
|
});
|
|
256
383
|
|
|
257
384
|
it('handles failed request correctly', async () => {
|
|
258
|
-
webex.request.rejects(new Error(
|
|
259
|
-
sinon.stub(Utils, 'generateCommonErrorMetadata').returns('formattedError')
|
|
385
|
+
webex.request.rejects(new Error('test error'));
|
|
386
|
+
sinon.stub(Utils, 'generateCommonErrorMetadata').returns('formattedError');
|
|
260
387
|
try {
|
|
261
388
|
await webex.internal.newMetrics.clientMetricsAliasUser({event: 'test'}, 'my-id');
|
|
262
389
|
} catch (err) {
|
|
@@ -338,19 +465,26 @@ describe('internal-plugin-metrics', () => {
|
|
|
338
465
|
sinon.assert.match(webex.internal.newMetrics.delaySubmitClientEvents, true);
|
|
339
466
|
sinon.assert.match(webex.internal.newMetrics.delayedClientEventsOverrides, {});
|
|
340
467
|
|
|
341
|
-
webex.internal.newMetrics.setDelaySubmitClientEvents({
|
|
468
|
+
webex.internal.newMetrics.setDelaySubmitClientEvents({
|
|
469
|
+
shouldDelay: false,
|
|
470
|
+
overrides: {foo: 'bar'},
|
|
471
|
+
});
|
|
342
472
|
|
|
343
|
-
assert.calledOnce(
|
|
344
|
-
|
|
473
|
+
assert.calledOnce(
|
|
474
|
+
webex.internal.newMetrics.callDiagnosticMetrics.submitDelayedClientEvents
|
|
475
|
+
);
|
|
476
|
+
assert.calledWith(
|
|
477
|
+
webex.internal.newMetrics.callDiagnosticMetrics.submitDelayedClientEvents,
|
|
478
|
+
{foo: 'bar'}
|
|
479
|
+
);
|
|
345
480
|
|
|
346
481
|
sinon.assert.match(webex.internal.newMetrics.delaySubmitClientEvents, false);
|
|
347
482
|
sinon.assert.match(webex.internal.newMetrics.delayedClientEventsOverrides, {foo: 'bar'});
|
|
348
483
|
});
|
|
349
484
|
|
|
350
485
|
it('should not fail when called before webex is ready', () => {
|
|
351
|
-
|
|
352
486
|
// Create mock
|
|
353
|
-
webex = mockWebex()
|
|
487
|
+
webex = mockWebex();
|
|
354
488
|
|
|
355
489
|
webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp = sinon.stub();
|
|
356
490
|
webex.internal.newMetrics.callDiagnosticLatencies.clearTimestamps = sinon.stub();
|
|
@@ -365,7 +499,6 @@ describe('internal-plugin-metrics', () => {
|
|
|
365
499
|
webex.internal.newMetrics.setDelaySubmitClientEvents({shouldDelay: false});
|
|
366
500
|
// Webex is ready
|
|
367
501
|
webex.emit('ready');
|
|
368
|
-
|
|
369
502
|
});
|
|
370
503
|
});
|
|
371
504
|
});
|
|
@@ -64,45 +64,36 @@ describe('internal-plugin-metrics', () => {
|
|
|
64
64
|
//@ts-ignore
|
|
65
65
|
assert.calledOnce(webex.request);
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
networkType: 'unknown',
|
|
87
|
-
upgradeChannel: 'test',
|
|
88
|
-
},
|
|
89
|
-
originTime: {
|
|
90
|
-
sent: dateAfterBatcherWait.toISOString(),
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
type: ['diagnostic-event'],
|
|
94
|
-
},
|
|
95
|
-
],
|
|
67
|
+
assert.deepEqual(webexRequestArgs.headers, {
|
|
68
|
+
authorization: false,
|
|
69
|
+
'x-prelogin-userid': preLoginId,
|
|
70
|
+
});
|
|
71
|
+
assert.equal(webexRequestArgs.method, 'POST');
|
|
72
|
+
assert.equal(webexRequestArgs.resource, 'clientmetrics-prelogin');
|
|
73
|
+
assert.equal(webexRequestArgs.service, 'metrics');
|
|
74
|
+
assert.equal(webexRequestArgs.waitForServiceTimeout, 30);
|
|
75
|
+
|
|
76
|
+
assert.deepEqual(webexRequestArgs.body.metrics[0].eventPayload, {
|
|
77
|
+
event: {
|
|
78
|
+
joinTimes: {
|
|
79
|
+
meetingInfoReqResp: undefined,
|
|
80
|
+
clickToInterstitial: undefined,
|
|
81
|
+
refreshCaptchaServiceReqResp: undefined,
|
|
82
|
+
downloadIntelligenceModelsReqResp: undefined,
|
|
83
|
+
clickToInterstitialWithUserDelay: undefined,
|
|
84
|
+
},
|
|
85
|
+
name: 'client.interstitial-window.launched',
|
|
96
86
|
},
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
'
|
|
87
|
+
origin: {
|
|
88
|
+
buildType: 'test',
|
|
89
|
+
networkType: 'unknown',
|
|
90
|
+
upgradeChannel: 'test',
|
|
91
|
+
},
|
|
92
|
+
originTime: {
|
|
93
|
+
sent: dateAfterBatcherWait.toISOString(),
|
|
100
94
|
},
|
|
101
|
-
method: 'POST',
|
|
102
|
-
resource: 'clientmetrics-prelogin',
|
|
103
|
-
service: 'metrics',
|
|
104
|
-
waitForServiceTimeout: 30,
|
|
105
95
|
});
|
|
96
|
+
assert.deepEqual(webexRequestArgs.body.metrics[0].type, ['diagnostic-event']);
|
|
106
97
|
assert.lengthOf(
|
|
107
98
|
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.queue,
|
|
108
99
|
0
|
|
@@ -320,5 +311,49 @@ describe('internal-plugin-metrics', () => {
|
|
|
320
311
|
);
|
|
321
312
|
});
|
|
322
313
|
});
|
|
314
|
+
|
|
315
|
+
describe('#submitHttpRequest', () => {
|
|
316
|
+
it('calls webex.request with the correct parameters', async () => {
|
|
317
|
+
const payload = [
|
|
318
|
+
{
|
|
319
|
+
eventPayload: {event: 'my.event'},
|
|
320
|
+
type: ['diagnostic-event'],
|
|
321
|
+
},
|
|
322
|
+
];
|
|
323
|
+
|
|
324
|
+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.savePreLoginId(
|
|
325
|
+
preLoginId
|
|
326
|
+
);
|
|
327
|
+
webex.request = sinon.stub().resolves({statusCode: 200});
|
|
328
|
+
|
|
329
|
+
const promise =
|
|
330
|
+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.submitHttpRequest(
|
|
331
|
+
payload
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
await flushPromises();
|
|
335
|
+
|
|
336
|
+
clock.tick(config.metrics.batcherWait);
|
|
337
|
+
|
|
338
|
+
await promise;
|
|
339
|
+
|
|
340
|
+
const webexRequestArgs = webex.request.args[0][0];
|
|
341
|
+
|
|
342
|
+
assert.match(webexRequestArgs, {
|
|
343
|
+
//@ts-ignore
|
|
344
|
+
body: {
|
|
345
|
+
metrics: payload,
|
|
346
|
+
},
|
|
347
|
+
headers: {
|
|
348
|
+
authorization: false,
|
|
349
|
+
'x-prelogin-userid': preLoginId,
|
|
350
|
+
},
|
|
351
|
+
method: 'POST',
|
|
352
|
+
resource: 'clientmetrics-prelogin',
|
|
353
|
+
service: 'metrics',
|
|
354
|
+
waitForServiceTimeout: 30,
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
});
|
|
323
358
|
});
|
|
324
359
|
});
|