@webex/internal-plugin-metrics 3.8.1-next.4 → 3.8.1-web-workers-keepalive.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.
@@ -1,5 +1,5 @@
1
1
  import { StatelessWebexPlugin } from '@webex/webex-core';
2
- import { Event, ClientType, SubClientType, NetworkType, EnvironmentType, NewEnvironmentType, ClientEvent, SubmitClientEventOptions, MediaQualityEvent, SubmitMQEOptions, SubmitMQEPayload, ClientLaunchMethodType, ClientEventError, ClientEventPayload, ClientSubServiceType, BrowserLaunchMethodType, DelayedClientEvent } from '../metrics.types';
2
+ import { Event, ClientType, SubClientType, NetworkType, EnvironmentType, NewEnvironmentType, ClientEvent, SubmitClientEventOptions, MediaQualityEvent, SubmitMQEOptions, SubmitMQEPayload, ClientLaunchMethodType, ClientEventError, ClientEventPayload, ClientSubServiceType, BrowserLaunchMethodType, DelayedClientEvent, FeatureEvent, ClientFeatureEventPayload } from '../metrics.types';
3
3
  type GetOriginOptions = {
4
4
  clientType: ClientType;
5
5
  subClientType: SubClientType;
@@ -30,6 +30,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
30
30
  private hasLoggedBrowserSerial;
31
31
  private device;
32
32
  private delayedClientEvents;
33
+ private delayedClientFeatureEvents;
33
34
  private eventErrorCache;
34
35
  private isMercuryConnected;
35
36
  validator: (options: {
@@ -328,6 +329,92 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
328
329
  idForEndpointAB?: string;
329
330
  correlationId: string;
330
331
  additionalProperties?: false;
332
+ } | {
333
+ aggregatedBreakoutMoveId?: string;
334
+ attendeeId?: string;
335
+ participantId?: string;
336
+ breakoutGroupId?: string;
337
+ breakoutMoveId?: string;
338
+ breakoutSessionId?: string;
339
+ ciExchangeTokenUrl?: string;
340
+ confluenceId?: string;
341
+ cpaasIdentifiers?: {
342
+ imiTenantId: string;
343
+ devClientId: string;
344
+ imiServiceId: string;
345
+ imiAppId: string;
346
+ sessionId: string;
347
+ sessionInstanceId: string;
348
+ additionalProperties?: false;
349
+ };
350
+ csdmDeviceUrl?: string;
351
+ destinationBreakoutSessionId?: string;
352
+ destinationLocusSessionId?: string;
353
+ destinationLocusUrl?: string;
354
+ destinationVenueId?: string;
355
+ deviceId?: string;
356
+ globalMeetingId?: string;
357
+ installationId?: string;
358
+ webexMeetingUUID?: string;
359
+ ivrCallId?: string;
360
+ ivrDialogId?: string;
361
+ ivrId?: string;
362
+ callId?: string;
363
+ pairCallId?: string;
364
+ locusId?: string;
365
+ locusJoinUrl?: string;
366
+ locusSessionId?: string;
367
+ locusStartTime?: string;
368
+ locusUrl?: string;
369
+ machineId?: string;
370
+ mediaAgentAlias?: string;
371
+ mediaAgentGroupId?: string;
372
+ meetClusterName?: string;
373
+ meetingInstanceId?: string;
374
+ meetingLookupUrl?: string;
375
+ meetingOrgId?: string;
376
+ metricServiceUrl?: string;
377
+ msteamsTenantGuid?: string;
378
+ msteamsConferenceId?: string;
379
+ msteamsMeetingId?: string;
380
+ oauth2ClientId?: string;
381
+ orgId?: string;
382
+ provisionalCorrelationId?: string;
383
+ roomId?: string;
384
+ sessionCorrelationId?: string;
385
+ sharedMediaId?: string;
386
+ sipCallId?: string;
387
+ sipSessionId?: {
388
+ local?: string;
389
+ remote?: string;
390
+ additionalProperties?: false;
391
+ };
392
+ sipUri?: string;
393
+ subConfId?: string;
394
+ tenantId?: string;
395
+ trackingId?: string;
396
+ userId?: string;
397
+ venueId?: string;
398
+ venueUrl?: string;
399
+ whiteboardUrl?: string;
400
+ wdmDeviceRegistrationUrl?: string;
401
+ webexConferenceId?: number;
402
+ webexClusterName?: string;
403
+ webexConferenceIdStr?: string;
404
+ webexDataCenter?: string;
405
+ webexGuestId?: number;
406
+ webexMeetingId?: number;
407
+ webexNodeId?: number;
408
+ webexSiteId?: number;
409
+ webexSiteName?: string;
410
+ webexSiteUuid?: string;
411
+ webexUserId?: number;
412
+ webexWebDomain?: string;
413
+ recordingId?: string;
414
+ clientCorrelationId?: string;
415
+ idForEndpointAB?: string;
416
+ correlationId: string;
417
+ additionalProperties?: false;
331
418
  };
332
419
  /**
333
420
  * Create diagnostic event, which can hold client event, feature event or MQE event data.
@@ -338,11 +425,30 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
338
425
  */
339
426
  prepareDiagnosticEvent(eventData: Event['event'], options: any): Event;
340
427
  /**
341
- * TODO: NOT IMPLEMENTED
428
+ * Create feature event
429
+ * @param name
430
+ * @param payload
431
+ * @param options
432
+ * @returns
433
+ */
434
+ private prepareClientFeatureEvent;
435
+ /**
342
436
  * Submit Feature Event
437
+ * submit to business_ucf
343
438
  * @returns
344
439
  */
345
- submitFeatureEvent(): void;
440
+ submitFeatureEvent({ name, payload, options, delaySubmitEvent, }: {
441
+ name: FeatureEvent['name'];
442
+ payload?: ClientFeatureEventPayload;
443
+ options?: SubmitClientEventOptions;
444
+ delaySubmitEvent?: boolean;
445
+ }): Promise<any>;
446
+ /**
447
+ * Submit Feature Event
448
+ * type is business
449
+ * @param event
450
+ */
451
+ submitToCallFeatures(event: Event): Promise<any>;
346
452
  /**
347
453
  * Submit Media Quality Event
348
454
  * @param args - submit params
@@ -381,6 +487,14 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
381
487
  * @param rawError
382
488
  */
383
489
  generateClientEventErrorPayload(rawError: any): any[];
490
+ /**
491
+ * Create common object for in meeting events
492
+ * @param name
493
+ * @param options
494
+ * @param eventType - 'client' | 'feature'
495
+ * @returns object
496
+ */
497
+ private createCommonEventObjectInMeeting;
384
498
  /**
385
499
  * Create client event object for in meeting events
386
500
  * @param arg - create args
@@ -389,6 +503,13 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
389
503
  * @returns object
390
504
  */
391
505
  private createClientEventObjectInMeeting;
506
+ /**
507
+ * Create feature event object for in meeting function event
508
+ * @param name
509
+ * @param options
510
+ * @returns object
511
+ */
512
+ private createFeatureEventObjectInMeeting;
392
513
  /**
393
514
  * Create client event object for pre meeting events
394
515
  * @param arg - create args
@@ -426,6 +547,10 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
426
547
  * Submit Delayed Client Event CA events. Clears delayedClientEvents array after submission.
427
548
  */
428
549
  submitDelayedClientEvents(overrides?: Partial<DelayedClientEvent['options']>): Promise<any[]> | Promise<void>;
550
+ /**
551
+ * Submit Delayed feature Event CA events. Clears submitDelayedClientFeatureEvents array after submission.
552
+ */
553
+ submitDelayedClientFeatureEvents(overrides?: Partial<DelayedClientEvent['options']>): Promise<any[]> | Promise<void>;
429
554
  /**
430
555
  * Prepare the event and send the request to metrics-a service.
431
556
  * @param event
@@ -1,5 +1,6 @@
1
1
  import { ClientEventError, ClientSubServiceType } from '../metrics.types';
2
2
  export declare const CALL_DIAGNOSTIC_LOG_IDENTIFIER = "call-diagnostic-events -> ";
3
+ export declare const CALL_FEATURE_LOG_IDENTIFIER = "call-diagnostic-events-feature -> ";
3
4
  export declare const AUTHENTICATION_FAILED_CODE = 1010;
4
5
  export declare const NETWORK_ERROR = 1026;
5
6
  export declare const NEW_LOCUS_ERROR_CLIENT_CODE = 4008;
@@ -195,3 +196,4 @@ export declare const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP: {
195
196
  };
196
197
  export declare const CLIENT_ERROR_CODE_TO_ERROR_PAYLOAD: Record<number, Partial<ClientEventError>>;
197
198
  export declare const CALL_DIAGNOSTIC_EVENT_FAILED_TO_SEND = "js_sdk_call_diagnostic_event_failed_to_send";
199
+ export declare const CALL_FEATURE_EVENT_FAILED_TO_SEND = "js_sdk_call_feature_event_failed_to_send";
@@ -1,6 +1,6 @@
1
- import { ClientEvent as RawClientEvent, Event as RawEvent, MediaQualityEvent as RawMediaQualityEvent } from '@webex/event-dictionary-ts';
1
+ import { ClientEvent as RawClientEvent, Event as RawEvent, MediaQualityEvent as RawMediaQualityEvent, FeatureEvent as RawFeatureEvent } from '@webex/event-dictionary-ts';
2
2
  export type Event = Omit<RawEvent, 'event'> & {
3
- event: RawClientEvent | RawMediaQualityEvent;
3
+ event: RawClientEvent | RawMediaQualityEvent | RawFeatureEvent;
4
4
  };
5
5
  export type ClientEventError = NonNullable<RawClientEvent['errors']>[0];
6
6
  export type EnvironmentType = NonNullable<RawEvent['origin']['environment']>;
@@ -89,9 +89,9 @@ export interface TaggedEvent {
89
89
  export type BehavioralEvent = TaggedEvent;
90
90
  export type OperationalEvent = TaggedEvent;
91
91
  export interface FeatureEvent {
92
- name: never;
93
- payload?: never;
94
- options?: never;
92
+ name: RawFeatureEvent['name'];
93
+ payload?: RawFeatureEvent;
94
+ options?: SubmitClientEventOptions;
95
95
  }
96
96
  export interface MediaQualityEvent {
97
97
  name: RawMediaQualityEvent['name'];
@@ -110,6 +110,7 @@ export type ClientSubServiceType = ClientEvent['payload']['webexSubServiceType']
110
110
  export type ClientEventPayload = RecursivePartial<ClientEvent['payload']>;
111
111
  export type ClientEventLeaveReason = ClientEvent['payload']['leaveReason'];
112
112
  export type ClientEventPayloadError = ClientEvent['payload']['errors'];
113
+ export type ClientFeatureEventPayload = RecursivePartial<FeatureEvent['payload']>;
113
114
  export type MediaQualityEventAudioSetupDelayPayload = NonNullable<MediaQualityEvent['payload']>['audioSetupDelay'];
114
115
  export type MediaQualityEventVideoSetupDelayPayload = NonNullable<MediaQualityEvent['payload']>['videoSetupDelay'];
115
116
  export type SubmitMQEPayload = RecursivePartial<MediaQualityEvent['payload']> & {
@@ -172,4 +173,14 @@ export interface DelayedClientEvent {
172
173
  payload?: RecursivePartial<ClientEvent['payload']>;
173
174
  options?: SubmitClientEventOptions;
174
175
  }
176
+ export type SubmitFeatureEvent = (args: {
177
+ name: FeatureEvent['name'];
178
+ payload?: RecursivePartial<FeatureEvent['payload']>;
179
+ options?: SubmitClientEventOptions;
180
+ }) => Promise<any>;
181
+ export interface DelayedClientFeatureEvent {
182
+ name: FeatureEvent['name'];
183
+ payload?: RecursivePartial<FeatureEvent['payload']>;
184
+ options?: SubmitClientEventOptions;
185
+ }
175
186
  export {};
@@ -3,7 +3,7 @@ import CallDiagnosticMetrics from './call-diagnostic/call-diagnostic-metrics';
3
3
  import BehavioralMetrics from './behavioral-metrics';
4
4
  import OperationalMetrics from './operational-metrics';
5
5
  import BusinessMetrics from './business-metrics';
6
- import { RecursivePartial, MetricEventProduct, MetricEventAgent, MetricEventVerb, ClientEvent, FeatureEvent, EventPayload, MediaQualityEvent, InternalEvent, SubmitClientEventOptions, Table, DelayedClientEvent } from './metrics.types';
6
+ import { RecursivePartial, MetricEventProduct, MetricEventAgent, MetricEventVerb, ClientEvent, FeatureEvent, EventPayload, MediaQualityEvent, InternalEvent, SubmitClientEventOptions, Table, DelayedClientEvent, DelayedClientFeatureEvent } from './metrics.types';
7
7
  import CallDiagnosticLatencies from './call-diagnostic/call-diagnostic-metrics-latencies';
8
8
  /**
9
9
  * Metrics plugin to centralize all types of metrics.
@@ -22,10 +22,15 @@ declare class Metrics extends WebexPlugin {
22
22
  * Whether or not to delay the submission of client events.
23
23
  */
24
24
  delaySubmitClientEvents: boolean;
25
+ /**
26
+ * Whether or not to delay the submission of feature events.
27
+ */
28
+ delaySubmitClientFeatureEvents: boolean;
25
29
  /**
26
30
  * 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' }
27
31
  */
28
32
  delayedClientEventsOverrides: Partial<DelayedClientEvent['options']>;
33
+ delayedClientFeatureEventsOverrides: Partial<DelayedClientFeatureEvent['options']>;
29
34
  /**
30
35
  * Constructor
31
36
  * @param args
@@ -119,7 +124,7 @@ declare class Metrics extends WebexPlugin {
119
124
  name: FeatureEvent['name'];
120
125
  payload?: RecursivePartial<FeatureEvent['payload']>;
121
126
  options: any;
122
- }): void;
127
+ }): Promise<any>;
123
128
  /**
124
129
  * Call Analyzer: Client Event
125
130
  * @public
@@ -188,5 +193,17 @@ declare class Metrics extends WebexPlugin {
188
193
  shouldDelay: boolean;
189
194
  overrides?: Partial<DelayedClientEvent['options']>;
190
195
  }): Promise<any[]> | Promise<void>;
196
+ /**
197
+ * Sets the value of setDelaySubmitClientFeatureEvents.
198
+ * If set to true, feature events will be delayed until submitDelayedClientFeatureEvents is called.
199
+ * If set to false, delayed feature events will be submitted.
200
+ *
201
+ * @param {object} options - {shouldDelay: A boolean value indicating whether to delay the submission of feature events,
202
+ * overrides: An object containing overrides for the feature events}
203
+ */
204
+ setDelaySubmitClientFeatureEvents({ shouldDelay, overrides, }: {
205
+ shouldDelay: boolean;
206
+ overrides?: Partial<DelayedClientFeatureEvent['options']>;
207
+ }): Promise<any[]> | Promise<void>;
191
208
  }
192
209
  export default Metrics;
package/package.json CHANGED
@@ -26,22 +26,22 @@
26
26
  "@webex/eslint-config-legacy": "0.0.0",
27
27
  "@webex/jest-config-legacy": "0.0.0",
28
28
  "@webex/legacy-tools": "0.0.0",
29
- "@webex/test-helper-chai": "3.8.1-next.4",
30
- "@webex/test-helper-mocha": "3.8.1-next.4",
31
- "@webex/test-helper-mock-webex": "3.8.1-next.4",
32
- "@webex/test-helper-test-users": "3.8.1-next.4",
29
+ "@webex/test-helper-chai": "3.8.1-web-workers-keepalive.1",
30
+ "@webex/test-helper-mocha": "3.8.1-web-workers-keepalive.1",
31
+ "@webex/test-helper-mock-webex": "3.8.1-web-workers-keepalive.1",
32
+ "@webex/test-helper-test-users": "3.8.1-web-workers-keepalive.1",
33
33
  "eslint": "^8.24.0",
34
34
  "prettier": "^2.7.1",
35
35
  "sinon": "^9.2.4"
36
36
  },
37
37
  "dependencies": {
38
- "@webex/common": "3.8.1-next.4",
39
- "@webex/common-timers": "3.8.1-next.4",
38
+ "@webex/common": "3.8.1-web-workers-keepalive.1",
39
+ "@webex/common-timers": "3.8.1-web-workers-keepalive.1",
40
40
  "@webex/event-dictionary-ts": "^1.0.1819",
41
- "@webex/internal-plugin-metrics": "3.8.1-next.4",
42
- "@webex/test-helper-chai": "3.8.1-next.4",
43
- "@webex/test-helper-mock-webex": "3.8.1-next.4",
44
- "@webex/webex-core": "3.8.1-next.4",
41
+ "@webex/internal-plugin-metrics": "3.8.1-web-workers-keepalive.1",
42
+ "@webex/test-helper-chai": "3.8.1-web-workers-keepalive.1",
43
+ "@webex/test-helper-mock-webex": "3.8.1-web-workers-keepalive.1",
44
+ "@webex/webex-core": "3.8.1-web-workers-keepalive.1",
45
45
  "ip-anonymize": "^0.1.0",
46
46
  "lodash": "^4.17.21",
47
47
  "uuid": "^3.3.2"
@@ -54,5 +54,5 @@
54
54
  "test:style": "eslint ./src/**/*.*",
55
55
  "test:unit": "webex-legacy-tools test --unit --runner mocha"
56
56
  },
57
- "version": "3.8.1-next.4"
57
+ "version": "3.8.1-web-workers-keepalive.1"
58
58
  }
@@ -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,6 +102,7 @@ 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();
101
107
  private isMercuryConnected = false;
102
108
 
@@ -427,12 +433,97 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
427
433
  }
428
434
 
429
435
  /**
430
- * TODO: NOT IMPLEMENTED
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
+ /**
431
471
  * Submit Feature Event
472
+ * submit to business_ucf
432
473
  * @returns
433
474
  */
434
- public submitFeatureEvent() {
435
- throw Error('Not implemented');
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);
436
527
  }
437
528
 
438
529
  /**
@@ -691,20 +782,20 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
691
782
  }
692
783
 
693
784
  /**
694
- * Create client event object for in meeting events
695
- * @param arg - create args
696
- * @param arg.event - event key
697
- * @param arg.options - options
785
+ * Create common object for in meeting events
786
+ * @param name
787
+ * @param options
788
+ * @param eventType - 'client' | 'feature'
698
789
  * @returns object
699
790
  */
700
- private createClientEventObjectInMeeting({
791
+ private createCommonEventObjectInMeeting({
701
792
  name,
702
793
  options,
703
- errors,
794
+ eventType = 'client',
704
795
  }: {
705
- name: ClientEvent['name'];
796
+ name: string;
706
797
  options?: SubmitClientEventOptions;
707
- errors?: ClientEventPayloadError;
798
+ eventType?: 'client' | 'feature';
708
799
  }) {
709
800
  const {
710
801
  meetingId,
@@ -719,16 +810,21 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
719
810
 
720
811
  if (!meeting) {
721
812
  console.warn(
722
- 'Attempt to send client event but no meeting was found...',
813
+ 'Attempt to send common event but no meeting was found...',
723
814
  `name: ${name}, meetingId: ${meetingId}`
724
815
  );
725
816
  // @ts-ignore
726
- this.webex.internal.metrics.submitClientMetrics(CALL_DIAGNOSTIC_EVENT_FAILED_TO_SEND, {
727
- fields: {
728
- meetingId,
729
- name,
730
- },
731
- });
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
+ );
732
828
 
733
829
  return undefined;
734
830
  }
@@ -742,15 +838,13 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
742
838
  sessionCorrelationId,
743
839
  });
744
840
 
745
- // create client event object
746
- const clientEventObject: ClientEvent['payload'] = {
841
+ // create common event object structur
842
+ const commonEventObject = {
747
843
  name,
748
844
  canProceed: true,
749
845
  identifiers,
750
- errors,
751
846
  eventData: {
752
847
  webClientDomain: window.location.hostname,
753
- isMercuryConnected: this.isMercuryConnected,
754
848
  },
755
849
  userType: meeting.getCurUserType(),
756
850
  loginType:
@@ -769,18 +863,80 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
769
863
 
770
864
  const joinFlowVersion = options.joinFlowVersion ?? meeting.callStateForMetrics?.joinFlowVersion;
771
865
  if (joinFlowVersion) {
772
- clientEventObject.joinFlowVersion = joinFlowVersion;
866
+ // @ts-ignore
867
+ commonEventObject.joinFlowVersion = joinFlowVersion;
773
868
  }
774
869
  const meetingJoinedTime = meeting.isoLocalClientMeetingJoinTime;
775
870
  if (meetingJoinedTime) {
776
- clientEventObject.meetingJoinedTime = meetingJoinedTime;
871
+ // @ts-ignore
872
+ commonEventObject.meetingJoinedTime = meetingJoinedTime;
777
873
  }
778
874
 
779
875
  if (options.meetingJoinPhase) {
780
- clientEventObject.meetingJoinPhase = options.meetingJoinPhase;
876
+ // @ts-ignore
877
+ commonEventObject.meetingJoinPhase = options.meetingJoinPhase;
781
878
  }
782
879
 
783
- return clientEventObject;
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'];
784
940
  }
785
941
 
786
942
  /**
@@ -977,6 +1133,31 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
977
1133
  return Promise.all(promises);
978
1134
  }
979
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
+
980
1161
  /**
981
1162
  * Prepare the event and send the request to metrics-a service.
982
1163
  * @param event
@@ -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';