@webex/internal-plugin-metrics 3.0.0-beta.23 → 3.0.0-beta.230

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 (60) hide show
  1. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +66 -0
  2. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -0
  3. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +446 -0
  4. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -0
  5. package/dist/call-diagnostic/call-diagnostic-metrics.js +693 -0
  6. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -0
  7. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +276 -0
  8. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -0
  9. package/dist/call-diagnostic/config.js +582 -0
  10. package/dist/call-diagnostic/config.js.map +1 -0
  11. package/dist/config.js +20 -1
  12. package/dist/config.js.map +1 -1
  13. package/dist/index.js +28 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/metrics.js +30 -30
  16. package/dist/metrics.js.map +1 -1
  17. package/dist/metrics.types.js +7 -0
  18. package/dist/metrics.types.js.map +1 -0
  19. package/dist/new-metrics.js +316 -0
  20. package/dist/new-metrics.js.map +1 -0
  21. package/dist/types/batcher.d.ts +2 -0
  22. package/dist/types/call-diagnostic/call-diagnostic-metrics-batcher.d.ts +2 -0
  23. package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +189 -0
  24. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +385 -0
  25. package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +73 -0
  26. package/dist/types/call-diagnostic/config.d.ts +87 -0
  27. package/dist/types/client-metrics-batcher.d.ts +2 -0
  28. package/dist/types/config.d.ts +35 -0
  29. package/dist/types/index.d.ts +12 -0
  30. package/dist/types/metrics.d.ts +3 -0
  31. package/dist/types/metrics.types.d.ts +99 -0
  32. package/dist/types/new-metrics.d.ts +133 -0
  33. package/dist/types/utils.d.ts +6 -0
  34. package/dist/utils.js +27 -0
  35. package/dist/utils.js.map +1 -0
  36. package/package.json +13 -8
  37. package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +80 -0
  38. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +403 -0
  39. package/src/call-diagnostic/call-diagnostic-metrics.ts +751 -0
  40. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +280 -0
  41. package/src/call-diagnostic/config.ts +580 -0
  42. package/src/config.js +19 -0
  43. package/src/index.ts +42 -0
  44. package/src/metrics.js +25 -27
  45. package/src/metrics.types.ts +152 -0
  46. package/src/new-metrics.ts +304 -0
  47. package/src/utils.ts +17 -0
  48. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +351 -0
  49. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +465 -0
  50. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +1283 -0
  51. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +454 -0
  52. package/test/unit/spec/metrics.js +65 -97
  53. package/test/unit/spec/new-metrics.ts +234 -0
  54. package/test/unit/spec/utils.ts +22 -0
  55. package/tsconfig.json +6 -0
  56. package/dist/call-diagnostic-events-batcher.js +0 -60
  57. package/dist/call-diagnostic-events-batcher.js.map +0 -1
  58. package/src/call-diagnostic-events-batcher.js +0 -62
  59. package/src/index.js +0 -17
  60. package/test/unit/spec/call-diagnostic-events-batcher.js +0 -195
package/src/metrics.js CHANGED
@@ -6,14 +6,17 @@
6
6
 
7
7
  import {WebexPlugin} from '@webex/webex-core';
8
8
  import {BrowserDetection} from '@webex/common';
9
+ import {OS_NAME, OSMap, CLIENT_NAME} from './config';
9
10
 
10
- import {CLIENT_NAME} from './config';
11
11
  import Batcher from './batcher';
12
12
  import ClientMetricsBatcher from './client-metrics-batcher';
13
- import CallDiagnosticEventsBatcher from './call-diagnostic-events-batcher';
14
13
 
15
14
  const {getOSName, getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
16
15
 
16
+ export function getOSNameInternal() {
17
+ return OSMap[getOSName()] ?? OS_NAME.OTHERS;
18
+ }
19
+
17
20
  function getSparkUserAgent(webex) {
18
21
  const {appName, appVersion, appPlatform} = webex?.config ?? {};
19
22
 
@@ -34,7 +37,6 @@ const Metrics = WebexPlugin.extend({
34
37
  children: {
35
38
  batcher: Batcher,
36
39
  clientMetricsBatcher: ClientMetricsBatcher,
37
- callDiagnosticEventsBatcher: CallDiagnosticEventsBatcher,
38
40
  },
39
41
 
40
42
  namespace: 'Metrics',
@@ -44,13 +46,12 @@ const Metrics = WebexPlugin.extend({
44
46
  },
45
47
 
46
48
  /**
47
- * This corresponds to #sendSemiStructured() in the deprecated metrics handler
49
+ * Returns the payload for submitting client metrics.
48
50
  * @param {string} eventName
49
- * @param {Object} props
50
- * @param {string} preLoginId
51
- * @returns {Object} HttpResponse object
51
+ * @param {any} props
52
+ * @returns {any} - the payload
52
53
  */
53
- submitClientMetrics(eventName, props = {}, preLoginId) {
54
+ getClientMetricsPayload(eventName, props) {
54
55
  if (!eventName) {
55
56
  throw Error('Missing behavioral metric name. Please provide one');
56
57
  }
@@ -59,22 +60,14 @@ const Metrics = WebexPlugin.extend({
59
60
  payload.tags = {
60
61
  ...props.tags,
61
62
  browser: getBrowserName(),
62
- os: getOSName(),
63
+ os: getOSNameInternal(),
63
64
 
64
65
  // Node does not like this so we need to check if it exists or not
65
66
  // eslint-disable-next-line no-undef
66
67
  domain:
67
68
  typeof window !== 'undefined' ? window.location.hostname || 'non-browser' : 'non-browser', // Check what else we could measure
68
- client_id: this.webex.credentials.config.client_id,
69
- user_id: this.webex.internal.device.userId,
70
69
  };
71
70
 
72
- try {
73
- payload.tags.org_id = this.webex.credentials.getOrgId();
74
- } catch {
75
- this.logger.info('metrics: unable to get orgId');
76
- }
77
-
78
71
  payload.fields = {
79
72
  ...props.fields,
80
73
  browser_version: getBrowserVersion(),
@@ -82,6 +75,7 @@ const Metrics = WebexPlugin.extend({
82
75
  sdk_version: this.webex.version,
83
76
  platform: 'Web',
84
77
  spark_user_agent: getSparkUserAgent(this.webex),
78
+ client_id: this.webex.credentials.config.client_id,
85
79
  };
86
80
 
87
81
  payload.type = props.type || this.webex.config.metrics.type;
@@ -93,7 +87,7 @@ const Metrics = WebexPlugin.extend({
93
87
  },
94
88
  locale: 'en-US',
95
89
  os: {
96
- name: getOSName(),
90
+ name: getOSNameInternal(),
97
91
  version: getOSVersion(),
98
92
  },
99
93
  };
@@ -106,6 +100,19 @@ const Metrics = WebexPlugin.extend({
106
100
  // is impossible so unable to use Date.now()
107
101
  payload.timestamp = new Date().valueOf();
108
102
 
103
+ return payload;
104
+ },
105
+
106
+ /**
107
+ * This corresponds to #sendSemiStructured() in the deprecated metrics handler
108
+ * @param {string} eventName
109
+ * @param {Object} props
110
+ * @param {string} preLoginId
111
+ * @returns {Object} HttpResponse object
112
+ */
113
+ submitClientMetrics(eventName, props = {}, preLoginId) {
114
+ const payload = this.getClientMetricsPayload(eventName, props);
115
+
109
116
  if (preLoginId) {
110
117
  const _payload = {
111
118
  metrics: [payload],
@@ -154,15 +161,6 @@ const Metrics = WebexPlugin.extend({
154
161
  })
155
162
  );
156
163
  },
157
-
158
- submitCallDiagnosticEvents(payload) {
159
- const event = {
160
- type: 'diagnostic-event',
161
- eventPayload: payload,
162
- };
163
-
164
- return this.callDiagnosticEventsBatcher.request(event);
165
- },
166
164
  });
167
165
 
168
166
  export default Metrics;
@@ -0,0 +1,152 @@
1
+ import {
2
+ ClientEvent as RawClientEvent,
3
+ Event as RawEvent,
4
+ MediaQualityEvent as RawMediaQualityEvent,
5
+ } from '@webex/event-dictionary-ts';
6
+
7
+ export type Event = Omit<RawEvent, 'event'> & {event: RawClientEvent | RawMediaQualityEvent};
8
+
9
+ export type ClientEventError = NonNullable<RawClientEvent['errors']>[0];
10
+
11
+ export type EnvironmentType = NonNullable<RawEvent['origin']['environment']>;
12
+
13
+ export type NewEnvironmentType = NonNullable<RawEvent['origin']['newEnvironment']>;
14
+
15
+ export type ClientLaunchMethodType = NonNullable<
16
+ RawEvent['origin']['clientInfo']
17
+ >['clientLaunchMethod'];
18
+
19
+ export type SubmitClientEventOptions = {
20
+ meetingId?: string;
21
+ mediaConnections?: any[];
22
+ rawError?: any;
23
+ correlationId?: string;
24
+ preLoginId?: string;
25
+ environment?: EnvironmentType;
26
+ newEnvironmentType?: NewEnvironmentType;
27
+ clientLaunchMethod?: ClientLaunchMethodType;
28
+ };
29
+
30
+ export type SubmitMQEOptions = {
31
+ meetingId: string;
32
+ mediaConnections?: any[];
33
+ networkType?: Event['origin']['networkType'];
34
+ };
35
+
36
+ export type InternalEvent = {
37
+ name:
38
+ | 'internal.client.meetinginfo.request'
39
+ | 'internal.client.meetinginfo.response'
40
+ | 'internal.reset.join.latencies'
41
+ | 'internal.client.meeting.click.joinbutton'
42
+ | 'internal.host.meeting.participant.admitted'
43
+ | 'internal.client.meeting.interstitial-window.showed'
44
+ | 'internal.client.interstitial-window.click.joinbutton';
45
+ payload?: never;
46
+ options?: never;
47
+ };
48
+
49
+ export interface ClientEvent {
50
+ name: RawClientEvent['name'];
51
+ payload?: RawClientEvent;
52
+ options?: SubmitClientEventOptions;
53
+ }
54
+
55
+ export interface BehavioralEvent {
56
+ // TODO: not implemented
57
+ name: 'host.meeting.participant.admitted' | 'sdk.media-flow.started';
58
+ payload?: never;
59
+ options?: never;
60
+ }
61
+
62
+ export interface OperationalEvent {
63
+ // TODO: not implemented
64
+ name: never;
65
+ payload?: never;
66
+ options?: never;
67
+ }
68
+
69
+ export interface FeatureEvent {
70
+ // TODO: not implemented
71
+ name: never;
72
+ payload?: never;
73
+ options?: never;
74
+ }
75
+
76
+ export interface MediaQualityEvent {
77
+ name: RawMediaQualityEvent['name'];
78
+ payload?: RawMediaQualityEvent;
79
+ options: SubmitMQEOptions;
80
+ }
81
+
82
+ export type RecursivePartial<T> = {
83
+ [P in keyof T]?: T[P] extends (infer U)[]
84
+ ? RecursivePartial<U>[]
85
+ : T[P] extends object
86
+ ? RecursivePartial<T[P]>
87
+ : T[P];
88
+ };
89
+
90
+ export type MetricEventNames =
91
+ | InternalEvent['name']
92
+ | ClientEvent['name']
93
+ | BehavioralEvent['name']
94
+ | OperationalEvent['name']
95
+ | FeatureEvent['name']
96
+ | MediaQualityEvent['name'];
97
+
98
+ export type ClientInfo = NonNullable<RawEvent['origin']['clientInfo']>;
99
+ export type ClientType = NonNullable<RawEvent['origin']['clientInfo']>['clientType'];
100
+ export type SubClientType = NonNullable<RawEvent['origin']['clientInfo']>['subClientType'];
101
+ export type NetworkType = NonNullable<RawEvent['origin']>['networkType'];
102
+
103
+ export type ClientEventPayload = RecursivePartial<ClientEvent['payload']>;
104
+ export type ClientEventLeaveReason = ClientEvent['payload']['leaveReason'];
105
+ export type ClientEventPayloadError = ClientEvent['payload']['errors'];
106
+
107
+ export type MediaQualityEventAudioSetupDelayPayload = NonNullable<
108
+ MediaQualityEvent['payload']
109
+ >['audioSetupDelay'];
110
+ export type MediaQualityEventVideoSetupDelayPayload = NonNullable<
111
+ MediaQualityEvent['payload']
112
+ >['videoSetupDelay'];
113
+
114
+ export type SubmitMQEPayload = RecursivePartial<MediaQualityEvent['payload']> & {
115
+ intervals: NonNullable<MediaQualityEvent['payload']>['intervals'];
116
+ };
117
+
118
+ export type SubmitInternalEvent = (args: {
119
+ name: InternalEvent['name'];
120
+ payload?: RecursivePartial<InternalEvent['payload']>;
121
+ options?: any;
122
+ }) => void;
123
+
124
+ export type SubmitBehavioralEvent = (args: {
125
+ name: BehavioralEvent['name'];
126
+ payload?: RecursivePartial<BehavioralEvent['payload']>;
127
+ options?: any;
128
+ }) => void;
129
+
130
+ export type SubmitClientEvent = (args: {
131
+ name: ClientEvent['name'];
132
+ payload?: RecursivePartial<ClientEvent['payload']>;
133
+ options?: SubmitClientEventOptions;
134
+ }) => Promise<any>;
135
+
136
+ export type SubmitOperationalEvent = (args: {
137
+ name: OperationalEvent['name'];
138
+ payload?: RecursivePartial<OperationalEvent['payload']>;
139
+ options?: any;
140
+ }) => void;
141
+
142
+ export type SubmitMQE = (args: {
143
+ name: MediaQualityEvent['name'];
144
+ payload: SubmitMQEPayload;
145
+ options: any;
146
+ }) => void;
147
+
148
+ export type BuildClientEventFetchRequestOptions = (args: {
149
+ name: ClientEvent['name'];
150
+ payload?: RecursivePartial<ClientEvent['payload']>;
151
+ options?: SubmitClientEventOptions;
152
+ }) => Promise<any>;
@@ -0,0 +1,304 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ /* eslint-disable class-methods-use-this */
3
+ /* eslint-disable valid-jsdoc */
4
+
5
+ // @ts-ignore
6
+ import {WebexPlugin} from '@webex/webex-core';
7
+
8
+ import CallDiagnosticMetrics from './call-diagnostic/call-diagnostic-metrics';
9
+ import {
10
+ RecursivePartial,
11
+ ClientEvent,
12
+ FeatureEvent,
13
+ BehavioralEvent,
14
+ OperationalEvent,
15
+ MediaQualityEvent,
16
+ InternalEvent,
17
+ SubmitClientEventOptions,
18
+ } from './metrics.types';
19
+ import CallDiagnosticLatencies from './call-diagnostic/call-diagnostic-metrics-latencies';
20
+ import {setMetricTimings} from './call-diagnostic/call-diagnostic-metrics.util';
21
+ import {generateCommonErrorMetadata} from './utils';
22
+
23
+ /**
24
+ * Metrics plugin to centralize all types of metrics.
25
+ * @class
26
+ */
27
+ class Metrics extends WebexPlugin {
28
+ // eslint-disable-next-line no-use-before-define
29
+ static instance: Metrics;
30
+
31
+ // Call Diagnostic latencies
32
+ callDiagnosticLatencies: CallDiagnosticLatencies;
33
+ // Helper classes to handle the different types of metrics
34
+ callDiagnosticMetrics: CallDiagnosticMetrics;
35
+
36
+ /**
37
+ * Constructor
38
+ * @param args
39
+ * @constructor
40
+ * @private
41
+ * @returns
42
+ */
43
+ constructor(...args) {
44
+ super(...args);
45
+
46
+ this.onReady();
47
+ }
48
+
49
+ /**
50
+ * On Ready
51
+ */
52
+ private onReady() {
53
+ // @ts-ignore
54
+ this.webex.once('ready', () => {
55
+ // @ts-ignore
56
+ this.callDiagnosticMetrics = new CallDiagnosticMetrics({}, {parent: this.webex});
57
+ // @ts-ignore
58
+ this.callDiagnosticLatencies = new CallDiagnosticLatencies({}, {parent: this.webex});
59
+ });
60
+ }
61
+
62
+ /**
63
+ * Used for internal purposes only
64
+ * @param args
65
+ */
66
+ submitInternalEvent({
67
+ name,
68
+ payload,
69
+ options,
70
+ }: {
71
+ name: InternalEvent['name'];
72
+ payload?: RecursivePartial<InternalEvent['payload']>;
73
+ options?: any;
74
+ }) {
75
+ if (name === 'internal.reset.join.latencies') {
76
+ this.callDiagnosticLatencies.clearTimestamps();
77
+ } else {
78
+ this.callDiagnosticLatencies.saveTimestamp({key: name});
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Behavioral event
84
+ * @param args
85
+ */
86
+ submitBehavioralEvent({
87
+ name,
88
+ payload,
89
+ options,
90
+ }: {
91
+ name: BehavioralEvent['name'];
92
+ payload?: RecursivePartial<BehavioralEvent['payload']>;
93
+ options?: any;
94
+ }) {
95
+ this.callDiagnosticLatencies.saveTimestamp({key: name});
96
+ throw new Error('Not implemented.');
97
+ }
98
+
99
+ /**
100
+ * Operational event
101
+ * @param args
102
+ */
103
+ submitOperationalEvent({
104
+ name,
105
+ payload,
106
+ options,
107
+ }: {
108
+ name: OperationalEvent['name'];
109
+ payload?: RecursivePartial<OperationalEvent['payload']>;
110
+ options?: any;
111
+ }) {
112
+ throw new Error('Not implemented.');
113
+ }
114
+
115
+ /**
116
+ * Call Analyzer: Media Quality Event
117
+ * @param args
118
+ */
119
+ submitMQE({
120
+ name,
121
+ payload,
122
+ options,
123
+ }: {
124
+ name: MediaQualityEvent['name'];
125
+ payload: RecursivePartial<MediaQualityEvent['payload']> & {
126
+ intervals: MediaQualityEvent['payload']['intervals'];
127
+ };
128
+ options: any;
129
+ }) {
130
+ this.callDiagnosticLatencies.saveTimestamp({key: name});
131
+ this.callDiagnosticMetrics.submitMQE({name, payload, options});
132
+ }
133
+
134
+ /**
135
+ * Call Analyzer: Feature Usage Event
136
+ * @param args
137
+ */
138
+ submitFeatureEvent({
139
+ name,
140
+ payload,
141
+ options,
142
+ }: {
143
+ name: FeatureEvent['name'];
144
+ payload?: RecursivePartial<FeatureEvent['payload']>;
145
+ options: any;
146
+ }) {
147
+ throw new Error('Not implemented.');
148
+ }
149
+
150
+ /**
151
+ * Call Analyzer: Client Event
152
+ * @public
153
+ * @param args
154
+ */
155
+ public submitClientEvent({
156
+ name,
157
+ payload,
158
+ options,
159
+ }: {
160
+ name: ClientEvent['name'];
161
+ payload?: RecursivePartial<ClientEvent['payload']>;
162
+ options?: SubmitClientEventOptions;
163
+ }): Promise<any> {
164
+ this.callDiagnosticLatencies.saveTimestamp({
165
+ key: name,
166
+ options: {meetingId: options?.meetingId},
167
+ });
168
+
169
+ return this.callDiagnosticMetrics.submitClientEvent({name, payload, options});
170
+ }
171
+
172
+ /**
173
+ * Submit a pre-login metric to clientmetrics
174
+ * @public
175
+ * @param payload
176
+ * @param preLoginId - pre-login ID of user
177
+ * @returns
178
+ */
179
+ public postPreLoginMetric(payload: any, preLoginId: string): Promise<any> {
180
+ // @ts-ignore
181
+ return this.webex
182
+ .request({
183
+ method: 'POST',
184
+ api: 'metrics',
185
+ resource: 'clientmetrics-prelogin',
186
+ headers: {
187
+ authorization: false,
188
+ 'x-prelogin-userid': preLoginId,
189
+ },
190
+ body: payload,
191
+ })
192
+ .then((res) => {
193
+ // @ts-ignore
194
+ this.webex.logger.log(
195
+ `NewMetrics: @postPreLoginMetric. Request successful:`,
196
+ `res: ${JSON.stringify(res)}`
197
+ );
198
+
199
+ return res;
200
+ })
201
+ .catch((err) => {
202
+ // @ts-ignore
203
+ this.logger.error(
204
+ `NewMetrics: @postPreLoginMetric. Request failed:`,
205
+ `err: ${generateCommonErrorMetadata(err)}`
206
+ );
207
+
208
+ return Promise.reject(err);
209
+ });
210
+ }
211
+
212
+ /**
213
+ * Issue request to alias a user's pre-login ID with their CI UUID
214
+ * @param {string} preLoginId
215
+ * @returns {Object} HttpResponse object
216
+ */
217
+ public clientMetricsAliasUser(preLoginId: string) {
218
+ // @ts-ignore
219
+ return this.webex
220
+ .request({
221
+ method: 'POST',
222
+ api: 'metrics',
223
+ resource: 'clientmetrics',
224
+ headers: {
225
+ 'x-prelogin-userid': preLoginId,
226
+ },
227
+ body: {},
228
+ qs: {
229
+ alias: true,
230
+ },
231
+ })
232
+ .then((res) => {
233
+ // @ts-ignore
234
+ this.webex.logger.log(
235
+ `NewMetrics: @clientMetricsAliasUser. Request successful:`,
236
+ `res: ${JSON.stringify(res)}`
237
+ );
238
+
239
+ return res;
240
+ })
241
+ .catch((err) => {
242
+ // @ts-ignore
243
+ this.logger.error(
244
+ `NewMetrics: @clientMetricsAliasUser. Request failed:`,
245
+ `err: ${generateCommonErrorMetadata(err)}`
246
+ );
247
+
248
+ return Promise.reject(err);
249
+ });
250
+ }
251
+
252
+ /**
253
+ * Returns a promise that will resolve to fetch options for submitting a metric.
254
+ *
255
+ * This is to support quickly submitting metrics when the browser/tab is closing.
256
+ * Calling submitClientEvent will not work because there some async steps that will
257
+ * not complete before the browser is closed. Instead, we pre-gather all the
258
+ * information/options needed for the request(s), and then simply and quickly
259
+ * fire the fetch(es) when beforeUnload is triggered.
260
+ *
261
+ * We must use fetch instead of request because fetch has a keepalive option that
262
+ * allows the request it to outlive the page.
263
+ *
264
+ * Note: the timings values will be wrong, but setMetricTimingsAndFetch() will
265
+ * properly adjust them before submitting.
266
+ *
267
+ * @public
268
+ * @param {Object} arg
269
+ * @param {String} arg.name - event name
270
+ * @param {Object} arg.payload - event payload
271
+ * @param {Object} arg.options - other options
272
+ * @returns {Promise} promise that resolves to options to be used with fetch
273
+ */
274
+ public async buildClientEventFetchRequestOptions({
275
+ name,
276
+ payload,
277
+ options,
278
+ }: {
279
+ name: ClientEvent['name'];
280
+ payload?: RecursivePartial<ClientEvent['payload']>;
281
+ options?: SubmitClientEventOptions;
282
+ }): Promise<any> {
283
+ return this.callDiagnosticMetrics.buildClientEventFetchRequestOptions({
284
+ name,
285
+ payload,
286
+ options,
287
+ });
288
+ }
289
+
290
+ /**
291
+ * Submits a metric from pre-built request options via the fetch API. Updates
292
+ * the "$timings" and "originTime" values to Date.now() since the existing times
293
+ * were set when the options were built (not submitted).
294
+
295
+ * @param {any} options - the pre-built request options for submitting a metric
296
+ * @returns {Promise} promise that resolves to the response object
297
+ */
298
+ public setMetricTimingsAndFetch(options: any): Promise<any> {
299
+ // @ts-ignore
300
+ return this.webex.setTimingsAndFetch(setMetricTimings(options));
301
+ }
302
+ }
303
+
304
+ export default Metrics;
package/src/utils.ts ADDED
@@ -0,0 +1,17 @@
1
+ /* eslint-disable import/prefer-default-export */
2
+ /**
3
+ * Generates common metadata for errors
4
+ * @param {any} error
5
+ * @returns {object}
6
+ */
7
+ export const generateCommonErrorMetadata = (error) => {
8
+ if (error instanceof Error) {
9
+ return JSON.stringify({
10
+ message: error?.message,
11
+ name: error?.name,
12
+ stack: error?.stack,
13
+ });
14
+ }
15
+
16
+ return error;
17
+ };