@webex/internal-plugin-metrics 3.0.0-beta.2 → 3.0.0-beta.200

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 (76) hide show
  1. package/README.md +1 -3
  2. package/dist/batcher.js +3 -22
  3. package/dist/batcher.js.map +1 -1
  4. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +56 -0
  5. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -0
  6. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +451 -0
  7. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -0
  8. package/dist/call-diagnostic/call-diagnostic-metrics.js +584 -0
  9. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -0
  10. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +225 -0
  11. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -0
  12. package/dist/call-diagnostic/config.js +461 -0
  13. package/dist/call-diagnostic/config.js.map +1 -0
  14. package/dist/call-diagnostic/generated-types-temp/ClientEvent.js +7 -0
  15. package/dist/call-diagnostic/generated-types-temp/ClientEvent.js.map +1 -0
  16. package/dist/call-diagnostic/generated-types-temp/Event.js +7 -0
  17. package/dist/call-diagnostic/generated-types-temp/Event.js.map +1 -0
  18. package/dist/call-diagnostic/generated-types-temp/MediaQualityEvent.js +7 -0
  19. package/dist/call-diagnostic/generated-types-temp/MediaQualityEvent.js.map +1 -0
  20. package/dist/client-metrics-batcher.js +1 -7
  21. package/dist/client-metrics-batcher.js.map +1 -1
  22. package/dist/config.js +21 -5
  23. package/dist/config.js.map +1 -1
  24. package/dist/index.js +26 -10
  25. package/dist/index.js.map +1 -1
  26. package/dist/metrics.js +43 -80
  27. package/dist/metrics.js.map +1 -1
  28. package/dist/metrics.types.js +7 -0
  29. package/dist/metrics.types.js.map +1 -0
  30. package/dist/new-metrics.js +249 -0
  31. package/dist/new-metrics.js.map +1 -0
  32. package/dist/types/batcher.d.ts +2 -0
  33. package/dist/types/call-diagnostic/call-diagnostic-metrics-batcher.d.ts +2 -0
  34. package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +189 -0
  35. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +348 -0
  36. package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +52 -0
  37. package/dist/types/call-diagnostic/config.d.ts +57 -0
  38. package/dist/types/call-diagnostic/generated-types-temp/ClientEvent.d.ts +1112 -0
  39. package/dist/types/call-diagnostic/generated-types-temp/Event.d.ts +4851 -0
  40. package/dist/types/call-diagnostic/generated-types-temp/MediaQualityEvent.d.ts +2121 -0
  41. package/dist/types/client-metrics-batcher.d.ts +2 -0
  42. package/dist/types/config.d.ts +35 -0
  43. package/dist/types/index.d.ts +11 -0
  44. package/dist/types/metrics.d.ts +3 -0
  45. package/dist/types/metrics.types.d.ts +92 -0
  46. package/dist/types/new-metrics.d.ts +119 -0
  47. package/package.json +12 -8
  48. package/src/batcher.js +33 -26
  49. package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +51 -0
  50. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +408 -0
  51. package/src/call-diagnostic/call-diagnostic-metrics.ts +591 -0
  52. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +233 -0
  53. package/src/call-diagnostic/config.ts +455 -0
  54. package/src/call-diagnostic/generated-types-temp/ClientEvent.ts +2395 -0
  55. package/src/call-diagnostic/generated-types-temp/Event.ts +7762 -0
  56. package/src/call-diagnostic/generated-types-temp/MediaQualityEvent.ts +2321 -0
  57. package/src/client-metrics-batcher.js +3 -4
  58. package/src/config.js +25 -5
  59. package/src/index.ts +39 -0
  60. package/src/metrics.js +44 -58
  61. package/src/metrics.types.ts +137 -0
  62. package/src/new-metrics.ts +223 -0
  63. package/test/unit/spec/batcher.js +26 -15
  64. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +243 -0
  65. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +474 -0
  66. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +820 -0
  67. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +336 -0
  68. package/test/unit/spec/client-metrics-batcher.js +26 -15
  69. package/test/unit/spec/metrics.js +85 -116
  70. package/test/unit/spec/new-metrics.ts +153 -0
  71. package/tsconfig.json +6 -0
  72. package/dist/call-diagnostic-events-batcher.js +0 -70
  73. package/dist/call-diagnostic-events-batcher.js.map +0 -1
  74. package/src/call-diagnostic-events-batcher.js +0 -62
  75. package/src/index.js +0 -17
  76. package/test/unit/spec/call-diagnostic-events-batcher.js +0 -180
@@ -0,0 +1,591 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ /* eslint-disable class-methods-use-this */
3
+ /* eslint-disable valid-jsdoc */
4
+ import {getOSNameInternal} from '@webex/internal-plugin-metrics';
5
+ import {BrowserDetection} from '@webex/common';
6
+ import uuid from 'uuid';
7
+ import {merge} from 'lodash';
8
+ import {StatelessWebexPlugin} from '@webex/webex-core';
9
+
10
+ import {
11
+ anonymizeIPAddress,
12
+ clearEmptyKeysRecursively,
13
+ isLocusServiceErrorCode,
14
+ prepareDiagnosticMetricItem,
15
+ userAgentToString,
16
+ } from './call-diagnostic-metrics.util';
17
+ import {CLIENT_NAME} from '../config';
18
+ import {
19
+ RecursivePartial,
20
+ Event,
21
+ ClientType,
22
+ SubClientType,
23
+ NetworkType,
24
+ ClientEvent,
25
+ SubmitClientEventOptions,
26
+ MediaQualityEvent,
27
+ SubmitMQEOptions,
28
+ SubmitMQEPayload,
29
+ ClientEventError,
30
+ ClientEventPayload,
31
+ } from '../metrics.types';
32
+ import CallDiagnosticEventsBatcher from './call-diagnostic-metrics-batcher';
33
+ import {
34
+ CLIENT_ERROR_CODE_TO_ERROR_PAYLOAD,
35
+ CALL_DIAGNOSTIC_EVENT_FAILED_TO_SEND,
36
+ MEETING_INFO_LOOKUP_ERROR_CLIENT_CODE,
37
+ NEW_LOCUS_ERROR_CLIENT_CODE,
38
+ SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP,
39
+ } from './config';
40
+
41
+ const {getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
42
+
43
+ type GetOriginOptions = {
44
+ clientType: ClientType;
45
+ subClientType: SubClientType;
46
+ networkType?: NetworkType;
47
+ };
48
+
49
+ type GetIdentifiersOptions = {
50
+ meeting?: any;
51
+ mediaConnections?: any[];
52
+ correlationId?: string;
53
+ };
54
+
55
+ /**
56
+ * @description Util class to handle Call Analyzer Metrics
57
+ * @export
58
+ * @class CallDiagnosticMetrics
59
+ */
60
+ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
61
+ // @ts-ignore
62
+ private callDiagnosticEventsBatcher: CallDiagnosticEventsBatcher;
63
+
64
+ /**
65
+ * Constructor
66
+ * @param args
67
+ */
68
+ constructor(...args) {
69
+ super(...args);
70
+ // @ts-ignore
71
+ this.callDiagnosticEventsBatcher = new CallDiagnosticEventsBatcher({}, {parent: this.webex});
72
+ }
73
+
74
+ /**
75
+ * Returns the login type of the current user
76
+ * @returns one of 'login-ci','unverified-guest', null
77
+ */
78
+ getCurLoginType() {
79
+ // @ts-ignore
80
+ if (this.webex.canAuthorize) {
81
+ // @ts-ignore
82
+ return this.webex.credentials.isUnverifiedGuest ? 'unverified-guest' : 'login-ci';
83
+ }
84
+
85
+ return null;
86
+ }
87
+
88
+ /**
89
+ * Get origin object for Call Diagnostic Event payload.
90
+ * @param options
91
+ * @param meetingId
92
+ * @returns
93
+ */
94
+ getOrigin(options: GetOriginOptions, meetingId?: string) {
95
+ const defaultClientType: ClientType =
96
+ // @ts-ignore
97
+ this.webex.meetings.config?.metrics?.clientType;
98
+ const defaultSubClientType: SubClientType =
99
+ // @ts-ignore
100
+ this.webex.meetings.config?.metrics?.subClientType;
101
+
102
+ if (
103
+ (defaultClientType && defaultSubClientType) ||
104
+ (options.clientType && options.subClientType)
105
+ ) {
106
+ const origin: Event['origin'] = {
107
+ name: 'endpoint',
108
+ networkType: options?.networkType || 'unknown',
109
+ userAgent: userAgentToString({
110
+ // @ts-ignore
111
+ clientName: this.webex.meetings?.metrics?.clientName,
112
+ // @ts-ignore
113
+ webexVersion: this.webex.version,
114
+ }),
115
+ clientInfo: {
116
+ clientType: options?.clientType || defaultClientType,
117
+ // @ts-ignore
118
+ clientVersion: `${CLIENT_NAME}/${this.webex.version}`,
119
+ localNetworkPrefix:
120
+ // @ts-ignore
121
+ anonymizeIPAddress(this.webex.meetings.geoHintInfo?.clientAddress) || undefined,
122
+ osVersion: getOSVersion() || 'unknown',
123
+ subClientType: options?.subClientType || defaultSubClientType,
124
+ os: getOSNameInternal(),
125
+ browser: getBrowserName(),
126
+ browserVersion: getBrowserVersion(),
127
+ },
128
+ };
129
+
130
+ if (meetingId) {
131
+ // @ts-ignore
132
+ const meeting = this.webex.meetings.meetingCollection.get(meetingId);
133
+ if (meeting?.environment) {
134
+ origin.environment = meeting.environment;
135
+ }
136
+ }
137
+
138
+ return origin;
139
+ }
140
+
141
+ throw new Error("ClientType and SubClientType can't be undefined");
142
+ }
143
+
144
+ /**
145
+ * Gather identifier details for call diagnostic payload.
146
+ * @throws Error if initialization fails.
147
+ * @param options
148
+ */
149
+ getIdentifiers(options: GetIdentifiersOptions) {
150
+ const {meeting, mediaConnections, correlationId} = options;
151
+ const identifiers: Event['event']['identifiers'] = {correlationId: 'unknown'};
152
+
153
+ if (meeting) {
154
+ identifiers.correlationId = meeting.correlationId;
155
+ }
156
+
157
+ if (correlationId) {
158
+ identifiers.correlationId = correlationId;
159
+ }
160
+ // @ts-ignore
161
+ if (this.webex.internal) {
162
+ // @ts-ignore
163
+ const {device} = this.webex.internal;
164
+ identifiers.userId = device.userId;
165
+ identifiers.deviceId = device.url;
166
+ identifiers.orgId = device.orgId;
167
+ // @ts-ignore
168
+ identifiers.locusUrl = this.webex.internal.services.get('locus');
169
+ }
170
+
171
+ if (meeting?.locusInfo?.fullState) {
172
+ identifiers.locusUrl = meeting.locusUrl;
173
+ identifiers.locusId = meeting.locusUrl && meeting.locusUrl.split('/').pop();
174
+ identifiers.locusStartTime =
175
+ meeting.locusInfo.fullState && meeting.locusInfo.fullState.lastActive;
176
+ }
177
+
178
+ if (mediaConnections) {
179
+ identifiers.mediaAgentAlias = mediaConnections?.[0]?.mediaAgentAlias;
180
+ identifiers.mediaAgentGroupId = mediaConnections?.[0]?.mediaAgentGroupId;
181
+ }
182
+
183
+ if (identifiers.correlationId === undefined) {
184
+ throw new Error('Identifiers initialization failed.');
185
+ }
186
+
187
+ return identifiers;
188
+ }
189
+
190
+ /**
191
+ * Create diagnostic event, which can hold client event, feature event or MQE event data.
192
+ * This just initiates the shared properties that are required for all the 3 event categories.
193
+ * @param eventData
194
+ * @param options
195
+ * @returns
196
+ */
197
+ prepareDiagnosticEvent(eventData: Event['event'], options: any) {
198
+ const {meetingId} = options;
199
+ const origin = this.getOrigin(options, meetingId);
200
+
201
+ const event: Event = {
202
+ eventId: uuid.v4(),
203
+ version: 1,
204
+ origin,
205
+ originTime: {
206
+ triggered: new Date().toISOString(),
207
+ // is overridden in prepareRequest batcher
208
+ sent: 'not_defined_yet',
209
+ },
210
+ // @ts-ignore
211
+ senderCountryCode: this.webex.meetings.geoHintInfo?.countryCode,
212
+ event: eventData,
213
+ };
214
+
215
+ // sanitize (remove empty properties, CA requires it)
216
+ // but we don't want to sanitize MQE as most of the times
217
+ // values will be 0, [] etc, and they are required.
218
+ if (eventData.name !== 'client.mediaquality.event') {
219
+ clearEmptyKeysRecursively(event);
220
+ }
221
+
222
+ return event;
223
+ }
224
+
225
+ /**
226
+ * TODO: NOT IMPLEMENTED
227
+ * Submit Feature Event
228
+ * @returns
229
+ */
230
+ public submitFeatureEvent() {
231
+ throw Error('Not implemented');
232
+ }
233
+
234
+ /**
235
+ * Submit Media Quality Event
236
+ * @param args - submit params
237
+ * @param arg.name - event key
238
+ * @param arg.payload - additional payload to be merge with the default payload
239
+ * @param arg.options - options
240
+ */
241
+ submitMQE({
242
+ name,
243
+ payload,
244
+ options,
245
+ }: {
246
+ name: MediaQualityEvent['name'];
247
+ payload: SubmitMQEPayload;
248
+ options: SubmitMQEOptions;
249
+ }) {
250
+ const {meetingId, mediaConnections} = options;
251
+
252
+ // events that will most likely happen in join phase
253
+ if (meetingId) {
254
+ // @ts-ignore
255
+ const meeting = this.webex.meetings.meetingCollection.get(meetingId);
256
+
257
+ if (!meeting) {
258
+ console.warn(
259
+ 'Attempt to send MQE but no meeting was found...',
260
+ `event: ${name}, meetingId: ${meetingId}`
261
+ );
262
+ // @ts-ignore
263
+ this.webex.internal.metrics.submitClientMetrics(CALL_DIAGNOSTIC_EVENT_FAILED_TO_SEND, {
264
+ fields: {
265
+ meetingId,
266
+ name,
267
+ },
268
+ });
269
+
270
+ return;
271
+ }
272
+
273
+ // merge identifiers
274
+ const identifiers = this.getIdentifiers({
275
+ meeting,
276
+ mediaConnections: meeting.mediaConnections || mediaConnections,
277
+ });
278
+
279
+ // create media quality event object
280
+ let clientEventObject: MediaQualityEvent['payload'] = {
281
+ name,
282
+ canProceed: true,
283
+ identifiers,
284
+ eventData: {
285
+ webClientDomain: window.location.hostname,
286
+ },
287
+ intervals: payload.intervals,
288
+ sourceMetadata: {
289
+ applicationSoftwareType: CLIENT_NAME,
290
+ // @ts-ignore
291
+ applicationSoftwareVersion: this.webex.version,
292
+ mediaEngineSoftwareType: getBrowserName() || 'browser',
293
+ mediaEngineSoftwareVersion: getOSVersion() || 'unknown',
294
+ startTime: new Date().toISOString(),
295
+ },
296
+ };
297
+
298
+ // merge any new properties, or override existing ones
299
+ clientEventObject = merge(clientEventObject, payload);
300
+
301
+ // append media quality event data to the call diagnostic event
302
+ const diagnosticEvent = this.prepareDiagnosticEvent(clientEventObject, options);
303
+ this.submitToCallDiagnostics(diagnosticEvent);
304
+ } else {
305
+ throw new Error(
306
+ 'Media quality events cant be sent outside the context of a meeting. Meeting id is required.'
307
+ );
308
+ }
309
+ }
310
+
311
+ /**
312
+ * Return Client Event payload by client error code
313
+ * @param arg - get error arg
314
+ * @param arg.clientErrorCode
315
+ * @param arg.serviceErrorCode
316
+ * @returns
317
+ */
318
+ public getErrorPayloadForClientErrorCode({
319
+ clientErrorCode,
320
+ serviceErrorCode,
321
+ }: {
322
+ clientErrorCode: number;
323
+ serviceErrorCode: any;
324
+ }): ClientEventError {
325
+ let error: ClientEventError;
326
+
327
+ if (clientErrorCode) {
328
+ const partialParsedError = CLIENT_ERROR_CODE_TO_ERROR_PAYLOAD[clientErrorCode];
329
+
330
+ if (partialParsedError) {
331
+ error = merge(
332
+ {fatal: true, shownToUser: false, name: 'other', category: 'other'}, // default values
333
+ {errorCode: clientErrorCode},
334
+ {serviceErrorCode},
335
+ partialParsedError
336
+ );
337
+
338
+ return error;
339
+ }
340
+ }
341
+
342
+ return undefined;
343
+ }
344
+
345
+ /**
346
+ * Generate error payload for Client Event
347
+ * @param rawError
348
+ */
349
+ generateClientEventErrorPayload(rawError: any) {
350
+ const serviceErrorCode = rawError?.body?.errorCode || rawError?.body?.code;
351
+ if (serviceErrorCode) {
352
+ const clientErrorCode = SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP[serviceErrorCode];
353
+ if (clientErrorCode) {
354
+ return this.getErrorPayloadForClientErrorCode({clientErrorCode, serviceErrorCode});
355
+ }
356
+
357
+ // by default, if it is locus error, return nre locus err
358
+ if (isLocusServiceErrorCode(serviceErrorCode)) {
359
+ return this.getErrorPayloadForClientErrorCode({
360
+ clientErrorCode: NEW_LOCUS_ERROR_CLIENT_CODE,
361
+ serviceErrorCode,
362
+ });
363
+ }
364
+
365
+ // otherwise return meeting info
366
+ return this.getErrorPayloadForClientErrorCode({
367
+ clientErrorCode: MEETING_INFO_LOOKUP_ERROR_CLIENT_CODE,
368
+ serviceErrorCode,
369
+ });
370
+ }
371
+
372
+ return undefined;
373
+ }
374
+
375
+ /**
376
+ * Create client event object for in meeting events
377
+ * @param arg - create args
378
+ * @param arg.event - event key
379
+ * @param arg.options - options
380
+ * @returns object
381
+ */
382
+ private createClientEventObjectInMeeting({
383
+ name,
384
+ options,
385
+ }: {
386
+ name: ClientEvent['name'];
387
+ options?: SubmitClientEventOptions;
388
+ }) {
389
+ const {meetingId, mediaConnections, rawError} = options;
390
+
391
+ // @ts-ignore
392
+ const meeting = this.webex.meetings.meetingCollection.get(meetingId);
393
+
394
+ if (!meeting) {
395
+ console.warn(
396
+ 'Attempt to send client event but no meeting was found...',
397
+ `event: ${name}, meetingId: ${meetingId}`
398
+ );
399
+ // @ts-ignore
400
+ this.webex.internal.metrics.submitClientMetrics(CALL_DIAGNOSTIC_EVENT_FAILED_TO_SEND, {
401
+ fields: {
402
+ meetingId,
403
+ name,
404
+ },
405
+ });
406
+
407
+ return undefined;
408
+ }
409
+
410
+ // grab identifiers
411
+ const identifiers = this.getIdentifiers({
412
+ meeting,
413
+ mediaConnections: meeting?.mediaConnections || mediaConnections,
414
+ });
415
+
416
+ // check if we need to generate errors
417
+ const errors: ClientEvent['payload']['errors'] = [];
418
+
419
+ if (rawError) {
420
+ const generatedError = this.generateClientEventErrorPayload(rawError);
421
+ if (generatedError) {
422
+ errors.push(generatedError);
423
+ }
424
+ }
425
+
426
+ // create client event object
427
+ const clientEventObject: ClientEvent['payload'] = {
428
+ name,
429
+ canProceed: true,
430
+ identifiers,
431
+ errors,
432
+ eventData: {
433
+ webClientDomain: window.location.hostname,
434
+ },
435
+ userType: meeting.getCurUserType(),
436
+ loginType: this.getCurLoginType(),
437
+ };
438
+
439
+ return clientEventObject;
440
+ }
441
+
442
+ /**
443
+ * Create client event object for pre meeting events
444
+ * @param arg - create args
445
+ * @param arg.event - event key
446
+ * @param arg.options - payload
447
+ * @returns object
448
+ */
449
+ private createClientEventObjectPreMeeting({
450
+ name,
451
+ options,
452
+ }: {
453
+ name: ClientEvent['name'];
454
+ options?: SubmitClientEventOptions;
455
+ }) {
456
+ const {correlationId} = options;
457
+
458
+ // grab identifiers
459
+ const identifiers = this.getIdentifiers({
460
+ correlationId,
461
+ });
462
+
463
+ // create client event object
464
+ const clientEventObject: ClientEvent['payload'] = {
465
+ name,
466
+ canProceed: true,
467
+ identifiers,
468
+ eventData: {
469
+ webClientDomain: window.location.hostname,
470
+ },
471
+ loginType: this.getCurLoginType(),
472
+ };
473
+
474
+ return clientEventObject;
475
+ }
476
+
477
+ /**
478
+ * Prepare Client Event CA event.
479
+ * @param arg - submit params
480
+ * @param arg.event - event key
481
+ * @param arg.payload - additional payload to be merged with default payload
482
+ * @param arg.options - payload
483
+ * @returns {any} options to be with fetch
484
+ * @throws
485
+ */
486
+ private prepareClientEvent({
487
+ name,
488
+ payload,
489
+ options,
490
+ }: {
491
+ name: ClientEvent['name'];
492
+ payload?: ClientEventPayload;
493
+ options?: SubmitClientEventOptions;
494
+ }) {
495
+ const {meetingId, correlationId} = options;
496
+ let clientEventObject: ClientEvent['payload'];
497
+
498
+ // events that will most likely happen in join phase
499
+ if (meetingId) {
500
+ clientEventObject = this.createClientEventObjectInMeeting({name, options});
501
+ } else if (correlationId) {
502
+ // any pre join events or events that are outside the meeting.
503
+ clientEventObject = this.createClientEventObjectPreMeeting({name, options});
504
+ } else {
505
+ throw new Error('Not implemented');
506
+ }
507
+
508
+ // merge any new properties, or override existing ones
509
+ clientEventObject = merge(clientEventObject, payload);
510
+
511
+ // append client event data to the call diagnostic event
512
+ const diagnosticEvent = this.prepareDiagnosticEvent(clientEventObject, options);
513
+
514
+ return diagnosticEvent;
515
+ }
516
+
517
+ /**
518
+ * Submit Client Event CA event.
519
+ * @param arg - submit params
520
+ * @param arg.event - event key
521
+ * @param arg.payload - additional payload to be merged with default payload
522
+ * @param arg.options - payload
523
+ * @throws
524
+ */
525
+ public submitClientEvent({
526
+ name,
527
+ payload,
528
+ options,
529
+ }: {
530
+ name: ClientEvent['name'];
531
+ payload?: ClientEventPayload;
532
+ options?: SubmitClientEventOptions;
533
+ }) {
534
+ const diagnosticEvent = this.prepareClientEvent({name, payload, options});
535
+
536
+ return this.submitToCallDiagnostics(diagnosticEvent);
537
+ }
538
+
539
+ /**
540
+ * Prepare the event and send the request to metrics-a service.
541
+ * @param event
542
+ * @returns promise
543
+ */
544
+ submitToCallDiagnostics(event: Event): Promise<any> {
545
+ // build metrics-a event type
546
+ const finalEvent = {
547
+ eventPayload: event,
548
+ type: ['diagnostic-event'],
549
+ };
550
+
551
+ return this.callDiagnosticEventsBatcher.request(finalEvent);
552
+ }
553
+
554
+ /**
555
+ * Builds a request options object to later be passed to fetch().
556
+ * @param arg - submit params
557
+ * @param arg.event - event key
558
+ * @param arg.payload - additional payload to be merged with default payload
559
+ * @param arg.options - client event options
560
+ * @returns {Promise<any>}
561
+ * @throws
562
+ */
563
+ public async buildClientEventFetchRequestOptions({
564
+ name,
565
+ payload,
566
+ options,
567
+ }: {
568
+ name: ClientEvent['name'];
569
+ payload?: ClientEventPayload;
570
+ options?: SubmitClientEventOptions;
571
+ }): Promise<any> {
572
+ const clientEvent = this.prepareClientEvent({name, payload, options});
573
+
574
+ // build metrics-a event type
575
+ // @ts-ignore
576
+ const diagnosticEvent = prepareDiagnosticMetricItem(this.webex, {
577
+ eventPayload: clientEvent,
578
+ type: ['diagnostic-event'],
579
+ });
580
+
581
+ // @ts-ignore
582
+ return this.webex.prepareFetchOptions({
583
+ method: 'POST',
584
+ service: 'metrics',
585
+ resource: 'clientmetrics',
586
+ body: {
587
+ metrics: [diagnosticEvent],
588
+ },
589
+ });
590
+ }
591
+ }