@webex/internal-plugin-metrics 3.8.0-next.2 → 3.8.0-next.21

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 } from '../metrics.types';
2
+ import { Event, ClientType, SubClientType, NetworkType, EnvironmentType, NewEnvironmentType, ClientEvent, SubmitClientEventOptions, MediaQualityEvent, SubmitMQEOptions, SubmitMQEPayload, ClientLaunchMethodType, ClientEventError, ClientEventPayload, ClientSubServiceType, BrowserLaunchMethodType, DelayedClientEvent } 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 eventErrorCache;
33
34
  validator: (options: {
34
35
  type: 'mqe' | 'ce';
35
36
  event: Event;
@@ -67,7 +68,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
67
68
  * @returns
68
69
  */
69
70
  getOrigin(options: GetOriginOptions, meetingId?: string): {
70
- name: "endpoint" | "addin" | "antares" | "appapi" | "beech" | "breakout" | "calendar" | "cb" | "cca" | "ccc" | "cloudproxy" | "crc" | "edonus" | "givr" | "hecate" | "hedge" | "hesiod" | "homer" | "superhomer" | "l2sip" | "linus" | "locus" | "mbs" | "mcc" | "mcs" | "mercury" | "mes" | "mjs" | "mmp" | "mygdon" | "ngservice" | "orpheus" | "page" | "poros" | "publicapi" | "rhesos" | "terminus" | "tpgw" | "ucc" | "wdm" | "webexivr" | "meetingcontainer";
71
+ name: "endpoint" | "addin" | "antares" | "appapi" | "beech" | "breakout" | "calendar" | "cb" | "cca" | "ccc" | "cloudproxy" | "crc" | "edonus" | "givr" | "hecate" | "hedge" | "hesiod" | "homer" | "idbroker" | "superhomer" | "l2sip" | "linus" | "locus" | "mbs" | "mcc" | "mcs" | "mercury" | "mes" | "mjs" | "mmp" | "mygdon" | "ngservice" | "orpheus" | "page" | "poros" | "publicapi" | "rhesos" | "terminus" | "tpgw" | "ucc" | "wdm" | "webexivr" | "meetingcontainer";
71
72
  userAgent: string;
72
73
  buildType?: "debug" | "test" | "prod" | "tap" | "analyzer-test";
73
74
  upgradeChannel?: string;
@@ -87,11 +88,14 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
87
88
  localNetworkPrefix?: string;
88
89
  publicNetworkPrefix?: string;
89
90
  browserLaunchMethod?: "url-handler" | "activex" | "npapi" | "extension" | "cwsapi" | "java" | "tfs" | "webacd" | "thinclient" | "switch-to-web" | "switch-to-native";
90
- clientLaunchMethod?: "url-handler" | "universal-link" | "voice-command" | "notification" | "manual" | "teams-cross-launch" | "mc-cross-launch";
91
+ clientLaunchMethod?: "url-handler" | "universal-link" | "voice-command" | "notification" | "manual" | "teams-cross-launch" | "mc-cross-launch" | "cws" | "launcher" | "cws-launcher";
91
92
  browser?: string;
92
93
  browserVersion?: string;
93
- clientType?: "MEETING_CENTER" | "EVENT_CENTER" | "TRAINING_CENTER" | "TEAMS_CLIENT" | "TEAMS_DEVICE" | "TEAMS_SHARE" | "SIP" | "RECORDING" | "CLOUD_AWARE_SIP" | "TEAMS_WXC_CLIENT" | "WXC_CLIENT" | "WXC_DEVICE" | "WEBEX_JS_SDK" | "VOICEA_CLIENT" | "CISCO_SIP_GW" | "WEBEX_SDK" | "CPAAS_THIRD_PARTY_SDK" | "WXC_THIRD_PARTY" | "WXCC";
94
- subClientType?: "TEAMS_DEVICE" | "AUTOMOTIVE_APP" | "DESKTOP_APP" | "DESKTOP_APP_VDI" | "DEVICE_CURRENT" | "DEVICE_LEGACY_2020" | "HOLOGRAM_HEADSET_APP" | "HVDI_APP" | "MIXED" | "MOBILE_APP" | "MOBILE_NETWORK" | "PAGE" | "VDI_APP" | "WEB_APP";
94
+ clientType?: "MEETING_CENTER" | "EVENT_CENTER" | "TRAINING_CENTER" | "TEAMS_CLIENT" | "TEAMS_DEVICE" | "TEAMS_SHARE" | "SIP" | "RECORDING" | "CLOUD_AWARE_SIP" | "TEAMS_WXC_CLIENT" | "WXC_CLIENT" | "WXC_DEVICE" | "WEBEX_JS_SDK" | "VOICEA_CLIENT" | "CISCO_SIP_GW" | "WEBEX_SDK" | "CPAAS_THIRD_PARTY_SDK" | "WXC_THIRD_PARTY" | "WXCC" | "TEAMS_PHONE"; /**
95
+ * Constructor
96
+ * @param args
97
+ */
98
+ subClientType?: "TEAMS_DEVICE" | "AUTOMOTIVE_APP" | "DESKTOP_APP" | "DESKTOP_APP_VDI" | "DEVICE_CURRENT" | "DEVICE_LEGACY_2020" | "HOLOGRAM_HEADSET_APP" | "HVDI_APP" | "MIXED" | "MOBILE_APP" | "MOBILE_NETWORK" | "PAGE" | "VDI_APP" | "WEB_APP" | "PHONE_NOVUM" | "PHONE_ESPRESSO" | "PHONE_BUMBLEBEE";
95
99
  schedulingClientType?: "TEAMS_CLIENT" | "GOOGLE_ADDON" | "PT" | "PUBLIC_API" | "UNIFIED_PAGE" | "WEBEX_PAGE" | "GOOGLE_NOTIFICATION_CALENDAR" | "MSFT_NOTIFICATION_ADDIN" | "MSFT_NOTIFICATION_CALENDAR" | "OUTLOOK_ADDIN";
96
100
  clientVersion?: string;
97
101
  clientVersionStatus?: "CURRENT" | "LEGACY" | "UNSUPPORTED";
@@ -147,6 +151,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
147
151
  * @param options
148
152
  */
149
153
  getIdentifiers(options: GetIdentifiersOptions): {
154
+ aggregatedBreakoutMoveId?: string;
150
155
  attendeeId?: string;
151
156
  participantId?: string;
152
157
  breakoutGroupId?: string;
@@ -230,6 +235,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
230
235
  correlationId: string;
231
236
  additionalProperties?: false;
232
237
  } | {
238
+ aggregatedBreakoutMoveId?: string;
233
239
  attendeeId?: string;
234
240
  participantId?: string;
235
241
  breakoutGroupId?: string;
@@ -356,26 +362,15 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
356
362
  payloadOverrides?: any;
357
363
  httpStatusCode?: number;
358
364
  }): ClientEventError;
365
+ /**
366
+ * Clear the error cache
367
+ */
368
+ clearErrorCache(): void;
359
369
  /**
360
370
  * Generate error payload for Client Event
361
371
  * @param rawError
362
372
  */
363
- generateClientEventErrorPayload(rawError: any): {
364
- fatal: boolean;
365
- category: "other" | "signaling" | "media" | "network" | "expected";
366
- errorDescription?: string;
367
- errorCode?: number;
368
- errorCodeStr?: string;
369
- httpCode?: number;
370
- errorCodeExt1?: number;
371
- errorData?: {};
372
- rawErrorMessage?: string;
373
- mediaDeviceErrors?: string;
374
- shownToUser: boolean;
375
- serviceErrorCode?: number;
376
- name: "other" | "locus.response" | "media-engine" | "ice.failed" | "locus.leave" | "client.leave" | "media-device" | "media-sca" | "wxc";
377
- additionalProperties?: false;
378
- };
373
+ generateClientEventErrorPayload(rawError: any): any[];
379
374
  /**
380
375
  * Create client event object for in meeting events
381
376
  * @param arg - create args
@@ -420,7 +415,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
420
415
  /**
421
416
  * Submit Delayed Client Event CA events. Clears delayedClientEvents array after submission.
422
417
  */
423
- submitDelayedClientEvents(): Promise<any[]> | Promise<void>;
418
+ submitDelayedClientEvents(overrides?: Partial<DelayedClientEvent['options']>): Promise<any[]> | Promise<void>;
424
419
  /**
425
420
  * Prepare the event and send the request to metrics-a service.
426
421
  * @param event
@@ -99,6 +99,7 @@ export declare const ERROR_DESCRIPTIONS: {
99
99
  SDP_OFFER_CREATION_ERROR: string;
100
100
  SDP_OFFER_CREATION_ERROR_MISSING_CODEC: string;
101
101
  WDM_RESTRICTED_REGION: string;
102
+ USER_NOT_ALLOWED_JOIN_WEBINAR: string;
102
103
  };
103
104
  export declare const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP: {
104
105
  58400: number;
@@ -108,6 +109,8 @@ export declare const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP: {
108
109
  400001: number;
109
110
  403004: number;
110
111
  403028: number;
112
+ 403025: number;
113
+ 403125: number;
111
114
  403032: number;
112
115
  403034: number;
113
116
  403036: number;
@@ -133,6 +136,14 @@ export declare const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP: {
133
136
  423012: number;
134
137
  423013: number;
135
138
  429005: number;
139
+ 403021: number;
140
+ 403022: number;
141
+ 403024: number;
142
+ 403137: number;
143
+ 423007: number;
144
+ 403026: number;
145
+ 403037: number;
146
+ 403003: number;
136
147
  2403001: number;
137
148
  2403002: number;
138
149
  2403003: number;
@@ -4,7 +4,7 @@
4
4
  import config from './config';
5
5
  import NewMetrics from './new-metrics';
6
6
  import * as Utils from './utils';
7
- import { ClientEvent, ClientEventLeaveReason, SubmitBehavioralEvent, SubmitClientEvent, SubmitInternalEvent, SubmitOperationalEvent, SubmitMQE, PreComputedLatencies } from './metrics.types';
7
+ import { ClientEvent, ClientEventLeaveReason, SubmitBehavioralEvent, SubmitClientEvent, SubmitInternalEvent, SubmitOperationalEvent, SubmitBusinessEvent, SubmitMQE, PreComputedLatencies } from './metrics.types';
8
8
  import * as CALL_DIAGNOSTIC_CONFIG from './call-diagnostic/config';
9
9
  import * as CallDiagnosticUtils from './call-diagnostic/call-diagnostic-metrics.util';
10
10
  import CallDiagnosticMetrics from './call-diagnostic/call-diagnostic-metrics';
@@ -15,4 +15,4 @@ import BusinessMetrics from './business-metrics';
15
15
  import RtcMetrics from './rtcMetrics';
16
16
  export { default, getOSNameInternal } from './metrics';
17
17
  export { config, CALL_DIAGNOSTIC_CONFIG, NewMetrics, Utils, CallDiagnosticUtils, CallDiagnosticLatencies, CallDiagnosticMetrics, BehavioralMetrics, OperationalMetrics, BusinessMetrics, RtcMetrics, };
18
- export type { ClientEvent, ClientEventLeaveReason, SubmitBehavioralEvent, SubmitClientEvent, SubmitInternalEvent, SubmitMQE, SubmitOperationalEvent, PreComputedLatencies, };
18
+ export type { ClientEvent, ClientEventLeaveReason, SubmitBehavioralEvent, SubmitClientEvent, SubmitInternalEvent, SubmitMQE, SubmitOperationalEvent, SubmitBusinessEvent, PreComputedLatencies, };
@@ -9,7 +9,7 @@ export type ClientLaunchMethodType = NonNullable<RawEvent['origin']['clientInfo'
9
9
  export type ClientUserNameInput = NonNullable<RawClientEvent['userNameInput']>;
10
10
  export type ClientEmailInput = NonNullable<RawClientEvent['emailInput']>;
11
11
  export type BrowserLaunchMethodType = NonNullable<RawEvent['origin']['clientInfo']>['browserLaunchMethod'];
12
- export type MetricEventProduct = 'webex' | 'wxcc_desktop' | 'wxcc_crm';
12
+ export type MetricEventProduct = 'webex' | 'wxcc_desktop' | 'wxcc_crm' | 'wxcc_sdk';
13
13
  export type MetricEventAgent = 'user' | 'browser' | 'system' | 'sdk' | 'redux' | 'service' | 'api';
14
14
  export type MetricEventVerb = 'abort' | 'accept' | 'activate' | 'apply' | 'answer' | 'authorize' | 'build' | 'cancel' | 'change' | 'click' | 'close' | 'complete' | 'connect' | 'create' | 'deactivate' | 'decrypt' | 'delete' | 'deliver' | 'destroy' | 'disable' | 'disconnect' | 'dismiss' | 'display' | 'download' | 'edit' | 'enable' | 'encrypt' | 'end' | 'expire' | 'fail' | 'fetch' | 'fire' | 'generate' | 'get' | 'hide' | 'hover' | 'ignore' | 'initialize' | 'initiate' | 'invalidate' | 'join' | 'list' | 'load' | 'login' | 'logout' | 'notify' | 'offer' | 'open' | 'press' | 'receive' | 'refer' | 'refresh' | 'register' | 'release' | 'reload' | 'reject' | 'request' | 'reset' | 'resize' | 'respond' | 'retry' | 'revoke' | 'save' | 'search' | 'select' | 'send' | 'set' | 'sign' | 'start' | 'submit' | 'switch' | 'sync' | 'toggle' | 'transfer' | 'unregister' | 'update' | 'upload' | 'use' | 'validate' | 'view' | 'visit' | 'wait' | 'warn' | 'exit';
15
15
  export type MetricEventJoinFlowVersion = 'Other' | 'NewFTE';
@@ -136,6 +136,12 @@ export type SubmitOperationalEvent = (args: {
136
136
  name: OperationalEvent['metricName'];
137
137
  payload: EventPayload;
138
138
  }) => void;
139
+ export type SubmitBusinessEvent = (args: {
140
+ name: OperationalEvent['metricName'];
141
+ payload: EventPayload;
142
+ metadata?: EventPayload;
143
+ table?: Table;
144
+ }) => void;
139
145
  export type SubmitMQE = (args: {
140
146
  name: MediaQualityEvent['name'];
141
147
  payload: SubmitMQEPayload;
@@ -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 } from './metrics.types';
6
+ import { RecursivePartial, MetricEventProduct, MetricEventAgent, MetricEventVerb, ClientEvent, FeatureEvent, EventPayload, MediaQualityEvent, InternalEvent, SubmitClientEventOptions, Table, DelayedClientEvent } 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,6 +22,10 @@ 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
+ * 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
+ */
28
+ delayedClientEventsOverrides: Partial<DelayedClientEvent['options']>;
25
29
  /**
26
30
  * Constructor
27
31
  * @param args
@@ -178,8 +182,11 @@ declare class Metrics extends WebexPlugin {
178
182
  * Sets the value of delaySubmitClientEvents. If set to true, client events will be delayed until submitDelayedClientEvents is called. If
179
183
  * set to false, delayed client events will be submitted.
180
184
  *
181
- * @param {boolean} shouldDelay - A boolean value indicating whether to delay the submission of client events.
185
+ * @param {object} options - {shouldDelay: A boolean value indicating whether to delay the submission of client events, overrides: An object containing overrides for the client events}
182
186
  */
183
- setDelaySubmitClientEvents(shouldDelay: boolean): Promise<any[]> | Promise<void>;
187
+ setDelaySubmitClientEvents({ shouldDelay, overrides, }: {
188
+ shouldDelay: boolean;
189
+ overrides?: Partial<DelayedClientEvent['options']>;
190
+ }): Promise<any[]> | Promise<void>;
184
191
  }
185
192
  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.0-next.2",
30
- "@webex/test-helper-mocha": "3.8.0-next.2",
31
- "@webex/test-helper-mock-webex": "3.8.0-next.2",
32
- "@webex/test-helper-test-users": "3.8.0-next.2",
29
+ "@webex/test-helper-chai": "3.8.0-next.21",
30
+ "@webex/test-helper-mocha": "3.8.0-next.21",
31
+ "@webex/test-helper-mock-webex": "3.8.0-next.21",
32
+ "@webex/test-helper-test-users": "3.8.0-next.21",
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.0-next.2",
39
- "@webex/common-timers": "3.8.0-next.2",
40
- "@webex/event-dictionary-ts": "^1.0.1688",
41
- "@webex/internal-plugin-metrics": "3.8.0-next.2",
42
- "@webex/test-helper-chai": "3.8.0-next.2",
43
- "@webex/test-helper-mock-webex": "3.8.0-next.2",
44
- "@webex/webex-core": "3.8.0-next.2",
38
+ "@webex/common": "3.8.0-next.21",
39
+ "@webex/common-timers": "3.8.0-next.21",
40
+ "@webex/event-dictionary-ts": "^1.0.1753",
41
+ "@webex/internal-plugin-metrics": "3.8.0-next.21",
42
+ "@webex/test-helper-chai": "3.8.0-next.21",
43
+ "@webex/test-helper-mock-webex": "3.8.0-next.21",
44
+ "@webex/webex-core": "3.8.0-next.21",
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.0-next.2"
57
+ "version": "3.8.0-next.21"
58
58
  }
@@ -97,6 +97,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
97
97
  private hasLoggedBrowserSerial: boolean;
98
98
  private device: any;
99
99
  private delayedClientEvents: DelayedClientEvent[] = [];
100
+ private eventErrorCache: WeakMap<any, any> = new WeakMap();
100
101
 
101
102
  // the default validator before piping an event to the batcher
102
103
  // this function can be overridden by the user
@@ -166,23 +167,17 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
166
167
  if (meetingInfo?.webexScheduled && !meetingInfo?.enableEvent && !meetingInfo?.pmr) {
167
168
  return WEBEX_SUB_SERVICE_TYPES.SCHEDULED_MEETING;
168
169
  }
169
- // if Scheduled, Webinar, not pmr - then Webinar
170
- if (
171
- meetingInfo?.webexScheduled &&
172
- meetingInfo?.enableEvent &&
173
- !meetingInfo?.pmr &&
174
- meetingInfo?.isConvergedWebinar
175
- ) {
176
- return WEBEX_SUB_SERVICE_TYPES.WEBINAR;
170
+
171
+ // if ConvergedArchitecture enable and isConvergedWebinarWebcast -- then webcast
172
+ if (meetingInfo?.enableConvergedArchitecture && meetingInfo?.enableEvent) {
173
+ return meetingInfo?.isConvergedWebinarWebcast
174
+ ? WEBEX_SUB_SERVICE_TYPES.WEBCAST
175
+ : WEBEX_SUB_SERVICE_TYPES.WEBINAR;
177
176
  }
178
- // if Scheduled, Webinar enable webcast - then webcast
179
- if (
180
- meetingInfo?.webexScheduled &&
181
- meetingInfo?.enableEvent &&
182
- !meetingInfo?.pmr &&
183
- meetingInfo?.isConvergedWebinarWebcast
184
- ) {
185
- return WEBEX_SUB_SERVICE_TYPES.WEBCAST;
177
+
178
+ // if Scheduled, enable event, not pmr - then Webinar
179
+ if (meetingInfo?.webexScheduled && meetingInfo?.enableEvent && !meetingInfo?.pmr) {
180
+ return WEBEX_SUB_SERVICE_TYPES.WEBINAR;
186
181
  }
187
182
  }
188
183
 
@@ -561,16 +556,31 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
561
556
  return undefined;
562
557
  }
563
558
 
559
+ /**
560
+ * Clear the error cache
561
+ */
562
+ clearErrorCache() {
563
+ this.eventErrorCache = new WeakMap();
564
+ }
565
+
564
566
  /**
565
567
  * Generate error payload for Client Event
566
568
  * @param rawError
567
569
  */
568
570
  generateClientEventErrorPayload(rawError: any) {
571
+ const cachedError = this.eventErrorCache.get(rawError);
572
+
573
+ if (cachedError) {
574
+ return [cachedError, true];
575
+ }
576
+
569
577
  const rawErrorMessage = rawError.message;
570
578
  const httpStatusCode = rawError.statusCode;
579
+ let payload;
580
+
571
581
  if (rawError.name) {
572
582
  if (isBrowserMediaErrorName(rawError.name)) {
573
- return this.getErrorPayloadForClientErrorCode({
583
+ payload = this.getErrorPayloadForClientErrorCode({
574
584
  serviceErrorCode: undefined,
575
585
  clientErrorCode: BROWSER_MEDIA_ERROR_NAME_TO_CLIENT_ERROR_CODES_MAP[rawError.name],
576
586
  serviceErrorName: rawError.name,
@@ -580,11 +590,11 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
580
590
  }
581
591
  }
582
592
 
583
- if (isSdpOfferCreationError(rawError)) {
593
+ if (isSdpOfferCreationError(rawError) && !payload) {
584
594
  // error code is 30005, but that's not specific enough. we also need to check error.cause.type
585
595
  const causeType = rawError.cause?.type;
586
596
 
587
- return this.getErrorPayloadForClientErrorCode({
597
+ payload = this.getErrorPayloadForClientErrorCode({
588
598
  serviceErrorCode: undefined,
589
599
  clientErrorCode:
590
600
  SDP_OFFER_CREATION_ERROR_MAP[causeType] || SDP_OFFER_CREATION_ERROR_MAP.GENERAL,
@@ -602,8 +612,8 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
602
612
 
603
613
  if (serviceErrorCode) {
604
614
  const clientErrorCode = SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP[serviceErrorCode];
605
- if (clientErrorCode) {
606
- return this.getErrorPayloadForClientErrorCode({
615
+ if (clientErrorCode && !payload) {
616
+ payload = this.getErrorPayloadForClientErrorCode({
607
617
  clientErrorCode,
608
618
  serviceErrorCode,
609
619
  rawErrorMessage,
@@ -612,8 +622,8 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
612
622
  }
613
623
 
614
624
  // by default, if it is locus error, return new locus err
615
- if (isLocusServiceErrorCode(serviceErrorCode)) {
616
- return this.getErrorPayloadForClientErrorCode({
625
+ if (isLocusServiceErrorCode(serviceErrorCode) && !payload) {
626
+ payload = this.getErrorPayloadForClientErrorCode({
617
627
  clientErrorCode: NEW_LOCUS_ERROR_CLIENT_CODE,
618
628
  serviceErrorCode,
619
629
  rawErrorMessage,
@@ -622,8 +632,8 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
622
632
  }
623
633
  }
624
634
 
625
- if (isMeetingInfoServiceError(rawError)) {
626
- return this.getErrorPayloadForClientErrorCode({
635
+ if (isMeetingInfoServiceError(rawError) && !payload) {
636
+ payload = this.getErrorPayloadForClientErrorCode({
627
637
  clientErrorCode: MEETING_INFO_LOOKUP_ERROR_CLIENT_CODE,
628
638
  serviceErrorCode,
629
639
  rawErrorMessage,
@@ -631,8 +641,8 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
631
641
  });
632
642
  }
633
643
 
634
- if (isNetworkError(rawError)) {
635
- return this.getErrorPayloadForClientErrorCode({
644
+ if (isNetworkError(rawError) && !payload) {
645
+ payload = this.getErrorPayloadForClientErrorCode({
636
646
  clientErrorCode: NETWORK_ERROR,
637
647
  serviceErrorCode,
638
648
  payloadOverrides: rawError.payloadOverrides,
@@ -641,8 +651,8 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
641
651
  });
642
652
  }
643
653
 
644
- if (isUnauthorizedError(rawError)) {
645
- return this.getErrorPayloadForClientErrorCode({
654
+ if (isUnauthorizedError(rawError) && !payload) {
655
+ payload = this.getErrorPayloadForClientErrorCode({
646
656
  clientErrorCode: AUTHENTICATION_FAILED_CODE,
647
657
  serviceErrorCode,
648
658
  payloadOverrides: rawError.payloadOverrides,
@@ -651,15 +661,22 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
651
661
  });
652
662
  }
653
663
 
654
- // otherwise return unkown error but passing serviceErrorCode and serviceErrorName so that we know the issue
655
- return this.getErrorPayloadForClientErrorCode({
656
- clientErrorCode: UNKNOWN_ERROR,
657
- serviceErrorCode: serviceErrorCode || UNKNOWN_ERROR,
658
- serviceErrorName: rawError?.name,
659
- payloadOverrides: rawError.payloadOverrides,
660
- rawErrorMessage,
661
- httpStatusCode,
662
- });
664
+ if (!payload) {
665
+ // otherwise return unkown error but passing serviceErrorCode and serviceErrorName so that we know the issue
666
+ payload = this.getErrorPayloadForClientErrorCode({
667
+ clientErrorCode: UNKNOWN_ERROR,
668
+ serviceErrorCode: serviceErrorCode || UNKNOWN_ERROR,
669
+ serviceErrorName: rawError?.name,
670
+ payloadOverrides: rawError.payloadOverrides,
671
+ rawErrorMessage,
672
+ httpStatusCode,
673
+ });
674
+ }
675
+
676
+ // cache the payload for future use
677
+ this.eventErrorCache.set(rawError, payload);
678
+
679
+ return [payload, false];
663
680
  }
664
681
 
665
682
  /**
@@ -742,6 +759,10 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
742
759
  if (joinFlowVersion) {
743
760
  clientEventObject.joinFlowVersion = joinFlowVersion;
744
761
  }
762
+ const meetingJoinedTime = meeting.isoLocalClientMeetingJoinTime;
763
+ if (meetingJoinedTime) {
764
+ clientEventObject.meetingJoinedTime = meetingJoinedTime;
765
+ }
745
766
 
746
767
  if (options.meetingJoinPhase) {
747
768
  clientEventObject.meetingJoinPhase = options.meetingJoinPhase;
@@ -836,14 +857,14 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
836
857
  const errors: ClientEventPayloadError = [];
837
858
 
838
859
  if (rawError) {
839
- const generatedError = this.generateClientEventErrorPayload(rawError);
860
+ const [generatedError, cached] = this.generateClientEventErrorPayload(rawError);
840
861
  if (generatedError) {
841
862
  errors.push(generatedError);
842
863
  }
843
864
  this.logger.log(
844
865
  CALL_DIAGNOSTIC_LOG_IDENTIFIER,
845
866
  'CallDiagnosticMetrics: @prepareClientEvent. Generated errors:',
846
- `generatedError: ${JSON.stringify(generatedError)}`
867
+ `generatedError (cached: ${cached}): ${JSON.stringify(generatedError)}`
847
868
  );
848
869
  }
849
870
 
@@ -921,7 +942,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
921
942
  /**
922
943
  * Submit Delayed Client Event CA events. Clears delayedClientEvents array after submission.
923
944
  */
924
- public submitDelayedClientEvents() {
945
+ public submitDelayedClientEvents(overrides?: Partial<DelayedClientEvent['options']>) {
925
946
  this.logger.log(
926
947
  CALL_DIAGNOSTIC_LOG_IDENTIFIER,
927
948
  'CallDiagnosticMetrics: @submitDelayedClientEvents. Submitting delayed client events.'
@@ -932,7 +953,10 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
932
953
  }
933
954
 
934
955
  const promises = this.delayedClientEvents.map((delayedSubmitClientEventParams) => {
935
- return this.submitClientEvent(delayedSubmitClientEventParams);
956
+ const {name, payload, options} = delayedSubmitClientEventParams;
957
+ const optionsWithOverrides: DelayedClientEvent['options'] = {...options, ...overrides};
958
+
959
+ return this.submitClientEvent({name, payload, options: optionsWithOverrides});
936
960
  });
937
961
 
938
962
  this.delayedClientEvents = [];
@@ -133,6 +133,7 @@ export const ERROR_DESCRIPTIONS = {
133
133
  SDP_OFFER_CREATION_ERROR: 'SdpOfferCreationError',
134
134
  SDP_OFFER_CREATION_ERROR_MISSING_CODEC: 'SdpOfferCreationErrorMissingCodec',
135
135
  WDM_RESTRICTED_REGION: 'WdmRestrictedRegion',
136
+ USER_NOT_ALLOWED_JOIN_WEBINAR: 'UserNotAllowedJoinWebinar',
136
137
  };
137
138
 
138
139
  export const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP = {
@@ -151,6 +152,10 @@ export const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP = {
151
152
  403004: 4005,
152
153
  // Wrong password. Meeting is not allow to access since password error
153
154
  403028: 4005,
155
+ // meeting is not allow to access since require panelist password
156
+ 403025: 4005,
157
+ // wrong password. Meeting is not allow to access since panelist password error
158
+ 403125: 4005,
154
159
  // Wrong or expired permission. Meeting is not allow to access since permissionToken error or expire
155
160
  403032: 4005,
156
161
  // Meeting is required login for current user
@@ -202,6 +207,22 @@ export const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP = {
202
207
  423013: 4005,
203
208
  // Too many requests access
204
209
  429005: 4100,
210
+ // Webinar: Meeting registration is required
211
+ 403021: 4104,
212
+ // Webinar: Meeting registration is still pending
213
+ 403022: 4104,
214
+ // Webinar: Meeting registration have been rejected
215
+ 403024: 4104,
216
+ // Webinar: Registration ID verified failure
217
+ 403137: 4104,
218
+ // Webinar: Registration ID input too many time,please input captcha code
219
+ 423007: 4104,
220
+ // Webinar: Need to join meeting via webcast
221
+ 403026: 4104,
222
+ // Webinar: Meeting join required registration ID
223
+ 403037: 4104,
224
+ // Not reach JBH, can't join meeting
225
+ 403003: 4101,
205
226
 
206
227
  // ---- Locus ------
207
228
  // FREE_USER_MAX_PARTICIPANTS_EXCEEDED
@@ -666,6 +687,11 @@ export const CLIENT_ERROR_CODE_TO_ERROR_PAYLOAD: Record<number, Partial<ClientEv
666
687
  category: 'expected',
667
688
  fatal: true,
668
689
  },
690
+ 4104: {
691
+ errorDescription: ERROR_DESCRIPTIONS.USER_NOT_ALLOWED_JOIN_WEBINAR,
692
+ category: 'expected',
693
+ fatal: true,
694
+ },
669
695
  2729: {
670
696
  errorDescription: ERROR_DESCRIPTIONS.NO_MEDIA_FOUND,
671
697
  category: 'expected',
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
  };
@@ -24,7 +24,7 @@ export type BrowserLaunchMethodType = NonNullable<
24
24
  RawEvent['origin']['clientInfo']
25
25
  >['browserLaunchMethod'];
26
26
 
27
- export type MetricEventProduct = 'webex' | 'wxcc_desktop' | 'wxcc_crm';
27
+ export type MetricEventProduct = 'webex' | 'wxcc_desktop' | 'wxcc_crm' | 'wxcc_sdk';
28
28
 
29
29
  export type MetricEventAgent = 'user' | 'browser' | 'system' | 'sdk' | 'redux' | 'service' | 'api';
30
30
 
@@ -287,6 +287,13 @@ export type SubmitOperationalEvent = (args: {
287
287
  payload: EventPayload;
288
288
  }) => void;
289
289
 
290
+ export type SubmitBusinessEvent = (args: {
291
+ name: OperationalEvent['metricName'];
292
+ payload: EventPayload;
293
+ metadata?: EventPayload;
294
+ table?: Table;
295
+ }) => void;
296
+
290
297
  export type SubmitMQE = (args: {
291
298
  name: MediaQualityEvent['name'];
292
299
  payload: SubmitMQEPayload;
@@ -22,6 +22,7 @@ import {
22
22
  InternalEvent,
23
23
  SubmitClientEventOptions,
24
24
  Table,
25
+ DelayedClientEvent,
25
26
  } from './metrics.types';
26
27
  import CallDiagnosticLatencies from './call-diagnostic/call-diagnostic-metrics-latencies';
27
28
  import {setMetricTimings} from './call-diagnostic/call-diagnostic-metrics.util';
@@ -50,6 +51,11 @@ class Metrics extends WebexPlugin {
50
51
  */
51
52
  delaySubmitClientEvents = false;
52
53
 
54
+ /**
55
+ * 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
+ */
57
+ delayedClientEventsOverrides: Partial<DelayedClientEvent['options']> = {};
58
+
53
59
  /**
54
60
  * Constructor
55
61
  * @param args
@@ -74,6 +80,10 @@ class Metrics extends WebexPlugin {
74
80
  // @ts-ignore
75
81
  this.callDiagnosticMetrics = new CallDiagnosticMetrics({}, {parent: this.webex});
76
82
  this.isReady = true;
83
+ this.setDelaySubmitClientEvents({
84
+ shouldDelay: this.delaySubmitClientEvents,
85
+ overrides: this.delayedClientEventsOverrides,
86
+ });
77
87
  });
78
88
  }
79
89
 
@@ -404,13 +414,20 @@ class Metrics extends WebexPlugin {
404
414
  * Sets the value of delaySubmitClientEvents. If set to true, client events will be delayed until submitDelayedClientEvents is called. If
405
415
  * set to false, delayed client events will be submitted.
406
416
  *
407
- * @param {boolean} shouldDelay - A boolean value indicating whether to delay the submission of client events.
417
+ * @param {object} options - {shouldDelay: A boolean value indicating whether to delay the submission of client events, overrides: An object containing overrides for the client events}
408
418
  */
409
- public setDelaySubmitClientEvents(shouldDelay: boolean) {
419
+ public setDelaySubmitClientEvents({
420
+ shouldDelay,
421
+ overrides,
422
+ }: {
423
+ shouldDelay: boolean;
424
+ overrides?: Partial<DelayedClientEvent['options']>;
425
+ }) {
410
426
  this.delaySubmitClientEvents = shouldDelay;
427
+ this.delayedClientEventsOverrides = overrides || {};
411
428
 
412
- if (!shouldDelay) {
413
- return this.callDiagnosticMetrics.submitDelayedClientEvents();
429
+ if (this.isReady && !shouldDelay) {
430
+ return this.callDiagnosticMetrics.submitDelayedClientEvents(overrides);
414
431
  }
415
432
 
416
433
  return Promise.resolve();