@webex/internal-plugin-metrics 3.8.1 → 3.9.0-webinar5k.1
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/call-diagnostic/call-diagnostic-metrics-latencies.js +49 -0
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.js +218 -48
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js +6 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
- package/dist/call-diagnostic/config.js +3 -1
- package/dist/call-diagnostic/config.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 +43 -1
- package/dist/new-metrics.js.map +1 -1
- package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +15 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +144 -9
- package/dist/types/call-diagnostic/config.d.ts +2 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/metrics.types.d.ts +17 -6
- package/dist/types/new-metrics.d.ts +19 -2
- package/package.json +12 -12
- package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +58 -0
- package/src/call-diagnostic/call-diagnostic-metrics.ts +219 -25
- package/src/call-diagnostic/call-diagnostic-metrics.util.ts +6 -0
- package/src/call-diagnostic/config.ts +3 -0
- package/src/index.ts +2 -0
- package/src/metrics.types.ts +22 -5
- package/src/new-metrics.ts +52 -1
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +20 -1
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +167 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +425 -38
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +6 -0
- package/test/unit/spec/new-metrics.ts +67 -2
- package/test/unit/spec/prelogin-metrics-batcher.ts +1 -0
- package/dist/call-diagnostic-events-batcher.js +0 -60
- package/dist/call-diagnostic-events-batcher.js.map +0 -1
|
@@ -41,6 +41,9 @@ import {
|
|
|
41
41
|
ClientSubServiceType,
|
|
42
42
|
BrowserLaunchMethodType,
|
|
43
43
|
DelayedClientEvent,
|
|
44
|
+
DelayedClientFeatureEvent,
|
|
45
|
+
FeatureEvent,
|
|
46
|
+
ClientFeatureEventPayload,
|
|
44
47
|
} from '../metrics.types';
|
|
45
48
|
import CallDiagnosticEventsBatcher from './call-diagnostic-metrics-batcher';
|
|
46
49
|
import PreLoginMetricsBatcher from '../prelogin-metrics-batcher';
|
|
@@ -58,6 +61,8 @@ import {
|
|
|
58
61
|
AUTHENTICATION_FAILED_CODE,
|
|
59
62
|
WEBEX_SUB_SERVICE_TYPES,
|
|
60
63
|
SDP_OFFER_CREATION_ERROR_MAP,
|
|
64
|
+
CALL_FEATURE_LOG_IDENTIFIER,
|
|
65
|
+
CALL_FEATURE_EVENT_FAILED_TO_SEND,
|
|
61
66
|
} from './config';
|
|
62
67
|
|
|
63
68
|
const {getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
|
|
@@ -97,7 +102,9 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
97
102
|
private hasLoggedBrowserSerial: boolean;
|
|
98
103
|
private device: any;
|
|
99
104
|
private delayedClientEvents: DelayedClientEvent[] = [];
|
|
105
|
+
private delayedClientFeatureEvents: DelayedClientFeatureEvent[] = [];
|
|
100
106
|
private eventErrorCache: WeakMap<any, any> = new WeakMap();
|
|
107
|
+
private isMercuryConnected = false;
|
|
101
108
|
|
|
102
109
|
// the default validator before piping an event to the batcher
|
|
103
110
|
// this function can be overridden by the user
|
|
@@ -150,6 +157,16 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
150
157
|
return undefined;
|
|
151
158
|
}
|
|
152
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Sets mercury connected status for event data object in CA events
|
|
162
|
+
* @public
|
|
163
|
+
* @param status - boolean value indicating mercury connection status
|
|
164
|
+
* @return {void}
|
|
165
|
+
*/
|
|
166
|
+
public setMercuryConnectedStatus(status: boolean): void {
|
|
167
|
+
this.isMercuryConnected = status;
|
|
168
|
+
}
|
|
169
|
+
|
|
153
170
|
/**
|
|
154
171
|
* Returns meeting's subServiceType
|
|
155
172
|
* @param meeting
|
|
@@ -416,12 +433,97 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
416
433
|
}
|
|
417
434
|
|
|
418
435
|
/**
|
|
419
|
-
*
|
|
436
|
+
* Create feature event
|
|
437
|
+
* @param name
|
|
438
|
+
* @param payload
|
|
439
|
+
* @param options
|
|
440
|
+
* @returns
|
|
441
|
+
*/
|
|
442
|
+
private prepareClientFeatureEvent({
|
|
443
|
+
name,
|
|
444
|
+
payload,
|
|
445
|
+
options,
|
|
446
|
+
}: {
|
|
447
|
+
name: FeatureEvent['name'];
|
|
448
|
+
payload?: ClientFeatureEventPayload;
|
|
449
|
+
options?: SubmitClientEventOptions;
|
|
450
|
+
}) {
|
|
451
|
+
const {meetingId, correlationId} = options;
|
|
452
|
+
let featureEventObject: FeatureEvent['payload'];
|
|
453
|
+
|
|
454
|
+
// events that will most likely happen in join phase
|
|
455
|
+
if (meetingId) {
|
|
456
|
+
featureEventObject = this.createFeatureEventObjectInMeeting({name, options});
|
|
457
|
+
} else {
|
|
458
|
+
throw new Error('Not implemented');
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// merge any new properties, or override existing ones
|
|
462
|
+
featureEventObject = merge(featureEventObject, payload);
|
|
463
|
+
|
|
464
|
+
// append client event data to the call diagnostic event
|
|
465
|
+
const featureEvent = this.prepareDiagnosticEvent(featureEventObject, options);
|
|
466
|
+
|
|
467
|
+
return featureEvent;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
420
471
|
* Submit Feature Event
|
|
472
|
+
* submit to business_ucf
|
|
421
473
|
* @returns
|
|
422
474
|
*/
|
|
423
|
-
public submitFeatureEvent(
|
|
424
|
-
|
|
475
|
+
public submitFeatureEvent({
|
|
476
|
+
name,
|
|
477
|
+
payload,
|
|
478
|
+
options,
|
|
479
|
+
delaySubmitEvent,
|
|
480
|
+
}: {
|
|
481
|
+
name: FeatureEvent['name'];
|
|
482
|
+
payload?: ClientFeatureEventPayload;
|
|
483
|
+
options?: SubmitClientEventOptions;
|
|
484
|
+
delaySubmitEvent?: boolean;
|
|
485
|
+
}) {
|
|
486
|
+
if (delaySubmitEvent) {
|
|
487
|
+
// Preserve the time when the event was triggered if delaying the submission to Call Features
|
|
488
|
+
const delayedOptions = {
|
|
489
|
+
...options,
|
|
490
|
+
triggeredTime: new Date().toISOString(),
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
this.delayedClientFeatureEvents.push({
|
|
494
|
+
name,
|
|
495
|
+
payload,
|
|
496
|
+
options: delayedOptions,
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
return Promise.resolve();
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
this.logger.log(
|
|
503
|
+
CALL_FEATURE_LOG_IDENTIFIER,
|
|
504
|
+
'CallFeatureMetrics: @submitFeatureEvent. Submit Client Feature Event CA event.',
|
|
505
|
+
`name: ${name}`
|
|
506
|
+
);
|
|
507
|
+
const featureEvent = this.prepareClientFeatureEvent({name, payload, options});
|
|
508
|
+
|
|
509
|
+
this.validator({type: 'ce', event: featureEvent});
|
|
510
|
+
|
|
511
|
+
return this.submitToCallFeatures(featureEvent);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Submit Feature Event
|
|
516
|
+
* type is business
|
|
517
|
+
* @param event
|
|
518
|
+
*/
|
|
519
|
+
submitToCallFeatures(event: Event): Promise<any> {
|
|
520
|
+
// build metrics-a event type
|
|
521
|
+
const finalEvent = {
|
|
522
|
+
eventPayload: event,
|
|
523
|
+
type: ['business'],
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
return this.callDiagnosticEventsBatcher.request(finalEvent);
|
|
425
527
|
}
|
|
426
528
|
|
|
427
529
|
/**
|
|
@@ -680,20 +782,20 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
680
782
|
}
|
|
681
783
|
|
|
682
784
|
/**
|
|
683
|
-
* Create
|
|
684
|
-
* @param
|
|
685
|
-
* @param
|
|
686
|
-
* @param
|
|
785
|
+
* Create common object for in meeting events
|
|
786
|
+
* @param name
|
|
787
|
+
* @param options
|
|
788
|
+
* @param eventType - 'client' | 'feature'
|
|
687
789
|
* @returns object
|
|
688
790
|
*/
|
|
689
|
-
private
|
|
791
|
+
private createCommonEventObjectInMeeting({
|
|
690
792
|
name,
|
|
691
793
|
options,
|
|
692
|
-
|
|
794
|
+
eventType = 'client',
|
|
693
795
|
}: {
|
|
694
|
-
name:
|
|
796
|
+
name: string;
|
|
695
797
|
options?: SubmitClientEventOptions;
|
|
696
|
-
|
|
798
|
+
eventType?: 'client' | 'feature';
|
|
697
799
|
}) {
|
|
698
800
|
const {
|
|
699
801
|
meetingId,
|
|
@@ -708,16 +810,21 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
708
810
|
|
|
709
811
|
if (!meeting) {
|
|
710
812
|
console.warn(
|
|
711
|
-
'Attempt to send
|
|
813
|
+
'Attempt to send common event but no meeting was found...',
|
|
712
814
|
`name: ${name}, meetingId: ${meetingId}`
|
|
713
815
|
);
|
|
714
816
|
// @ts-ignore
|
|
715
|
-
this.webex.internal.metrics.submitClientMetrics(
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
817
|
+
this.webex.internal.metrics.submitClientMetrics(
|
|
818
|
+
eventType === 'feature'
|
|
819
|
+
? CALL_FEATURE_EVENT_FAILED_TO_SEND
|
|
820
|
+
: CALL_DIAGNOSTIC_EVENT_FAILED_TO_SEND,
|
|
821
|
+
{
|
|
822
|
+
fields: {
|
|
823
|
+
meetingId,
|
|
824
|
+
name,
|
|
825
|
+
},
|
|
826
|
+
}
|
|
827
|
+
);
|
|
721
828
|
|
|
722
829
|
return undefined;
|
|
723
830
|
}
|
|
@@ -731,12 +838,11 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
731
838
|
sessionCorrelationId,
|
|
732
839
|
});
|
|
733
840
|
|
|
734
|
-
// create
|
|
735
|
-
const
|
|
841
|
+
// create common event object structur
|
|
842
|
+
const commonEventObject = {
|
|
736
843
|
name,
|
|
737
844
|
canProceed: true,
|
|
738
845
|
identifiers,
|
|
739
|
-
errors,
|
|
740
846
|
eventData: {
|
|
741
847
|
webClientDomain: window.location.hostname,
|
|
742
848
|
},
|
|
@@ -757,18 +863,80 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
757
863
|
|
|
758
864
|
const joinFlowVersion = options.joinFlowVersion ?? meeting.callStateForMetrics?.joinFlowVersion;
|
|
759
865
|
if (joinFlowVersion) {
|
|
760
|
-
|
|
866
|
+
// @ts-ignore
|
|
867
|
+
commonEventObject.joinFlowVersion = joinFlowVersion;
|
|
761
868
|
}
|
|
762
869
|
const meetingJoinedTime = meeting.isoLocalClientMeetingJoinTime;
|
|
763
870
|
if (meetingJoinedTime) {
|
|
764
|
-
|
|
871
|
+
// @ts-ignore
|
|
872
|
+
commonEventObject.meetingJoinedTime = meetingJoinedTime;
|
|
765
873
|
}
|
|
766
874
|
|
|
767
875
|
if (options.meetingJoinPhase) {
|
|
768
|
-
|
|
876
|
+
// @ts-ignore
|
|
877
|
+
commonEventObject.meetingJoinPhase = options.meetingJoinPhase;
|
|
769
878
|
}
|
|
770
879
|
|
|
771
|
-
return
|
|
880
|
+
return commonEventObject;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/**
|
|
884
|
+
* Create client event object for in meeting events
|
|
885
|
+
* @param arg - create args
|
|
886
|
+
* @param arg.event - event key
|
|
887
|
+
* @param arg.options - options
|
|
888
|
+
* @returns object
|
|
889
|
+
*/
|
|
890
|
+
private createClientEventObjectInMeeting({
|
|
891
|
+
name,
|
|
892
|
+
options,
|
|
893
|
+
errors,
|
|
894
|
+
}: {
|
|
895
|
+
name: ClientEvent['name'];
|
|
896
|
+
options?: SubmitClientEventOptions;
|
|
897
|
+
errors?: ClientEventPayloadError;
|
|
898
|
+
}) {
|
|
899
|
+
const commonObject = this.createCommonEventObjectInMeeting({
|
|
900
|
+
name,
|
|
901
|
+
options,
|
|
902
|
+
eventType: 'client',
|
|
903
|
+
});
|
|
904
|
+
if (!commonObject) return undefined;
|
|
905
|
+
|
|
906
|
+
return {
|
|
907
|
+
...commonObject,
|
|
908
|
+
errors,
|
|
909
|
+
eventData: {
|
|
910
|
+
...commonObject.eventData,
|
|
911
|
+
isMercuryConnected: this.isMercuryConnected,
|
|
912
|
+
},
|
|
913
|
+
} as ClientEvent['payload'];
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/**
|
|
917
|
+
* Create feature event object for in meeting function event
|
|
918
|
+
* @param name
|
|
919
|
+
* @param options
|
|
920
|
+
* @returns object
|
|
921
|
+
*/
|
|
922
|
+
private createFeatureEventObjectInMeeting({
|
|
923
|
+
name,
|
|
924
|
+
options,
|
|
925
|
+
}: {
|
|
926
|
+
name: FeatureEvent['name'];
|
|
927
|
+
options?: SubmitClientEventOptions;
|
|
928
|
+
}) {
|
|
929
|
+
const commonObject = this.createCommonEventObjectInMeeting({
|
|
930
|
+
name,
|
|
931
|
+
options,
|
|
932
|
+
eventType: 'feature',
|
|
933
|
+
});
|
|
934
|
+
if (!commonObject) return undefined;
|
|
935
|
+
|
|
936
|
+
return {
|
|
937
|
+
...commonObject,
|
|
938
|
+
key: 'UcfFeatureUsage',
|
|
939
|
+
} as FeatureEvent['payload'];
|
|
772
940
|
}
|
|
773
941
|
|
|
774
942
|
/**
|
|
@@ -807,6 +975,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
807
975
|
identifiers,
|
|
808
976
|
eventData: {
|
|
809
977
|
webClientDomain: window.location.hostname,
|
|
978
|
+
isMercuryConnected: this.isMercuryConnected,
|
|
810
979
|
},
|
|
811
980
|
loginType: this.getCurLoginType(),
|
|
812
981
|
// @ts-ignore
|
|
@@ -964,6 +1133,31 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
964
1133
|
return Promise.all(promises);
|
|
965
1134
|
}
|
|
966
1135
|
|
|
1136
|
+
/**
|
|
1137
|
+
* Submit Delayed feature Event CA events. Clears submitDelayedClientFeatureEvents array after submission.
|
|
1138
|
+
*/
|
|
1139
|
+
public submitDelayedClientFeatureEvents(overrides?: Partial<DelayedClientEvent['options']>) {
|
|
1140
|
+
this.logger.log(
|
|
1141
|
+
CALL_FEATURE_LOG_IDENTIFIER,
|
|
1142
|
+
'CallDiagnosticMetrics: @submitDelayedClientFeatureEvents. Submitting delayed feature events.'
|
|
1143
|
+
);
|
|
1144
|
+
|
|
1145
|
+
if (this.delayedClientFeatureEvents.length === 0) {
|
|
1146
|
+
return Promise.resolve();
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
const promises = this.delayedClientFeatureEvents.map((delayedSubmitClientEventParams) => {
|
|
1150
|
+
const {name, payload, options} = delayedSubmitClientEventParams;
|
|
1151
|
+
const optionsWithOverrides: DelayedClientEvent['options'] = {...options, ...overrides};
|
|
1152
|
+
|
|
1153
|
+
return this.submitFeatureEvent({name, payload, options: optionsWithOverrides});
|
|
1154
|
+
});
|
|
1155
|
+
|
|
1156
|
+
this.delayedClientFeatureEvents = [];
|
|
1157
|
+
|
|
1158
|
+
return Promise.all(promises);
|
|
1159
|
+
}
|
|
1160
|
+
|
|
967
1161
|
/**
|
|
968
1162
|
* Prepare the event and send the request to metrics-a service.
|
|
969
1163
|
* @param event
|
|
@@ -257,6 +257,7 @@ export const prepareDiagnosticMetricItem = (webex: any, item: any) => {
|
|
|
257
257
|
switch (eventName) {
|
|
258
258
|
case 'client.webexapp.launched':
|
|
259
259
|
joinTimes.downloadTime = cdl.getDownloadTimeJMT();
|
|
260
|
+
joinTimes.pageJmt = cdl.getPageJMT();
|
|
260
261
|
break;
|
|
261
262
|
case 'client.login.end':
|
|
262
263
|
joinTimes.otherAppApiReqResp = cdl.getOtherAppApiReqResp();
|
|
@@ -267,6 +268,7 @@ export const prepareDiagnosticMetricItem = (webex: any, item: any) => {
|
|
|
267
268
|
joinTimes.clickToInterstitial = cdl.getClickToInterstitial();
|
|
268
269
|
joinTimes.refreshCaptchaServiceReqResp = cdl.getRefreshCaptchaReqResp();
|
|
269
270
|
joinTimes.downloadIntelligenceModelsReqResp = cdl.getDownloadIntelligenceModelsReqResp();
|
|
271
|
+
joinTimes.clickToInterstitialWithUserDelay = cdl.getClickToInterstitialWithUserDelay();
|
|
270
272
|
break;
|
|
271
273
|
|
|
272
274
|
case 'client.call.initiated':
|
|
@@ -287,6 +289,8 @@ export const prepareDiagnosticMetricItem = (webex: any, item: any) => {
|
|
|
287
289
|
joinTimes.totalJmt = cdl.getTotalJMT();
|
|
288
290
|
joinTimes.clientJmt = cdl.getClientJMT();
|
|
289
291
|
joinTimes.downloadTime = cdl.getDownloadTimeJMT();
|
|
292
|
+
joinTimes.clickToInterstitialWithUserDelay = cdl.getClickToInterstitialWithUserDelay();
|
|
293
|
+
joinTimes.totalJMTWithUserDelay = cdl.getTotalJMTWithUserDelay();
|
|
290
294
|
break;
|
|
291
295
|
|
|
292
296
|
case 'client.ice.end':
|
|
@@ -307,6 +311,8 @@ export const prepareDiagnosticMetricItem = (webex: any, item: any) => {
|
|
|
307
311
|
joinTimes.interstitialToMediaOKJMT = cdl.getInterstitialToMediaOKJMT();
|
|
308
312
|
joinTimes.callInitMediaEngineReady = cdl.getCallInitMediaEngineReady();
|
|
309
313
|
joinTimes.stayLobbyTime = cdl.getStayLobbyTime();
|
|
314
|
+
joinTimes.totalMediaJMTWithUserDelay = cdl.getTotalMediaJMTWithUserDelay();
|
|
315
|
+
joinTimes.totalJMTWithUserDelay = cdl.getTotalJMTWithUserDelay();
|
|
310
316
|
break;
|
|
311
317
|
|
|
312
318
|
case 'client.media.tx.start':
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import {ClientEventError, ClientSubServiceType} from '../metrics.types';
|
|
6
6
|
|
|
7
7
|
export const CALL_DIAGNOSTIC_LOG_IDENTIFIER = 'call-diagnostic-events -> ';
|
|
8
|
+
export const CALL_FEATURE_LOG_IDENTIFIER = 'call-diagnostic-events-feature -> ';
|
|
8
9
|
|
|
9
10
|
export const AUTHENTICATION_FAILED_CODE = 1010;
|
|
10
11
|
export const NETWORK_ERROR = 1026;
|
|
@@ -738,3 +739,5 @@ export const CLIENT_ERROR_CODE_TO_ERROR_PAYLOAD: Record<number, Partial<ClientEv
|
|
|
738
739
|
};
|
|
739
740
|
|
|
740
741
|
export const CALL_DIAGNOSTIC_EVENT_FAILED_TO_SEND = 'js_sdk_call_diagnostic_event_failed_to_send';
|
|
742
|
+
|
|
743
|
+
export const CALL_FEATURE_EVENT_FAILED_TO_SEND = 'js_sdk_call_feature_event_failed_to_send';
|
package/src/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
SubmitBusinessEvent,
|
|
19
19
|
SubmitMQE,
|
|
20
20
|
PreComputedLatencies,
|
|
21
|
+
SubmitFeatureEvent,
|
|
21
22
|
} from './metrics.types';
|
|
22
23
|
import * as CALL_DIAGNOSTIC_CONFIG from './call-diagnostic/config';
|
|
23
24
|
import * as CallDiagnosticUtils from './call-diagnostic/call-diagnostic-metrics.util';
|
|
@@ -61,4 +62,5 @@ export type {
|
|
|
61
62
|
SubmitOperationalEvent,
|
|
62
63
|
SubmitBusinessEvent,
|
|
63
64
|
PreComputedLatencies,
|
|
65
|
+
SubmitFeatureEvent,
|
|
64
66
|
};
|
package/src/metrics.types.ts
CHANGED
|
@@ -2,9 +2,12 @@ import {
|
|
|
2
2
|
ClientEvent as RawClientEvent,
|
|
3
3
|
Event as RawEvent,
|
|
4
4
|
MediaQualityEvent as RawMediaQualityEvent,
|
|
5
|
+
FeatureEvent as RawFeatureEvent,
|
|
5
6
|
} from '@webex/event-dictionary-ts';
|
|
6
7
|
|
|
7
|
-
export type Event = Omit<RawEvent, 'event'> & {
|
|
8
|
+
export type Event = Omit<RawEvent, 'event'> & {
|
|
9
|
+
event: RawClientEvent | RawMediaQualityEvent | RawFeatureEvent;
|
|
10
|
+
};
|
|
8
11
|
|
|
9
12
|
export type ClientEventError = NonNullable<RawClientEvent['errors']>[0];
|
|
10
13
|
|
|
@@ -212,10 +215,9 @@ export type BehavioralEvent = TaggedEvent;
|
|
|
212
215
|
export type OperationalEvent = TaggedEvent;
|
|
213
216
|
|
|
214
217
|
export interface FeatureEvent {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
options?: never;
|
|
218
|
+
name: RawFeatureEvent['name'];
|
|
219
|
+
payload?: RawFeatureEvent;
|
|
220
|
+
options?: SubmitClientEventOptions;
|
|
219
221
|
}
|
|
220
222
|
|
|
221
223
|
export interface MediaQualityEvent {
|
|
@@ -251,6 +253,8 @@ export type ClientEventPayload = RecursivePartial<ClientEvent['payload']>;
|
|
|
251
253
|
export type ClientEventLeaveReason = ClientEvent['payload']['leaveReason'];
|
|
252
254
|
export type ClientEventPayloadError = ClientEvent['payload']['errors'];
|
|
253
255
|
|
|
256
|
+
export type ClientFeatureEventPayload = RecursivePartial<FeatureEvent['payload']>;
|
|
257
|
+
|
|
254
258
|
export type MediaQualityEventAudioSetupDelayPayload = NonNullable<
|
|
255
259
|
MediaQualityEvent['payload']
|
|
256
260
|
>['audioSetupDelay'];
|
|
@@ -311,6 +315,7 @@ export type PreComputedLatencies =
|
|
|
311
315
|
| 'internal.download.time'
|
|
312
316
|
| 'internal.get.cluster.time'
|
|
313
317
|
| 'internal.click.to.interstitial'
|
|
318
|
+
| 'internal.click.to.interstitial.with.user.delay'
|
|
314
319
|
| 'internal.refresh.captcha.time'
|
|
315
320
|
| 'internal.exchange.ci.token.time'
|
|
316
321
|
| 'internal.get.u2c.time'
|
|
@@ -339,3 +344,15 @@ export interface DelayedClientEvent {
|
|
|
339
344
|
payload?: RecursivePartial<ClientEvent['payload']>;
|
|
340
345
|
options?: SubmitClientEventOptions;
|
|
341
346
|
}
|
|
347
|
+
|
|
348
|
+
export type SubmitFeatureEvent = (args: {
|
|
349
|
+
name: FeatureEvent['name'];
|
|
350
|
+
payload?: RecursivePartial<FeatureEvent['payload']>;
|
|
351
|
+
options?: SubmitClientEventOptions;
|
|
352
|
+
}) => Promise<any>;
|
|
353
|
+
|
|
354
|
+
export interface DelayedClientFeatureEvent {
|
|
355
|
+
name: FeatureEvent['name'];
|
|
356
|
+
payload?: RecursivePartial<FeatureEvent['payload']>;
|
|
357
|
+
options?: SubmitClientEventOptions;
|
|
358
|
+
}
|
package/src/new-metrics.ts
CHANGED
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
SubmitClientEventOptions,
|
|
24
24
|
Table,
|
|
25
25
|
DelayedClientEvent,
|
|
26
|
+
DelayedClientFeatureEvent,
|
|
26
27
|
} from './metrics.types';
|
|
27
28
|
import CallDiagnosticLatencies from './call-diagnostic/call-diagnostic-metrics-latencies';
|
|
28
29
|
import {setMetricTimings} from './call-diagnostic/call-diagnostic-metrics.util';
|
|
@@ -51,11 +52,18 @@ class Metrics extends WebexPlugin {
|
|
|
51
52
|
*/
|
|
52
53
|
delaySubmitClientEvents = false;
|
|
53
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Whether or not to delay the submission of feature events.
|
|
57
|
+
*/
|
|
58
|
+
delaySubmitClientFeatureEvents = false;
|
|
59
|
+
|
|
54
60
|
/**
|
|
55
61
|
* Overrides for delayed client events. E.g. if you want to override the correlationId for all delayed client events, you can set this to { correlationId: 'newCorrelationId' }
|
|
56
62
|
*/
|
|
57
63
|
delayedClientEventsOverrides: Partial<DelayedClientEvent['options']> = {};
|
|
58
64
|
|
|
65
|
+
delayedClientFeatureEventsOverrides: Partial<DelayedClientFeatureEvent['options']> = {};
|
|
66
|
+
|
|
59
67
|
/**
|
|
60
68
|
* Constructor
|
|
61
69
|
* @param args
|
|
@@ -275,7 +283,25 @@ class Metrics extends WebexPlugin {
|
|
|
275
283
|
payload?: RecursivePartial<FeatureEvent['payload']>;
|
|
276
284
|
options: any;
|
|
277
285
|
}) {
|
|
278
|
-
|
|
286
|
+
if (!this.callDiagnosticLatencies || !this.callDiagnosticMetrics) {
|
|
287
|
+
// @ts-ignore
|
|
288
|
+
this.webex.logger.log(
|
|
289
|
+
`NewMetrics: @submitFeatureEvent. Attempted to submit before webex.ready. Event name: ${name}`
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
return Promise.resolve();
|
|
293
|
+
}
|
|
294
|
+
this.callDiagnosticLatencies.saveTimestamp({
|
|
295
|
+
key: name,
|
|
296
|
+
options: {meetingId: options?.meetingId},
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
return this.callDiagnosticMetrics.submitFeatureEvent({
|
|
300
|
+
name,
|
|
301
|
+
payload,
|
|
302
|
+
options,
|
|
303
|
+
delaySubmitEvent: this.delaySubmitClientFeatureEvents,
|
|
304
|
+
});
|
|
279
305
|
}
|
|
280
306
|
|
|
281
307
|
/**
|
|
@@ -432,6 +458,31 @@ class Metrics extends WebexPlugin {
|
|
|
432
458
|
|
|
433
459
|
return Promise.resolve();
|
|
434
460
|
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Sets the value of setDelaySubmitClientFeatureEvents.
|
|
464
|
+
* If set to true, feature events will be delayed until submitDelayedClientFeatureEvents is called.
|
|
465
|
+
* If set to false, delayed feature events will be submitted.
|
|
466
|
+
*
|
|
467
|
+
* @param {object} options - {shouldDelay: A boolean value indicating whether to delay the submission of feature events,
|
|
468
|
+
* overrides: An object containing overrides for the feature events}
|
|
469
|
+
*/
|
|
470
|
+
public setDelaySubmitClientFeatureEvents({
|
|
471
|
+
shouldDelay,
|
|
472
|
+
overrides,
|
|
473
|
+
}: {
|
|
474
|
+
shouldDelay: boolean;
|
|
475
|
+
overrides?: Partial<DelayedClientFeatureEvent['options']>;
|
|
476
|
+
}) {
|
|
477
|
+
this.delaySubmitClientFeatureEvents = shouldDelay;
|
|
478
|
+
this.delayedClientFeatureEventsOverrides = overrides || {};
|
|
479
|
+
|
|
480
|
+
if (this.isReady && !shouldDelay) {
|
|
481
|
+
return this.callDiagnosticMetrics.submitDelayedClientFeatureEvents(overrides);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
return Promise.resolve();
|
|
485
|
+
}
|
|
435
486
|
}
|
|
436
487
|
|
|
437
488
|
export default Metrics;
|
|
@@ -108,6 +108,8 @@ describe('plugin-metrics', () => {
|
|
|
108
108
|
.returns(10);
|
|
109
109
|
webex.internal.newMetrics.callDiagnosticLatencies.getDownloadIntelligenceModelsReqResp =
|
|
110
110
|
sinon.stub().returns(42);
|
|
111
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitialWithUserDelay =
|
|
112
|
+
sinon.stub().returns(12);
|
|
111
113
|
|
|
112
114
|
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
113
115
|
//@ts-ignore
|
|
@@ -127,6 +129,7 @@ describe('plugin-metrics', () => {
|
|
|
127
129
|
meetingInfoReqResp: 10,
|
|
128
130
|
refreshCaptchaServiceReqResp: 10,
|
|
129
131
|
downloadIntelligenceModelsReqResp: 42,
|
|
132
|
+
clickToInterstitialWithUserDelay: 12,
|
|
130
133
|
},
|
|
131
134
|
});
|
|
132
135
|
assert.lengthOf(
|
|
@@ -183,9 +186,15 @@ describe('plugin-metrics', () => {
|
|
|
183
186
|
webex.internal.newMetrics.callDiagnosticLatencies.getCallInitJoinReq = sinon
|
|
184
187
|
.stub()
|
|
185
188
|
.returns(10);
|
|
186
|
-
|
|
189
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getDownloadTimeJMT = sinon
|
|
187
190
|
.stub()
|
|
188
191
|
.returns(100);
|
|
192
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getClickToInterstitialWithUserDelay = sinon
|
|
193
|
+
.stub()
|
|
194
|
+
.returns(43);
|
|
195
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getTotalJMTWithUserDelay = sinon
|
|
196
|
+
.stub()
|
|
197
|
+
.returns(64);
|
|
189
198
|
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
190
199
|
//@ts-ignore
|
|
191
200
|
{event: {name: 'client.locus.join.response'}}
|
|
@@ -209,6 +218,8 @@ describe('plugin-metrics', () => {
|
|
|
209
218
|
totalJmt: 20,
|
|
210
219
|
clientJmt: 5,
|
|
211
220
|
downloadTime: 100,
|
|
221
|
+
clickToInterstitialWithUserDelay: 43,
|
|
222
|
+
totalJMTWithUserDelay: 64,
|
|
212
223
|
},
|
|
213
224
|
});
|
|
214
225
|
assert.lengthOf(
|
|
@@ -338,6 +349,12 @@ describe('plugin-metrics', () => {
|
|
|
338
349
|
webex.internal.newMetrics.callDiagnosticLatencies.getStayLobbyTime = sinon
|
|
339
350
|
.stub()
|
|
340
351
|
.returns(1);
|
|
352
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getTotalMediaJMTWithUserDelay = sinon
|
|
353
|
+
.stub()
|
|
354
|
+
.returns(43);
|
|
355
|
+
webex.internal.newMetrics.callDiagnosticLatencies.getTotalJMTWithUserDelay = sinon
|
|
356
|
+
.stub()
|
|
357
|
+
.returns(64);
|
|
341
358
|
const promise = webex.internal.newMetrics.callDiagnosticMetrics.submitToCallDiagnostics(
|
|
342
359
|
//@ts-ignore
|
|
343
360
|
{event: {name: 'client.media-engine.ready'}}
|
|
@@ -356,6 +373,8 @@ describe('plugin-metrics', () => {
|
|
|
356
373
|
interstitialToMediaOKJMT: 22,
|
|
357
374
|
callInitMediaEngineReady: 10,
|
|
358
375
|
stayLobbyTime: 1,
|
|
376
|
+
totalMediaJMTWithUserDelay: 43,
|
|
377
|
+
totalJMTWithUserDelay: 64,
|
|
359
378
|
},
|
|
360
379
|
});
|
|
361
380
|
assert.lengthOf(
|