@webex/internal-plugin-metrics 3.7.0 → 3.8.0-next.10
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/business-metrics.js +74 -100
- package/dist/business-metrics.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +24 -15
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.js +76 -10
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
- package/dist/call-diagnostic/config.js +19 -12
- package/dist/call-diagnostic/config.js.map +1 -1
- package/dist/generic-metrics.js +2 -2
- package/dist/generic-metrics.js.map +1 -1
- 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 +28 -5
- package/dist/new-metrics.js.map +1 -1
- package/dist/types/business-metrics.d.ts +10 -28
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +14 -1
- package/dist/types/call-diagnostic/config.d.ts +2 -0
- package/dist/types/generic-metrics.d.ts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/metrics.types.d.ts +17 -1
- package/dist/types/new-metrics.d.ts +15 -3
- package/package.json +12 -12
- package/src/business-metrics.ts +66 -76
- package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +36 -14
- package/src/call-diagnostic/call-diagnostic-metrics.ts +80 -3
- package/src/call-diagnostic/config.ts +8 -0
- package/src/generic-metrics.ts +2 -2
- package/src/index.ts +2 -0
- package/src/metrics.types.ts +21 -1
- package/src/new-metrics.ts +32 -4
- package/test/unit/spec/business/business-metrics.ts +2 -2
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +85 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +674 -32
- package/test/unit/spec/new-metrics.ts +23 -0
- package/dist/behavioral/behavioral-metrics.js +0 -199
- package/dist/behavioral/behavioral-metrics.js.map +0 -1
- package/dist/behavioral/config.js +0 -11
- package/dist/behavioral/config.js.map +0 -1
- package/dist/types/behavioral/behavioral-metrics.d.ts +0 -63
- package/dist/types/behavioral/config.d.ts +0 -1
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
ClientEventPayloadError,
|
|
41
41
|
ClientSubServiceType,
|
|
42
42
|
BrowserLaunchMethodType,
|
|
43
|
+
DelayedClientEvent,
|
|
43
44
|
} from '../metrics.types';
|
|
44
45
|
import CallDiagnosticEventsBatcher from './call-diagnostic-metrics-batcher';
|
|
45
46
|
import PreLoginMetricsBatcher from '../prelogin-metrics-batcher';
|
|
@@ -95,6 +96,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
95
96
|
private logger: any; // to avoid adding @ts-ignore everywhere
|
|
96
97
|
private hasLoggedBrowserSerial: boolean;
|
|
97
98
|
private device: any;
|
|
99
|
+
private delayedClientEvents: DelayedClientEvent[] = [];
|
|
98
100
|
|
|
99
101
|
// the default validator before piping an event to the batcher
|
|
100
102
|
// this function can be overridden by the user
|
|
@@ -164,7 +166,15 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
164
166
|
if (meetingInfo?.webexScheduled && !meetingInfo?.enableEvent && !meetingInfo?.pmr) {
|
|
165
167
|
return WEBEX_SUB_SERVICE_TYPES.SCHEDULED_MEETING;
|
|
166
168
|
}
|
|
167
|
-
|
|
169
|
+
|
|
170
|
+
// if ConvergedArchitecture enable and isConvergedWebinarWebcast -- then webcast
|
|
171
|
+
if (meetingInfo?.enableConvergedArchitecture && meetingInfo?.enableEvent) {
|
|
172
|
+
return meetingInfo?.isConvergedWebinarWebcast
|
|
173
|
+
? WEBEX_SUB_SERVICE_TYPES.WEBCAST
|
|
174
|
+
: WEBEX_SUB_SERVICE_TYPES.WEBINAR;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// if Scheduled, enable event, not pmr - then Webinar
|
|
168
178
|
if (meetingInfo?.webexScheduled && meetingInfo?.enableEvent && !meetingInfo?.pmr) {
|
|
169
179
|
return WEBEX_SUB_SERVICE_TYPES.WEBINAR;
|
|
170
180
|
}
|
|
@@ -377,7 +387,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
377
387
|
* @returns
|
|
378
388
|
*/
|
|
379
389
|
prepareDiagnosticEvent(eventData: Event['event'], options: any) {
|
|
380
|
-
const {meetingId} = options;
|
|
390
|
+
const {meetingId, triggeredTime} = options;
|
|
381
391
|
const origin = this.getOrigin(options, meetingId);
|
|
382
392
|
|
|
383
393
|
const event: Event = {
|
|
@@ -385,7 +395,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
385
395
|
version: 1,
|
|
386
396
|
origin,
|
|
387
397
|
originTime: {
|
|
388
|
-
triggered: new Date().toISOString(),
|
|
398
|
+
triggered: triggeredTime || new Date().toISOString(),
|
|
389
399
|
// is overridden in prepareRequest batcher
|
|
390
400
|
sent: 'not_defined_yet',
|
|
391
401
|
},
|
|
@@ -715,13 +725,25 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
715
725
|
isConvergedArchitectureEnabled: this.getIsConvergedArchitectureEnabled({
|
|
716
726
|
meetingId,
|
|
717
727
|
}),
|
|
728
|
+
...(meeting.userNameInput && {userNameInput: meeting.userNameInput}),
|
|
729
|
+
...(meeting.emailInput && {emailInput: meeting.emailInput}),
|
|
718
730
|
webexSubServiceType: this.getSubServiceType(meeting),
|
|
731
|
+
// @ts-ignore
|
|
732
|
+
webClientPreload: this.webex.meetings?.config?.metrics?.webClientPreload,
|
|
719
733
|
};
|
|
720
734
|
|
|
721
735
|
const joinFlowVersion = options.joinFlowVersion ?? meeting.callStateForMetrics?.joinFlowVersion;
|
|
722
736
|
if (joinFlowVersion) {
|
|
723
737
|
clientEventObject.joinFlowVersion = joinFlowVersion;
|
|
724
738
|
}
|
|
739
|
+
const meetingJoinedTime = meeting.isoLocalClientMeetingJoinTime;
|
|
740
|
+
if (meetingJoinedTime) {
|
|
741
|
+
clientEventObject.meetingJoinedTime = meetingJoinedTime;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
if (options.meetingJoinPhase) {
|
|
745
|
+
clientEventObject.meetingJoinPhase = options.meetingJoinPhase;
|
|
746
|
+
}
|
|
725
747
|
|
|
726
748
|
return clientEventObject;
|
|
727
749
|
}
|
|
@@ -764,12 +786,26 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
764
786
|
webClientDomain: window.location.hostname,
|
|
765
787
|
},
|
|
766
788
|
loginType: this.getCurLoginType(),
|
|
789
|
+
// @ts-ignore
|
|
790
|
+
webClientPreload: this.webex.meetings?.config?.metrics?.webClientPreload,
|
|
767
791
|
};
|
|
768
792
|
|
|
769
793
|
if (options.joinFlowVersion) {
|
|
770
794
|
clientEventObject.joinFlowVersion = options.joinFlowVersion;
|
|
771
795
|
}
|
|
772
796
|
|
|
797
|
+
if (options.meetingJoinPhase) {
|
|
798
|
+
clientEventObject.meetingJoinPhase = options.meetingJoinPhase;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
if (options.userNameInput) {
|
|
802
|
+
clientEventObject.userNameInput = options.userNameInput;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
if (options.emailInput) {
|
|
806
|
+
clientEventObject.emailInput = options.emailInput;
|
|
807
|
+
}
|
|
808
|
+
|
|
773
809
|
return clientEventObject;
|
|
774
810
|
}
|
|
775
811
|
|
|
@@ -834,17 +870,36 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
834
870
|
* @param arg.event - event key
|
|
835
871
|
* @param arg.payload - additional payload to be merged with default payload
|
|
836
872
|
* @param arg.options - payload
|
|
873
|
+
* @param arg.delaySubmitEvent - a boolean value indicating whether to delay the submission of client events.
|
|
837
874
|
* @throws
|
|
838
875
|
*/
|
|
839
876
|
public submitClientEvent({
|
|
840
877
|
name,
|
|
841
878
|
payload,
|
|
842
879
|
options,
|
|
880
|
+
delaySubmitEvent,
|
|
843
881
|
}: {
|
|
844
882
|
name: ClientEvent['name'];
|
|
845
883
|
payload?: ClientEventPayload;
|
|
846
884
|
options?: SubmitClientEventOptions;
|
|
885
|
+
delaySubmitEvent?: boolean;
|
|
847
886
|
}) {
|
|
887
|
+
if (delaySubmitEvent) {
|
|
888
|
+
// Preserve the time when the event was triggered if delaying the submission to Call Diagnostics
|
|
889
|
+
const delayedOptions = {
|
|
890
|
+
...options,
|
|
891
|
+
triggeredTime: new Date().toISOString(),
|
|
892
|
+
};
|
|
893
|
+
|
|
894
|
+
this.delayedClientEvents.push({
|
|
895
|
+
name,
|
|
896
|
+
payload,
|
|
897
|
+
options: delayedOptions,
|
|
898
|
+
});
|
|
899
|
+
|
|
900
|
+
return Promise.resolve();
|
|
901
|
+
}
|
|
902
|
+
|
|
848
903
|
this.logger.log(
|
|
849
904
|
CALL_DIAGNOSTIC_LOG_IDENTIFIER,
|
|
850
905
|
'CallDiagnosticMetrics: @submitClientEvent. Submit Client Event CA event.',
|
|
@@ -861,6 +916,28 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
861
916
|
return this.submitToCallDiagnostics(diagnosticEvent);
|
|
862
917
|
}
|
|
863
918
|
|
|
919
|
+
/**
|
|
920
|
+
* Submit Delayed Client Event CA events. Clears delayedClientEvents array after submission.
|
|
921
|
+
*/
|
|
922
|
+
public submitDelayedClientEvents() {
|
|
923
|
+
this.logger.log(
|
|
924
|
+
CALL_DIAGNOSTIC_LOG_IDENTIFIER,
|
|
925
|
+
'CallDiagnosticMetrics: @submitDelayedClientEvents. Submitting delayed client events.'
|
|
926
|
+
);
|
|
927
|
+
|
|
928
|
+
if (this.delayedClientEvents.length === 0) {
|
|
929
|
+
return Promise.resolve();
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
const promises = this.delayedClientEvents.map((delayedSubmitClientEventParams) => {
|
|
933
|
+
return this.submitClientEvent(delayedSubmitClientEventParams);
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
this.delayedClientEvents = [];
|
|
937
|
+
|
|
938
|
+
return Promise.all(promises);
|
|
939
|
+
}
|
|
940
|
+
|
|
864
941
|
/**
|
|
865
942
|
* Prepare the event and send the request to metrics-a service.
|
|
866
943
|
* @param event
|
|
@@ -17,12 +17,14 @@ export const DTLS_HANDSHAKE_FAILED_CLIENT_CODE = 2008;
|
|
|
17
17
|
export const ICE_FAILED_WITH_TURN_TLS_CLIENT_CODE = 2010;
|
|
18
18
|
export const ICE_FAILED_WITHOUT_TURN_TLS_CLIENT_CODE = 2009;
|
|
19
19
|
export const ICE_AND_REACHABILITY_FAILED_CLIENT_CODE = 2011;
|
|
20
|
+
export const MULTISTREAM_NOT_AVAILABLE_CLIENT_CODE = 2012;
|
|
20
21
|
export const WBX_APP_API_URL = 'wbxappapi'; // MeetingInfo WebexAppApi response object normally contains a body.url that includes the string 'wbxappapi'
|
|
21
22
|
|
|
22
23
|
export const WEBEX_SUB_SERVICE_TYPES: Record<string, ClientSubServiceType> = {
|
|
23
24
|
PMR: 'PMR',
|
|
24
25
|
SCHEDULED_MEETING: 'ScheduledMeeting',
|
|
25
26
|
WEBINAR: 'Webinar',
|
|
27
|
+
WEBCAST: 'Webcast',
|
|
26
28
|
};
|
|
27
29
|
|
|
28
30
|
// Found in https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
|
|
@@ -127,6 +129,7 @@ export const ERROR_DESCRIPTIONS = {
|
|
|
127
129
|
ICE_FAILED_WITHOUT_TURN_TLS: 'ICEFailedWithoutTURN_TLS',
|
|
128
130
|
ICE_FAILED_WITH_TURN_TLS: 'ICEFailedWithTURN_TLS',
|
|
129
131
|
ICE_AND_REACHABILITY_FAILED: 'ICEAndReachabilityFailed',
|
|
132
|
+
MULTISTREAM_NOT_AVAILABLE: 'MultistreamNotAvailable',
|
|
130
133
|
SDP_OFFER_CREATION_ERROR: 'SdpOfferCreationError',
|
|
131
134
|
SDP_OFFER_CREATION_ERROR_MISSING_CODEC: 'SdpOfferCreationErrorMissingCodec',
|
|
132
135
|
WDM_RESTRICTED_REGION: 'WdmRestrictedRegion',
|
|
@@ -409,6 +412,11 @@ export const CLIENT_ERROR_CODE_TO_ERROR_PAYLOAD: Record<number, Partial<ClientEv
|
|
|
409
412
|
category: 'expected',
|
|
410
413
|
fatal: true,
|
|
411
414
|
},
|
|
415
|
+
[MULTISTREAM_NOT_AVAILABLE_CLIENT_CODE]: {
|
|
416
|
+
errorDescription: ERROR_DESCRIPTIONS.MULTISTREAM_NOT_AVAILABLE,
|
|
417
|
+
category: 'expected',
|
|
418
|
+
fatal: false,
|
|
419
|
+
},
|
|
412
420
|
2050: {
|
|
413
421
|
errorDescription: ERROR_DESCRIPTIONS.SDP_OFFER_CREATION_ERROR,
|
|
414
422
|
category: 'media',
|
package/src/generic-metrics.ts
CHANGED
|
@@ -37,7 +37,7 @@ export default abstract class GenericMetrics extends StatelessWebexPlugin {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
|
-
* Submit a
|
|
40
|
+
* Submit a business metric to our metrics endpoint.
|
|
41
41
|
* @param {string} kind of metric for logging
|
|
42
42
|
* @param {string} name of the metric
|
|
43
43
|
* @param {object} event
|
|
@@ -105,7 +105,7 @@ export default abstract class GenericMetrics extends StatelessWebexPlugin {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
|
-
* Returns true once we have the deviceId we need to submit behavioral/operational/
|
|
108
|
+
* Returns true once we have the deviceId we need to submit behavioral/operational/business events
|
|
109
109
|
* @returns {boolean}
|
|
110
110
|
*/
|
|
111
111
|
public isReadyToSubmitEvents(): boolean {
|
package/src/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
SubmitClientEvent,
|
|
16
16
|
SubmitInternalEvent,
|
|
17
17
|
SubmitOperationalEvent,
|
|
18
|
+
SubmitBusinessEvent,
|
|
18
19
|
SubmitMQE,
|
|
19
20
|
PreComputedLatencies,
|
|
20
21
|
} from './metrics.types';
|
|
@@ -58,5 +59,6 @@ export type {
|
|
|
58
59
|
SubmitInternalEvent,
|
|
59
60
|
SubmitMQE,
|
|
60
61
|
SubmitOperationalEvent,
|
|
62
|
+
SubmitBusinessEvent,
|
|
61
63
|
PreComputedLatencies,
|
|
62
64
|
};
|
package/src/metrics.types.ts
CHANGED
|
@@ -16,11 +16,15 @@ export type ClientLaunchMethodType = NonNullable<
|
|
|
16
16
|
RawEvent['origin']['clientInfo']
|
|
17
17
|
>['clientLaunchMethod'];
|
|
18
18
|
|
|
19
|
+
export type ClientUserNameInput = NonNullable<RawClientEvent['userNameInput']>;
|
|
20
|
+
|
|
21
|
+
export type ClientEmailInput = NonNullable<RawClientEvent['emailInput']>;
|
|
22
|
+
|
|
19
23
|
export type BrowserLaunchMethodType = NonNullable<
|
|
20
24
|
RawEvent['origin']['clientInfo']
|
|
21
25
|
>['browserLaunchMethod'];
|
|
22
26
|
|
|
23
|
-
export type MetricEventProduct = 'webex' | 'wxcc_desktop';
|
|
27
|
+
export type MetricEventProduct = 'webex' | 'wxcc_desktop' | 'wxcc_crm' | 'wxcc_sdk';
|
|
24
28
|
|
|
25
29
|
export type MetricEventAgent = 'user' | 'browser' | 'system' | 'sdk' | 'redux' | 'service' | 'api';
|
|
26
30
|
|
|
@@ -111,6 +115,7 @@ export type MetricEventVerb =
|
|
|
111
115
|
| 'exit';
|
|
112
116
|
|
|
113
117
|
export type MetricEventJoinFlowVersion = 'Other' | 'NewFTE';
|
|
118
|
+
export type MetricEventMeetingJoinPhase = 'pre-join' | 'join' | 'in-meeting';
|
|
114
119
|
|
|
115
120
|
export type SubmitClientEventOptions = {
|
|
116
121
|
meetingId?: string;
|
|
@@ -126,6 +131,10 @@ export type SubmitClientEventOptions = {
|
|
|
126
131
|
webexConferenceIdStr?: string;
|
|
127
132
|
globalMeetingId?: string;
|
|
128
133
|
joinFlowVersion?: MetricEventJoinFlowVersion;
|
|
134
|
+
meetingJoinPhase?: MetricEventMeetingJoinPhase;
|
|
135
|
+
triggeredTime?: string;
|
|
136
|
+
emailInput?: ClientEmailInput;
|
|
137
|
+
userNameInput?: ClientUserNameInput;
|
|
129
138
|
};
|
|
130
139
|
|
|
131
140
|
export type SubmitMQEOptions = {
|
|
@@ -278,6 +287,11 @@ export type SubmitOperationalEvent = (args: {
|
|
|
278
287
|
payload: EventPayload;
|
|
279
288
|
}) => void;
|
|
280
289
|
|
|
290
|
+
export type SubmitBusinessEvent = (args: {
|
|
291
|
+
name: OperationalEvent['metricName'];
|
|
292
|
+
payload: EventPayload;
|
|
293
|
+
}) => void;
|
|
294
|
+
|
|
281
295
|
export type SubmitMQE = (args: {
|
|
282
296
|
name: MediaQualityEvent['name'];
|
|
283
297
|
payload: SubmitMQEPayload;
|
|
@@ -317,3 +331,9 @@ export interface IMetricsAttributes {
|
|
|
317
331
|
meetingId?: string;
|
|
318
332
|
callId?: string;
|
|
319
333
|
}
|
|
334
|
+
|
|
335
|
+
export interface DelayedClientEvent {
|
|
336
|
+
name: ClientEvent['name'];
|
|
337
|
+
payload?: RecursivePartial<ClientEvent['payload']>;
|
|
338
|
+
options?: SubmitClientEventOptions;
|
|
339
|
+
}
|
package/src/new-metrics.ts
CHANGED
|
@@ -45,6 +45,11 @@ class Metrics extends WebexPlugin {
|
|
|
45
45
|
businessMetrics: BusinessMetrics;
|
|
46
46
|
isReady = false;
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Whether or not to delay the submission of client events.
|
|
50
|
+
*/
|
|
51
|
+
delaySubmitClientEvents = false;
|
|
52
|
+
|
|
48
53
|
/**
|
|
49
54
|
* Constructor
|
|
50
55
|
* @param args
|
|
@@ -141,7 +146,7 @@ class Metrics extends WebexPlugin {
|
|
|
141
146
|
}
|
|
142
147
|
|
|
143
148
|
/**
|
|
144
|
-
* @returns true once we have the deviceId we need to submit
|
|
149
|
+
* @returns true once we have the deviceId we need to submit business events
|
|
145
150
|
*/
|
|
146
151
|
isReadyToSubmitBusinessEvents() {
|
|
147
152
|
this.lazyBuildBusinessMetrics();
|
|
@@ -200,17 +205,19 @@ class Metrics extends WebexPlugin {
|
|
|
200
205
|
}
|
|
201
206
|
|
|
202
207
|
/**
|
|
203
|
-
*
|
|
208
|
+
* Business event
|
|
204
209
|
* @param args
|
|
205
210
|
*/
|
|
206
211
|
submitBusinessEvent({
|
|
207
212
|
name,
|
|
208
213
|
payload,
|
|
209
214
|
table,
|
|
215
|
+
metadata,
|
|
210
216
|
}: {
|
|
211
217
|
name: string;
|
|
212
218
|
payload: EventPayload;
|
|
213
219
|
table?: Table;
|
|
220
|
+
metadata?: EventPayload;
|
|
214
221
|
}) {
|
|
215
222
|
if (!this.isReady) {
|
|
216
223
|
// @ts-ignore
|
|
@@ -223,7 +230,7 @@ class Metrics extends WebexPlugin {
|
|
|
223
230
|
|
|
224
231
|
this.lazyBuildBusinessMetrics();
|
|
225
232
|
|
|
226
|
-
return this.businessMetrics.submitBusinessEvent({name, payload, table});
|
|
233
|
+
return this.businessMetrics.submitBusinessEvent({name, payload, table, metadata});
|
|
227
234
|
}
|
|
228
235
|
|
|
229
236
|
/**
|
|
@@ -288,7 +295,12 @@ class Metrics extends WebexPlugin {
|
|
|
288
295
|
options: {meetingId: options?.meetingId},
|
|
289
296
|
});
|
|
290
297
|
|
|
291
|
-
return this.callDiagnosticMetrics.submitClientEvent({
|
|
298
|
+
return this.callDiagnosticMetrics.submitClientEvent({
|
|
299
|
+
name,
|
|
300
|
+
payload,
|
|
301
|
+
options,
|
|
302
|
+
delaySubmitEvent: this.delaySubmitClientEvents,
|
|
303
|
+
});
|
|
292
304
|
}
|
|
293
305
|
|
|
294
306
|
/**
|
|
@@ -387,6 +399,22 @@ class Metrics extends WebexPlugin {
|
|
|
387
399
|
public isServiceErrorExpected(serviceErrorCode: number): boolean {
|
|
388
400
|
return this.callDiagnosticMetrics.isServiceErrorExpected(serviceErrorCode);
|
|
389
401
|
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Sets the value of delaySubmitClientEvents. If set to true, client events will be delayed until submitDelayedClientEvents is called. If
|
|
405
|
+
* set to false, delayed client events will be submitted.
|
|
406
|
+
*
|
|
407
|
+
* @param {boolean} shouldDelay - A boolean value indicating whether to delay the submission of client events.
|
|
408
|
+
*/
|
|
409
|
+
public setDelaySubmitClientEvents(shouldDelay: boolean) {
|
|
410
|
+
this.delaySubmitClientEvents = shouldDelay;
|
|
411
|
+
|
|
412
|
+
if (!shouldDelay) {
|
|
413
|
+
return this.callDiagnosticMetrics.submitDelayedClientEvents();
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return Promise.resolve();
|
|
417
|
+
}
|
|
390
418
|
}
|
|
391
419
|
|
|
392
420
|
export default Metrics;
|
|
@@ -154,11 +154,12 @@ describe('internal-plugin-metrics', () => {
|
|
|
154
154
|
businessMetrics.clientMetricsBatcher.request = request;
|
|
155
155
|
|
|
156
156
|
assert.equal(requestCalls.length, 0)
|
|
157
|
-
businessMetrics.submitBusinessEvent({ name: "foobar", payload: {bar:"gee"}, table: 'business_metrics' })
|
|
157
|
+
businessMetrics.submitBusinessEvent({ name: "foobar", payload: {bar: "gee"}, table: 'business_metrics', metadata: {asdf: 'hjkl'} })
|
|
158
158
|
assert.equal(requestCalls.length, 1)
|
|
159
159
|
assert.deepEqual(requestCalls[0], {
|
|
160
160
|
eventPayload: {
|
|
161
161
|
key: 'foobar',
|
|
162
|
+
asdf: 'hjkl',
|
|
162
163
|
appType: 'Web Client',
|
|
163
164
|
client_timestamp: requestCalls[0].eventPayload.client_timestamp, // This is to bypass time check, which is checked below.
|
|
164
165
|
value: {
|
|
@@ -173,7 +174,6 @@ describe('internal-plugin-metrics', () => {
|
|
|
173
174
|
os: getOSNameInternal(),
|
|
174
175
|
app: {version: 'webex-version'},
|
|
175
176
|
device: {id: 'deviceId'},
|
|
176
|
-
locale: 'language',
|
|
177
177
|
}
|
|
178
178
|
},
|
|
179
179
|
type: ['business'],
|
|
@@ -283,6 +283,18 @@ describe('internal-plugin-metrics', () => {
|
|
|
283
283
|
cdl.saveTimestamp({key: 'internal.client.meetinginfo.response', value: 20});
|
|
284
284
|
assert.deepEqual(saveFirstTimestamp.callCount, 1);
|
|
285
285
|
});
|
|
286
|
+
|
|
287
|
+
it('calls saveFirstTimestamp for remote SDP received', () => {
|
|
288
|
+
const saveFirstTimestamp = sinon.stub(cdl, 'saveFirstTimestampOnly');
|
|
289
|
+
cdl.saveTimestamp({key: 'client.media-engine.remote-sdp-received', value: 10});
|
|
290
|
+
assert.deepEqual(saveFirstTimestamp.callCount, 1);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it('clears timestamp for remote SDP received when local SDP generated', () => {
|
|
294
|
+
cdl.saveTimestamp({key: 'client.media-engine.remote-sdp-received', value: 10});
|
|
295
|
+
cdl.saveTimestamp({key: 'client.media-engine.local-sdp-generated', value: 20});
|
|
296
|
+
assert.isUndefined(cdl.latencyTimestamps.get('client.media-engine.remote-sdp-received'));
|
|
297
|
+
});
|
|
286
298
|
});
|
|
287
299
|
|
|
288
300
|
it('calculates getShowInterstitialTime correctly', () => {
|
|
@@ -425,6 +437,15 @@ describe('internal-plugin-metrics', () => {
|
|
|
425
437
|
assert.deepEqual(cdl.getClickToInterstitial(), 5);
|
|
426
438
|
});
|
|
427
439
|
|
|
440
|
+
it('calculates getClickToInterstitial without join button timestamp when it is 0', () => {
|
|
441
|
+
cdl.saveLatency('internal.click.to.interstitial', 0);
|
|
442
|
+
cdl.saveTimestamp({
|
|
443
|
+
key: 'internal.client.meeting.interstitial-window.showed',
|
|
444
|
+
value: 20,
|
|
445
|
+
});
|
|
446
|
+
assert.deepEqual(cdl.getClickToInterstitial(), 0);
|
|
447
|
+
});
|
|
448
|
+
|
|
428
449
|
it('calculates getInterstitialToJoinOK correctly', () => {
|
|
429
450
|
cdl.saveTimestamp({
|
|
430
451
|
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
@@ -437,6 +458,18 @@ describe('internal-plugin-metrics', () => {
|
|
|
437
458
|
assert.deepEqual(cdl.getInterstitialToJoinOK(), 10);
|
|
438
459
|
});
|
|
439
460
|
|
|
461
|
+
it('calculates getInterstitialToJoinOK correctly when one value is not a number', () => {
|
|
462
|
+
cdl.saveTimestamp({
|
|
463
|
+
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
464
|
+
value: 'ten' as unknown as number,
|
|
465
|
+
});
|
|
466
|
+
cdl.saveTimestamp({
|
|
467
|
+
key: 'client.locus.join.response',
|
|
468
|
+
value: 20,
|
|
469
|
+
});
|
|
470
|
+
assert.deepEqual(cdl.getInterstitialToJoinOK(), undefined);
|
|
471
|
+
});
|
|
472
|
+
|
|
440
473
|
it('calculates getCallInitMediaEngineReady correctly', () => {
|
|
441
474
|
cdl.saveTimestamp({
|
|
442
475
|
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
@@ -469,6 +502,58 @@ describe('internal-plugin-metrics', () => {
|
|
|
469
502
|
assert.deepEqual(cdl.getTotalJMT(), 45);
|
|
470
503
|
});
|
|
471
504
|
|
|
505
|
+
it('calculates getTotalJMT correctly when clickToInterstitial is 0', () => {
|
|
506
|
+
cdl.saveLatency('internal.click.to.interstitial', 0);
|
|
507
|
+
cdl.saveTimestamp({
|
|
508
|
+
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
509
|
+
value: 20,
|
|
510
|
+
});
|
|
511
|
+
cdl.saveTimestamp({
|
|
512
|
+
key: 'client.locus.join.response',
|
|
513
|
+
value: 40,
|
|
514
|
+
});
|
|
515
|
+
assert.deepEqual(cdl.getTotalJMT(), 20);
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
it('calculates getTotalJMT correctly when interstitialToJoinOk is 0', () => {
|
|
519
|
+
cdl.saveTimestamp({
|
|
520
|
+
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
521
|
+
value: 40,
|
|
522
|
+
});
|
|
523
|
+
cdl.saveLatency('internal.click.to.interstitial', 12);
|
|
524
|
+
cdl.saveTimestamp({
|
|
525
|
+
key: 'client.locus.join.response',
|
|
526
|
+
value: 40,
|
|
527
|
+
});
|
|
528
|
+
assert.deepEqual(cdl.getTotalJMT(), 12);
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
it('calculates getTotalJMT correctly when both clickToInterstitial and interstitialToJoinOk are 0', () => {
|
|
532
|
+
cdl.saveTimestamp({
|
|
533
|
+
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
534
|
+
value: 40,
|
|
535
|
+
});
|
|
536
|
+
cdl.saveLatency('internal.click.to.interstitial', 0);
|
|
537
|
+
cdl.saveTimestamp({
|
|
538
|
+
key: 'client.locus.join.response',
|
|
539
|
+
value: 40,
|
|
540
|
+
});
|
|
541
|
+
assert.deepEqual(cdl.getTotalJMT(), 0);
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
it('calculates getTotalJMT correctly when both clickToInterstitial is not a number', () => {
|
|
545
|
+
cdl.saveTimestamp({
|
|
546
|
+
key: 'internal.client.interstitial-window.click.joinbutton',
|
|
547
|
+
value: 40,
|
|
548
|
+
});
|
|
549
|
+
cdl.saveLatency('internal.click.to.interstitial', 'eleven' as unknown as number);
|
|
550
|
+
cdl.saveTimestamp({
|
|
551
|
+
key: 'client.locus.join.response',
|
|
552
|
+
value: 40,
|
|
553
|
+
});
|
|
554
|
+
assert.deepEqual(cdl.getTotalJMT(), undefined);
|
|
555
|
+
});
|
|
556
|
+
|
|
472
557
|
it('calculates getTotalMediaJMT correctly', () => {
|
|
473
558
|
cdl.saveTimestamp({
|
|
474
559
|
key: 'internal.client.meeting.click.joinbutton',
|