@webex/internal-plugin-metrics 3.12.0-next.9 → 3.12.0-webex-services-ready.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.
Files changed (38) hide show
  1. package/dist/batcher.js +3 -0
  2. package/dist/batcher.js.map +1 -1
  3. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +23 -0
  4. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -1
  5. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +29 -25
  6. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
  7. package/dist/call-diagnostic/call-diagnostic-metrics.js +55 -8
  8. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
  9. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +5 -0
  10. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
  11. package/dist/call-diagnostic/config.js +14 -2
  12. package/dist/call-diagnostic/config.js.map +1 -1
  13. package/dist/config.js +1 -0
  14. package/dist/config.js.map +1 -1
  15. package/dist/metrics.js +1 -1
  16. package/dist/metrics.types.js.map +1 -1
  17. package/dist/prelogin-metrics-batcher.js +23 -0
  18. package/dist/prelogin-metrics-batcher.js.map +1 -1
  19. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +23 -0
  20. package/dist/types/call-diagnostic/config.d.ts +4 -0
  21. package/dist/types/config.d.ts +1 -0
  22. package/dist/types/metrics.types.d.ts +2 -2
  23. package/package.json +11 -11
  24. package/src/batcher.js +4 -0
  25. package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +26 -0
  26. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +54 -38
  27. package/src/call-diagnostic/call-diagnostic-metrics.ts +46 -1
  28. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +5 -0
  29. package/src/call-diagnostic/config.ts +13 -0
  30. package/src/config.js +1 -0
  31. package/src/metrics.types.ts +1 -1
  32. package/src/prelogin-metrics-batcher.ts +26 -0
  33. package/test/unit/spec/batcher.js +43 -0
  34. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +145 -0
  35. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +105 -95
  36. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +680 -159
  37. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +27 -0
  38. package/test/unit/spec/prelogin-metrics-batcher.ts +190 -36
@@ -1 +1 @@
1
- {"version":3,"names":["_lodash","require","_batcher","_interopRequireDefault","_callDiagnosticMetrics","_utils","PRE_LOGIN_METRICS_IDENTIFIER","PreLoginMetricsBatcher","Batcher","extend","namespace","preLoginId","undefined","savePreLoginId","prepareItem","item","_promise","default","resolve","prepareDiagnosticMetricItem","webex","prepareRequest","queue","forEach","eventPayload","originTime","sent","Date","toISOString","submitHttpRequest","payload","_this","batchId","uniqueId","logger","error","concat","reject","Error","request","method","service","resource","headers","authorization","body","metrics","waitForServiceTimeout","config","then","res","log","catch","err","generateCommonErrorMetadata","_default","exports"],"sources":["prelogin-metrics-batcher.ts"],"sourcesContent":["import {uniqueId} from 'lodash';\nimport Batcher from './batcher';\nimport {prepareDiagnosticMetricItem} from './call-diagnostic/call-diagnostic-metrics.util';\nimport {generateCommonErrorMetadata} from './utils';\n\nconst PRE_LOGIN_METRICS_IDENTIFIER = 'Pre Login Metrics -->';\n\nconst PreLoginMetricsBatcher = Batcher.extend({\n namespace: 'Metrics',\n preLoginId: undefined,\n\n /**\n * Save the pre-login ID.\n * @param {string} preLoginId The pre-login ID to be saved.\n * @returns {void}\n */\n savePreLoginId(preLoginId) {\n this.preLoginId = preLoginId;\n },\n\n /**\n * Prepare item\n * @param {any} item\n * @returns {Promise<any>}\n */\n prepareItem(item) {\n return Promise.resolve(prepareDiagnosticMetricItem(this.webex, item));\n },\n\n /**\n * Prepare request, add time sensitive date etc.\n * @param {any[]} queue\n * @returns {Promise<any[]>}\n */\n prepareRequest(queue) {\n // Add sent timestamp\n queue.forEach((item) => {\n item.eventPayload.originTime = item.eventPayload.originTime || {};\n item.eventPayload.originTime.sent = new Date().toISOString();\n });\n\n return Promise.resolve(queue);\n },\n\n /**\n *\n * @param {any} payload\n * @returns {Promise<any>}\n */\n submitHttpRequest(payload: any) {\n const batchId = uniqueId('prelogin-batch-');\n if (this.preLoginId === undefined) {\n this.webex.logger.error(\n PRE_LOGIN_METRICS_IDENTIFIER,\n `PreLoginMetricsBatcher: @submitHttpRequest#${batchId}. PreLoginId is not set.`\n );\n\n return Promise.reject(new Error('PreLoginId is not set.'));\n }\n\n return this.webex\n .request({\n method: 'POST',\n service: 'metrics',\n resource: 'clientmetrics-prelogin',\n headers: {\n authorization: false,\n 'x-prelogin-userid': this.preLoginId,\n },\n body: {\n metrics: payload,\n },\n waitForServiceTimeout: this.webex.config.metrics.waitForServiceTimeout,\n })\n .then((res) => {\n this.webex.logger.log(\n PRE_LOGIN_METRICS_IDENTIFIER,\n `PreLoginMetricsBatcher: @submitHttpRequest#${batchId}. Request successful.`\n );\n\n return res;\n })\n .catch((err) => {\n this.webex.logger.error(\n PRE_LOGIN_METRICS_IDENTIFIER,\n `PreLoginMetricsBatcher: @submitHttpRequest#${batchId}. Request failed:`,\n `error: ${generateCommonErrorMetadata(err)}`\n );\n\n return Promise.reject(err);\n });\n },\n});\n\nexport default PreLoginMetricsBatcher;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_lodash","require","_batcher","_interopRequireDefault","_callDiagnosticMetrics","_utils","PRE_LOGIN_METRICS_IDENTIFIER","PreLoginMetricsBatcher","Batcher","extend","namespace","preLoginId","undefined","savePreLoginId","prepareItem","item","_promise","default","resolve","prepareDiagnosticMetricItem","webex","prepareRequest","queue","forEach","eventPayload","originTime","sent","Date","toISOString","submitHttpRequest","payload","_this","batchId","uniqueId","logger","error","concat","reject","Error","request","method","service","resource","headers","authorization","body","metrics","waitForServiceTimeout","config","then","res","log","handleHttpResponseStatus","statusCode","catch","err","generateCommonErrorMetadata","shouldMark","_isArray","some","markTelemetryOptOutOnResponse","_this$webex$internal$","_this$webex$internal$2","internal","newMetrics","callDiagnosticMetrics","setIsTelemetryOptOutAutomatic","_default","exports"],"sources":["prelogin-metrics-batcher.ts"],"sourcesContent":["import {uniqueId} from 'lodash';\nimport Batcher from './batcher';\nimport {prepareDiagnosticMetricItem} from './call-diagnostic/call-diagnostic-metrics.util';\nimport {generateCommonErrorMetadata} from './utils';\n\nconst PRE_LOGIN_METRICS_IDENTIFIER = 'Pre Login Metrics -->';\n\nconst PreLoginMetricsBatcher = Batcher.extend({\n namespace: 'Metrics',\n preLoginId: undefined,\n\n /**\n * Save the pre-login ID.\n * @param {string} preLoginId The pre-login ID to be saved.\n * @returns {void}\n */\n savePreLoginId(preLoginId) {\n this.preLoginId = preLoginId;\n },\n\n /**\n * Prepare item\n * @param {any} item\n * @returns {Promise<any>}\n */\n prepareItem(item) {\n return Promise.resolve(prepareDiagnosticMetricItem(this.webex, item));\n },\n\n /**\n * Prepare request, add time sensitive date etc.\n * @param {any[]} queue\n * @returns {Promise<any[]>}\n */\n prepareRequest(queue) {\n // Add sent timestamp\n queue.forEach((item) => {\n item.eventPayload.originTime = item.eventPayload.originTime || {};\n item.eventPayload.originTime.sent = new Date().toISOString();\n });\n\n return Promise.resolve(queue);\n },\n\n /**\n *\n * @param {any} payload\n * @returns {Promise<any>}\n */\n submitHttpRequest(payload: any) {\n const batchId = uniqueId('prelogin-batch-');\n if (this.preLoginId === undefined) {\n this.webex.logger.error(\n PRE_LOGIN_METRICS_IDENTIFIER,\n `PreLoginMetricsBatcher: @submitHttpRequest#${batchId}. PreLoginId is not set.`\n );\n\n return Promise.reject(new Error('PreLoginId is not set.'));\n }\n\n return this.webex\n .request({\n method: 'POST',\n service: 'metrics',\n resource: 'clientmetrics-prelogin',\n headers: {\n authorization: false,\n 'x-prelogin-userid': this.preLoginId,\n },\n body: {\n metrics: payload,\n },\n waitForServiceTimeout: this.webex.config.metrics.waitForServiceTimeout,\n })\n .then((res) => {\n this.webex.logger.log(\n PRE_LOGIN_METRICS_IDENTIFIER,\n `PreLoginMetricsBatcher: @submitHttpRequest#${batchId}. Request successful.`\n );\n\n this.handleHttpResponseStatus(res?.statusCode, payload);\n\n return res;\n })\n .catch((err) => {\n this.webex.logger.error(\n PRE_LOGIN_METRICS_IDENTIFIER,\n `PreLoginMetricsBatcher: @submitHttpRequest#${batchId}. Request failed:`,\n `error: ${generateCommonErrorMetadata(err)}`\n );\n\n this.handleHttpResponseStatus(err?.statusCode, payload);\n\n return Promise.reject(err);\n });\n },\n\n /**\n * React to the HTTP status code returned by the prelogin metrics endpoint.\n * Only items submitted with `markTelemetryOptOutOnResponse: true` opt into\n * this behavior.\n * @param {number | undefined} statusCode\n * @param {any[]} payload Items flushed in this HTTP batch.\n * @returns {void}\n */\n handleHttpResponseStatus(statusCode: number | undefined, payload: any[]) {\n const shouldMark =\n Array.isArray(payload) &&\n payload.some((item) => item?.markTelemetryOptOutOnResponse === true);\n\n if (!shouldMark) {\n return;\n }\n\n if (statusCode === 200) {\n this.webex.internal.newMetrics?.callDiagnosticMetrics?.setIsTelemetryOptOutAutomatic(true);\n }\n },\n});\n\nexport default PreLoginMetricsBatcher;\n"],"mappings":"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","ignoreList":[]}
@@ -36,6 +36,8 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
36
36
  private isMercuryConnected;
37
37
  private eventLimitTracker;
38
38
  private eventLimitWarningsLogged;
39
+ private isTelemetryOptOutManual;
40
+ private isTelemetryOptOutAutomatic;
39
41
  validator: (options: {
40
42
  type: 'mqe' | 'ce';
41
43
  event: Event;
@@ -53,6 +55,21 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
53
55
  * @returns one of 'login-ci','unverified-guest', null
54
56
  */
55
57
  getCurLoginType(): "unverified-guest" | "login-ci";
58
+ /**
59
+ * Returns the telemetryOptOut value of the current user
60
+ * @returns one of 'manual', 'automatic', undefined
61
+ */
62
+ getTelemetryOptOut(): "manual" | "automatic";
63
+ /**
64
+ * Sets the manual telemetry opt-out status for the current user
65
+ * @param value - boolean value indicating manual telemetry opt-out status
66
+ */
67
+ setIsTelemetryOptOutManual(value: boolean): void;
68
+ /**
69
+ * Sets the automatic telemetry opt-out status for the current user
70
+ * @param value - boolean value indicating automatic telemetry opt-out status
71
+ */
72
+ setIsTelemetryOptOutAutomatic(value: boolean): void;
56
73
  /**
57
74
  * Returns if the meeting has converged architecture enabled
58
75
  * @param options.meetingId
@@ -84,6 +101,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
84
101
  userAgent: string;
85
102
  buildType?: "debug" | "test" | "prod" | "tap" | "analyzer-test";
86
103
  upgradeChannel?: string;
104
+ upgradeSource?: string;
87
105
  instanceId?: string;
88
106
  networkType: "wifi" | "ethernet" | "cellular" | "unknown";
89
107
  localIP?: string;
@@ -142,6 +160,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
142
160
  shareType?: "cb-normal-share" | "ce-airplay-share" | "ce-direct-share" | "ce-gui-loopback-share" | "ce-input-source-share" | "ce-input-source-share-hdmi" | "ce-input-source-share-usbc" | "ce-jpg-share" | "ce-miracast-share" | "mcs-normal-share" | "mcs-normal-audio-share" | "mcs-hfps-share" | "mcs-hfps-audio-share";
143
161
  videoDisplayMode?: "grid-view" | "active-speaker-view";
144
162
  videoLayoutType?: "auto" | "stack" | "stackWithShare" | "sideBySide" | "sideBySideWithShare" | "grid" | "floatingActive" | "floatingThumbnail" | "floatingGrid" | "overlay" | "focus" | "prominent" | "focusWithShare" | "prominentWithShare" | "equal" | "equalWithShare" | "largeGallery" | "autoWithShare";
163
+ appliedLayout?: "auto" | "stack" | "stackWithShare" | "sideBySide" | "sideBySideWithShare" | "grid" | "floatingActive" | "floatingThumbnail" | "floatingGrid" | "overlay" | "focus" | "prominent" | "focusWithShare" | "prominentWithShare" | "equal" | "equalWithShare" | "largeGallery" | "autoWithShare";
145
164
  videoRenderType?: "wme" | "client_d3d" | "client_gdi";
146
165
  vdiInfo?: {};
147
166
  is64BitsClient?: boolean;
@@ -203,6 +222,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
203
222
  callId?: string;
204
223
  pairCallId?: string;
205
224
  llmWebsocketUrl?: string;
225
+ locusCluster?: string;
206
226
  locusId?: string;
207
227
  locusJoinUrl?: string;
208
228
  locusSessionId?: string;
@@ -293,6 +313,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
293
313
  callId?: string;
294
314
  pairCallId?: string;
295
315
  llmWebsocketUrl?: string;
316
+ locusCluster?: string;
296
317
  locusId?: string;
297
318
  locusJoinUrl?: string;
298
319
  locusSessionId?: string;
@@ -383,6 +404,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
383
404
  callId?: string;
384
405
  pairCallId?: string;
385
406
  llmWebsocketUrl?: string;
407
+ locusCluster?: string;
386
408
  locusId?: string;
387
409
  locusJoinUrl?: string;
388
410
  locusSessionId?: string;
@@ -609,6 +631,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
609
631
  * Prepare the event and send the request to metrics-a service, pre login.
610
632
  * @param event
611
633
  * @param preLoginId
634
+ * @param markTelemetryOptOutOnResponse
612
635
  * @returns
613
636
  */
614
637
  submitToCallDiagnosticsPreLogin: (event: Event, preLoginId?: string) => Promise<any>;
@@ -102,11 +102,13 @@ export declare const ERROR_DESCRIPTIONS: {
102
102
  WEBRTC_API_NOT_AVAILABLE: string;
103
103
  WDM_RESTRICTED_REGION: string;
104
104
  USER_NOT_ALLOWED_JOIN_WEBINAR: string;
105
+ INVALID_MEETING_INFO: string;
105
106
  };
106
107
  export declare const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP: {
107
108
  58400: number;
108
109
  99002: number;
109
110
  99009: number;
111
+ 99019: number;
110
112
  58500: number;
111
113
  400001: number;
112
114
  403004: number;
@@ -134,6 +136,7 @@ export declare const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP: {
134
136
  423001: number;
135
137
  423005: number;
136
138
  423006: number;
139
+ 423008: number;
137
140
  423010: number;
138
141
  423012: number;
139
142
  423013: number;
@@ -147,6 +150,7 @@ export declare const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP: {
147
150
  403037: number;
148
151
  403003: number;
149
152
  403030: number;
153
+ 403106: number;
150
154
  2403001: number;
151
155
  2403002: number;
152
156
  2403003: number;
@@ -12,6 +12,7 @@ declare namespace _default {
12
12
  const batcherMaxCalls: number;
13
13
  const batcherMaxWait: number;
14
14
  const batcherRetryPlateau: number;
15
+ const batcherRetryOnNetworkError: boolean;
15
16
  const waitForServiceTimeout: number;
16
17
  }
17
18
  export { metrics_1 as metrics };
@@ -42,7 +42,7 @@ export type SubmitMQEOptions = {
42
42
  globalMeetingId?: string;
43
43
  };
44
44
  export type InternalEvent = {
45
- name: 'internal.client.meetinginfo.request' | 'internal.client.meetinginfo.response' | 'internal.register.device.request' | 'internal.register.device.response' | 'internal.reset.join.latencies' | 'internal.client.meeting.click.joinbutton' | 'internal.host.meeting.participant.admitted' | 'internal.client.meeting.interstitial-window.showed' | 'internal.client.interstitial-window.click.joinbutton' | 'internal.client.add-media.turn-discovery.start' | 'internal.client.add-media.turn-discovery.end' | 'internal.client.share.initiated' | 'internal.client.share.stopped';
45
+ name: 'internal.client.meetinginfo.request' | 'internal.client.meetinginfo.response' | 'internal.register.device.request' | 'internal.register.device.response' | 'internal.reset.join.latencies' | 'internal.host.meeting.participant.admitted' | 'internal.client.meeting.interstitial-window.showed' | 'internal.client.interstitial-window.click.joinbutton' | 'internal.client.add-media.turn-discovery.start' | 'internal.client.add-media.turn-discovery.end' | 'internal.client.share.initiated' | 'internal.client.share.stopped';
46
46
  payload?: never;
47
47
  options?: never;
48
48
  };
@@ -154,7 +154,7 @@ export type BuildClientEventFetchRequestOptions = (args: {
154
154
  payload?: RecursivePartial<ClientEvent['payload']>;
155
155
  options?: SubmitClientEventOptions;
156
156
  }) => Promise<any>;
157
- export type PreComputedLatencies = 'internal.client.pageJMT' | 'internal.download.time' | 'internal.get.cluster.time' | 'internal.click.to.interstitial' | 'internal.click.to.interstitial.with.user.delay' | 'internal.refresh.captcha.time' | 'internal.exchange.ci.token.time' | 'internal.get.u2c.time' | 'internal.call.init.join.req' | 'internal.other.app.api.time' | 'internal.api.fetch.intelligence.models';
157
+ export type PreComputedLatencies = 'internal.client.pageJMT' | 'internal.download.time' | 'internal.get.cluster.time' | 'internal.click.to.interstitial' | 'internal.click.to.interstitial.with.user.delay' | 'internal.click.to.interstitial.for.client.jmt' | 'internal.refresh.captcha.time' | 'internal.exchange.ci.token.time' | 'internal.get.u2c.time' | 'internal.call.init.join.req' | 'internal.other.app.api.time' | 'internal.api.fetch.intelligence.models';
158
158
  export interface IdType {
159
159
  meetingId?: string;
160
160
  callId?: string;
package/package.json CHANGED
@@ -24,23 +24,23 @@
24
24
  "@sinonjs/fake-timers": "^6.0.1",
25
25
  "@webex/babel-config-legacy": "0.0.0",
26
26
  "@webex/eslint-config-legacy": "0.0.0",
27
- "@webex/event-dictionary-ts": "^1.0.2138",
27
+ "@webex/event-dictionary-ts": "^1.0.2191",
28
28
  "@webex/jest-config-legacy": "0.0.0",
29
29
  "@webex/legacy-tools": "0.0.0",
30
- "@webex/test-helper-chai": "3.11.0-next.1",
31
- "@webex/test-helper-mocha": "3.11.0-next.1",
32
- "@webex/test-helper-mock-webex": "3.11.0-next.1",
33
- "@webex/test-helper-test-users": "3.11.0-next.1",
30
+ "@webex/test-helper-chai": "3.12.0-webex-services-ready.1",
31
+ "@webex/test-helper-mocha": "3.12.0-webex-services-ready.1",
32
+ "@webex/test-helper-mock-webex": "3.12.0-webex-services-ready.1",
33
+ "@webex/test-helper-test-users": "3.12.0-webex-services-ready.1",
34
34
  "eslint": "^8.24.0",
35
35
  "prettier": "^2.7.1",
36
36
  "sinon": "^9.2.4"
37
37
  },
38
38
  "dependencies": {
39
- "@webex/common": "3.11.0-next.1",
40
- "@webex/common-timers": "3.11.0-next.1",
41
- "@webex/test-helper-chai": "3.11.0-next.1",
42
- "@webex/test-helper-mock-webex": "3.11.0-next.1",
43
- "@webex/webex-core": "3.12.0-next.9",
39
+ "@webex/common": "3.12.0-webex-services-ready.1",
40
+ "@webex/common-timers": "3.12.0-webex-services-ready.1",
41
+ "@webex/test-helper-chai": "3.12.0-webex-services-ready.1",
42
+ "@webex/test-helper-mock-webex": "3.12.0-webex-services-ready.1",
43
+ "@webex/webex-core": "3.12.0-webex-services-ready.1",
44
44
  "ip-anonymize": "^0.1.0",
45
45
  "lodash": "^4.17.21",
46
46
  "uuid": "^3.3.2"
@@ -53,5 +53,5 @@
53
53
  "test:style": "eslint ./src/**/*.*",
54
54
  "test:unit": "webex-legacy-tools test --unit --runner mocha"
55
55
  },
56
- "version": "3.12.0-next.9"
56
+ "version": "3.12.0-webex-services-ready.1"
57
57
  }
package/src/batcher.js CHANGED
@@ -75,6 +75,10 @@ const MetricsBatcher = Batcher.extend({
75
75
  */
76
76
  handleHttpError(reason) {
77
77
  if (reason instanceof WebexHttpError.NetworkOrCORSError) {
78
+ if (!this.config.batcherRetryOnNetworkError) {
79
+ return Reflect.apply(Batcher.prototype.handleHttpError, this, [reason]);
80
+ }
81
+
78
82
  this.logger.warn(
79
83
  'metrics-batcher: received network error submitting metrics, reenqueuing payload'
80
84
  );
@@ -55,6 +55,8 @@ const CallDiagnosticEventsBatcher = Batcher.extend({
55
55
  `CallDiagnosticEventsBatcher: @submitHttpRequest#${batchId}. Request successful.`
56
56
  );
57
57
 
58
+ this.handleHttpResponseStatus(res?.statusCode, payload);
59
+
58
60
  return res;
59
61
  })
60
62
  .catch((err) => {
@@ -64,9 +66,33 @@ const CallDiagnosticEventsBatcher = Batcher.extend({
64
66
  `error: ${generateCommonErrorMetadata(err)}`
65
67
  );
66
68
 
69
+ this.handleHttpResponseStatus(err?.statusCode, payload);
70
+
67
71
  return Promise.reject(err);
68
72
  });
69
73
  },
74
+
75
+ /**
76
+ * React to the HTTP status code returned by the metrics endpoint.
77
+ * Only items submitted with `markTelemetryOptOutOnResponse: true` opt into
78
+ * this behavior.
79
+ * @param {number | undefined} statusCode
80
+ * @param {any[]} payload Items flushed in this HTTP batch.
81
+ * @returns {void}
82
+ */
83
+ handleHttpResponseStatus(statusCode: number | undefined, payload: any[]) {
84
+ const shouldMark =
85
+ Array.isArray(payload) &&
86
+ payload.some((item) => item?.markTelemetryOptOutOnResponse === true);
87
+
88
+ if (!shouldMark) {
89
+ return;
90
+ }
91
+
92
+ if (statusCode === 200) {
93
+ this.webex.internal.newMetrics?.callDiagnosticMetrics?.setIsTelemetryOptOutAutomatic(true);
94
+ }
95
+ },
70
96
  });
71
97
 
72
98
  export default CallDiagnosticEventsBatcher;
@@ -224,11 +224,17 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
224
224
  * @returns - latency
225
225
  */
226
226
  public getCallInitJoinReq() {
227
- return this.getDiffBetweenTimestamps(
228
- 'internal.client.interstitial-window.click.joinbutton',
229
- 'client.locus.join.request',
230
- {maximum: 1200000}
227
+ const interstitialShowedToJoinReq = this.getDiffBetweenTimestamps(
228
+ 'internal.client.meeting.interstitial-window.showed',
229
+ 'client.locus.join.request'
231
230
  );
231
+ const showInterstitialTime = this.getShowInterstitialTime() || 0;
232
+
233
+ if (typeof interstitialShowedToJoinReq !== 'number') {
234
+ return undefined;
235
+ }
236
+
237
+ return clamp(interstitialShowedToJoinReq - showInterstitialTime, 0, 1200000);
232
238
  }
233
239
 
234
240
  /**
@@ -363,14 +369,6 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
363
369
  * @returns - latency
364
370
  */
365
371
  public getClickToInterstitial() {
366
- // for normal join (where green join button exists before interstitial, i.e reminder, space list etc)
367
- if (this.latencyTimestamps.get('internal.client.meeting.click.joinbutton')) {
368
- return this.getDiffBetweenTimestamps(
369
- 'internal.client.meeting.click.joinbutton',
370
- 'internal.client.meeting.interstitial-window.showed'
371
- );
372
- }
373
-
374
372
  const clickToInterstitialLatency = this.precomputedLatencies.get(
375
373
  'internal.click.to.interstitial'
376
374
  );
@@ -387,14 +385,6 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
387
385
  * @returns - latency
388
386
  */
389
387
  public getClickToInterstitialWithUserDelay() {
390
- // for normal join (where green join button exists before interstitial, i.e reminder, space list etc)
391
- if (this.latencyTimestamps.get('internal.client.meeting.click.joinbutton')) {
392
- return this.getDiffBetweenTimestamps(
393
- 'internal.client.meeting.click.joinbutton',
394
- 'internal.client.meeting.interstitial-window.showed'
395
- );
396
- }
397
-
398
388
  const clickToInterstitialWithUserDelayLatency = this.precomputedLatencies.get(
399
389
  'internal.click.to.interstitial.with.user.delay'
400
390
  );
@@ -411,10 +401,17 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
411
401
  * @returns - latency
412
402
  */
413
403
  public getInterstitialToJoinOK() {
414
- return this.getDiffBetweenTimestamps(
415
- 'internal.client.interstitial-window.click.joinbutton',
404
+ const interstitialShowedToJoinResp = this.getDiffBetweenTimestamps(
405
+ 'internal.client.meeting.interstitial-window.showed',
416
406
  'client.locus.join.response'
417
407
  );
408
+ const showInterstitialTime = this.getShowInterstitialTime() || 0;
409
+
410
+ if (typeof interstitialShowedToJoinResp !== 'number') {
411
+ return undefined;
412
+ }
413
+
414
+ return clamp(interstitialShowedToJoinResp - showInterstitialTime, 0, this.MAX_INTEGER);
418
415
  }
419
416
 
420
417
  /**
@@ -430,18 +427,19 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
430
427
  * @returns - latency
431
428
  */
432
429
  public getInterstitialToMediaOKJMT() {
433
- const interstitialClickJoinToIceEnd = this.getDiffBetweenTimestamps(
434
- 'internal.client.interstitial-window.click.joinbutton',
430
+ const interstitialShowedToIceEnd = this.getDiffBetweenTimestamps(
431
+ 'internal.client.meeting.interstitial-window.showed',
435
432
  'client.ice.end'
436
433
  );
434
+ const showInterstitialTime = this.getShowInterstitialTime() || 0;
437
435
  const stayLobbyTimeCappedByIceEnd = this.getStayLobbyTimeCappedBy('client.ice.end');
438
436
 
439
437
  if (
440
- typeof interstitialClickJoinToIceEnd === 'number' &&
438
+ typeof interstitialShowedToIceEnd === 'number' &&
441
439
  typeof stayLobbyTimeCappedByIceEnd === 'number'
442
440
  ) {
443
441
  return clamp(
444
- interstitialClickJoinToIceEnd - stayLobbyTimeCappedByIceEnd,
442
+ interstitialShowedToIceEnd - showInterstitialTime - stayLobbyTimeCappedByIceEnd,
445
443
  0,
446
444
  this.MAX_INTEGER
447
445
  );
@@ -456,17 +454,18 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
456
454
  */
457
455
  public getTotalJMT() {
458
456
  const clickToInterstitial = this.getClickToInterstitial();
459
- const interstitialClickJoinToJoinLocusResponse = this.getDiffBetweenTimestamps(
460
- 'internal.client.interstitial-window.click.joinbutton',
457
+ const interstitialShowedToJoinLocusResponse = this.getDiffBetweenTimestamps(
458
+ 'internal.client.meeting.interstitial-window.showed',
461
459
  'client.locus.join.response'
462
460
  );
461
+ const showInterstitialTime = this.getShowInterstitialTime() || 0;
463
462
 
464
463
  if (
465
464
  typeof clickToInterstitial === 'number' &&
466
- typeof interstitialClickJoinToJoinLocusResponse === 'number'
465
+ typeof interstitialShowedToJoinLocusResponse === 'number'
467
466
  ) {
468
467
  return clamp(
469
- clickToInterstitial + interstitialClickJoinToJoinLocusResponse,
468
+ clickToInterstitial + interstitialShowedToJoinLocusResponse - showInterstitialTime,
470
469
  0,
471
470
  this.MAX_INTEGER
472
471
  );
@@ -521,22 +520,24 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
521
520
  */
522
521
  public getTotalMediaJMT() {
523
522
  const clickToInterstitial = this.getClickToInterstitial();
524
- const interstitialClickJoinToMediaEngineReady = this.getDiffBetweenTimestamps(
525
- 'internal.client.interstitial-window.click.joinbutton',
523
+ const interstitialShowedToMediaEngineReady = this.getDiffBetweenTimestamps(
524
+ 'internal.client.meeting.interstitial-window.showed',
526
525
  'client.media-engine.ready'
527
526
  );
527
+ const showInterstitialTime = this.getShowInterstitialTime() || 0;
528
528
  const stayLobbyTimeCappedByMediaEngineReady = this.getStayLobbyTimeCappedBy(
529
529
  'client.media-engine.ready'
530
530
  );
531
531
 
532
532
  if (
533
533
  typeof clickToInterstitial === 'number' &&
534
- typeof interstitialClickJoinToMediaEngineReady === 'number' &&
534
+ typeof interstitialShowedToMediaEngineReady === 'number' &&
535
535
  typeof stayLobbyTimeCappedByMediaEngineReady === 'number'
536
536
  ) {
537
537
  return clamp(
538
538
  clickToInterstitial +
539
- interstitialClickJoinToMediaEngineReady -
539
+ interstitialShowedToMediaEngineReady -
540
+ showInterstitialTime -
540
541
  stayLobbyTimeCappedByMediaEngineReady,
541
542
  0,
542
543
  this.MAX_INTEGER
@@ -576,11 +577,26 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
576
577
  * @returns - latency
577
578
  */
578
579
  public getClientJMT() {
579
- const interstitialToJoinOk = this.getInterstitialToJoinOK();
580
- const joinConfJMT = this.getJoinConfJMT();
580
+ const clickToInterstitialForClientJmt = this.precomputedLatencies.get(
581
+ 'internal.click.to.interstitial.for.client.jmt'
582
+ );
583
+ const interstitialShowedToLocusJoinRequest = this.getDiffBetweenTimestamps(
584
+ 'internal.client.meeting.interstitial-window.showed',
585
+ 'client.locus.join.request'
586
+ );
587
+ const showInterstitialTime = this.getShowInterstitialTime() || 0;
581
588
 
582
- if (typeof interstitialToJoinOk === 'number' && typeof joinConfJMT === 'number') {
583
- return clamp(interstitialToJoinOk - joinConfJMT, 0, this.MAX_INTEGER);
589
+ if (
590
+ typeof clickToInterstitialForClientJmt === 'number' &&
591
+ typeof interstitialShowedToLocusJoinRequest === 'number'
592
+ ) {
593
+ return clamp(
594
+ clickToInterstitialForClientJmt +
595
+ interstitialShowedToLocusJoinRequest -
596
+ showInterstitialTime,
597
+ 0,
598
+ this.MAX_INTEGER
599
+ );
584
600
  }
585
601
 
586
602
  return undefined;
@@ -108,6 +108,8 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
108
108
  private isMercuryConnected = false;
109
109
  private eventLimitTracker: Map<string, number> = new Map();
110
110
  private eventLimitWarningsLogged: Set<string> = new Set();
111
+ private isTelemetryOptOutManual = false;
112
+ private isTelemetryOptOutAutomatic = false;
111
113
 
112
114
  // the default validator before piping an event to the batcher
113
115
  // this function can be overridden by the user
@@ -145,6 +147,37 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
145
147
  return null;
146
148
  }
147
149
 
150
+ /**
151
+ * Returns the telemetryOptOut value of the current user
152
+ * @returns one of 'manual', 'automatic', undefined
153
+ */
154
+ public getTelemetryOptOut() {
155
+ if (this.isTelemetryOptOutManual) {
156
+ return 'manual';
157
+ }
158
+ if (this.isTelemetryOptOutAutomatic) {
159
+ return 'automatic';
160
+ }
161
+
162
+ return undefined;
163
+ }
164
+
165
+ /**
166
+ * Sets the manual telemetry opt-out status for the current user
167
+ * @param value - boolean value indicating manual telemetry opt-out status
168
+ */
169
+ public setIsTelemetryOptOutManual(value: boolean) {
170
+ this.isTelemetryOptOutManual = value;
171
+ }
172
+
173
+ /**
174
+ * Sets the automatic telemetry opt-out status for the current user
175
+ * @param value - boolean value indicating automatic telemetry opt-out status
176
+ */
177
+ public setIsTelemetryOptOutAutomatic(value: boolean) {
178
+ this.isTelemetryOptOutAutomatic = value;
179
+ }
180
+
148
181
  /**
149
182
  * Returns if the meeting has converged architecture enabled
150
183
  * @param options.meetingId
@@ -607,6 +640,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
607
640
  mediaEngineSoftwareVersion: getOSVersion() || 'unknown',
608
641
  startTime: new Date().toISOString(),
609
642
  },
643
+ webexSubServiceType: this.getSubServiceType(meeting),
610
644
  };
611
645
 
612
646
  // merge any new properties, or override existing ones
@@ -989,7 +1023,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
989
1023
  sessionCorrelationId,
990
1024
  });
991
1025
 
992
- // create common event object structur
1026
+ // create common event object structure
993
1027
  const commonEventObject = {
994
1028
  name,
995
1029
  canProceed: true,
@@ -1002,6 +1036,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
1002
1036
  'loginType' in meeting.callStateForMetrics
1003
1037
  ? meeting.callStateForMetrics.loginType
1004
1038
  : this.getCurLoginType(),
1039
+ telemetryOptOut: this.getTelemetryOptOut(),
1005
1040
  isConvergedArchitectureEnabled: this.getIsConvergedArchitectureEnabled({
1006
1041
  meetingId,
1007
1042
  }),
@@ -1010,6 +1045,9 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
1010
1045
  webexSubServiceType: this.getSubServiceType(meeting),
1011
1046
  // @ts-ignore
1012
1047
  webClientPreload: this.webex.meetings?.config?.metrics?.webClientPreload,
1048
+ isVipMeeting: meeting?.meetingInfo?.vipmeeting || false,
1049
+ isAutomatedUser:
1050
+ typeof window !== 'undefined' && typeof navigator !== 'undefined' && !!navigator?.webdriver, // if webdriver is true, it's most likely in a test environment
1013
1051
  };
1014
1052
 
1015
1053
  const joinFlowVersion = options.joinFlowVersion ?? meeting.callStateForMetrics?.joinFlowVersion;
@@ -1129,8 +1167,11 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
1129
1167
  isMercuryConnected: this.isMercuryConnected,
1130
1168
  },
1131
1169
  loginType: this.getCurLoginType(),
1170
+ telemetryOptOut: this.getTelemetryOptOut(),
1132
1171
  // @ts-ignore
1133
1172
  webClientPreload: this.webex.meetings?.config?.metrics?.webClientPreload,
1173
+ isAutomatedUser:
1174
+ typeof window !== 'undefined' && typeof navigator !== 'undefined' && !!navigator?.webdriver, // if webdriver is true, it's most likely in a test environment
1134
1175
  };
1135
1176
 
1136
1177
  if (options.joinFlowVersion) {
@@ -1323,6 +1364,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
1323
1364
  const finalEvent = {
1324
1365
  eventPayload: event,
1325
1366
  type: ['diagnostic-event'],
1367
+ markTelemetryOptOutOnResponse: true,
1326
1368
  };
1327
1369
 
1328
1370
  return this.callDiagnosticEventsBatcher.request(finalEvent);
@@ -1332,6 +1374,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
1332
1374
  * Prepare the event and send the request to metrics-a service, pre login.
1333
1375
  * @param event
1334
1376
  * @param preLoginId
1377
+ * @param markTelemetryOptOutOnResponse
1335
1378
  * @returns
1336
1379
  */
1337
1380
  submitToCallDiagnosticsPreLogin = (event: Event, preLoginId?: string): Promise<any> => {
@@ -1339,7 +1382,9 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
1339
1382
  const finalEvent = {
1340
1383
  eventPayload: event,
1341
1384
  type: ['diagnostic-event'],
1385
+ markTelemetryOptOutOnResponse: true,
1342
1386
  };
1387
+
1343
1388
  this.preLoginMetricsBatcher.savePreLoginId(preLoginId);
1344
1389
 
1345
1390
  return this.preLoginMetricsBatcher.request(finalEvent);
@@ -390,6 +390,11 @@ export const prepareDiagnosticMetricItem = (webex: any, item: any) => {
390
390
 
391
391
  item.eventPayload.origin = Object.assign(origin, item.eventPayload.origin);
392
392
 
393
+ // Mark call milestones in logs for easier filtering and analysis
394
+ if (eventName) {
395
+ webex.logger.log('Milestone,CallDiagnostic', eventName);
396
+ }
397
+
393
398
  webex.logger.log(
394
399
  `CallDiagnosticLatencies,prepareDiagnosticMetricItem: ${JSON.stringify({
395
400
  latencies: Object.fromEntries(cdl.latencyTimestamps),
@@ -137,6 +137,7 @@ export const ERROR_DESCRIPTIONS = {
137
137
  WEBRTC_API_NOT_AVAILABLE: 'WebrtcApiNotAvailableError',
138
138
  WDM_RESTRICTED_REGION: 'WdmRestrictedRegion',
139
139
  USER_NOT_ALLOWED_JOIN_WEBINAR: 'UserNotAllowedJoinWebinar',
140
+ INVALID_MEETING_INFO: 'InvalidMeetingInfo',
140
141
  };
141
142
 
142
143
  export const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP = {
@@ -147,6 +148,8 @@ export const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP = {
147
148
  99002: 4100,
148
149
  // Cannot find the data. Unkown meeting.
149
150
  99009: 4100,
151
+ // The input parameters contain invalid item
152
+ 99019: 4105,
150
153
  // Meeting is not allow to cross env
151
154
  58500: 4100,
152
155
  // Input parameters contain invalit item
@@ -202,6 +205,8 @@ export const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP = {
202
205
  423005: 4005,
203
206
  // Wrong password or host key with too many requests
204
207
  423006: 4005,
208
+ // PanelistPasswordError too many time,please input captcha code
209
+ 423008: 4005,
205
210
  // PasswordError with right captcha, please input captcha code
206
211
  423010: 4005,
207
212
  // PasswordOrHostKeyError with right captcha, please input captcha code
@@ -228,6 +233,8 @@ export const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP = {
228
233
  403003: 4101,
229
234
  // Attendee email is required
230
235
  403030: 4101,
236
+ // webinar need login when un-invited attendee join
237
+ 403106: 4104,
231
238
 
232
239
  // ---- Locus ------
233
240
  // FREE_USER_MAX_PARTICIPANTS_EXCEEDED
@@ -697,6 +704,12 @@ export const CLIENT_ERROR_CODE_TO_ERROR_PAYLOAD: Record<number, Partial<ClientEv
697
704
  category: 'expected',
698
705
  fatal: true,
699
706
  },
707
+ 4105: {
708
+ errorDescription: ERROR_DESCRIPTIONS.INVALID_MEETING_INFO,
709
+ category: 'expected',
710
+ fatal: false,
711
+ shownToUser: true,
712
+ },
700
713
  2729: {
701
714
  errorDescription: ERROR_DESCRIPTIONS.NO_MEDIA_FOUND,
702
715
  category: 'expected',
package/src/config.js CHANGED
@@ -19,6 +19,7 @@ export default {
19
19
  batcherMaxCalls: 50,
20
20
  batcherMaxWait: 1500,
21
21
  batcherRetryPlateau: 32000,
22
+ batcherRetryOnNetworkError: true,
22
23
  waitForServiceTimeout: 30,
23
24
  },
24
25
  };
@@ -156,7 +156,6 @@ export type InternalEvent = {
156
156
  | 'internal.register.device.request'
157
157
  | 'internal.register.device.response'
158
158
  | 'internal.reset.join.latencies'
159
- | 'internal.client.meeting.click.joinbutton'
160
159
  | 'internal.host.meeting.participant.admitted'
161
160
  | 'internal.client.meeting.interstitial-window.showed'
162
161
  | 'internal.client.interstitial-window.click.joinbutton'
@@ -319,6 +318,7 @@ export type PreComputedLatencies =
319
318
  | 'internal.get.cluster.time'
320
319
  | 'internal.click.to.interstitial'
321
320
  | 'internal.click.to.interstitial.with.user.delay'
321
+ | 'internal.click.to.interstitial.for.client.jmt'
322
322
  | 'internal.refresh.captcha.time'
323
323
  | 'internal.exchange.ci.token.time'
324
324
  | 'internal.get.u2c.time'