@webex/internal-plugin-metrics 3.4.0 → 3.5.0-next.10

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 (69) hide show
  1. package/dist/behavioral-metrics.js +63 -0
  2. package/dist/behavioral-metrics.js.map +1 -0
  3. package/dist/business-metrics.js +169 -0
  4. package/dist/business-metrics.js.map +1 -0
  5. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +1 -1
  6. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
  7. package/dist/call-diagnostic/call-diagnostic-metrics.js +27 -11
  8. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
  9. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +14 -4
  10. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
  11. package/dist/call-diagnostic/config.js +13 -3
  12. package/dist/call-diagnostic/config.js.map +1 -1
  13. package/dist/{behavioral/behavioral-metrics.js → generic-metrics.js} +77 -92
  14. package/dist/generic-metrics.js.map +1 -0
  15. package/dist/index.js +22 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/metrics.js +1 -1
  18. package/dist/metrics.types.js.map +1 -1
  19. package/dist/new-metrics.js +124 -24
  20. package/dist/new-metrics.js.map +1 -1
  21. package/dist/operational-metrics.js +56 -0
  22. package/dist/operational-metrics.js.map +1 -0
  23. package/dist/rtcMetrics/constants.js +11 -0
  24. package/dist/rtcMetrics/constants.js.map +1 -0
  25. package/dist/rtcMetrics/index.js +202 -0
  26. package/dist/rtcMetrics/index.js.map +1 -0
  27. package/dist/types/behavioral-metrics.d.ts +25 -0
  28. package/dist/types/business-metrics.d.ts +47 -0
  29. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +27 -6
  30. package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +2 -1
  31. package/dist/types/call-diagnostic/config.d.ts +3 -0
  32. package/dist/types/generic-metrics.d.ts +63 -0
  33. package/dist/types/index.d.ts +5 -2
  34. package/dist/types/metrics.types.d.ts +27 -14
  35. package/dist/types/new-metrics.d.ts +42 -9
  36. package/dist/types/operational-metrics.d.ts +19 -0
  37. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  38. package/dist/types/rtcMetrics/index.d.ts +71 -0
  39. package/package.json +12 -12
  40. package/src/behavioral-metrics.ts +40 -0
  41. package/src/business-metrics.ts +118 -0
  42. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +1 -1
  43. package/src/call-diagnostic/call-diagnostic-metrics.ts +30 -9
  44. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +17 -4
  45. package/src/call-diagnostic/config.ts +12 -0
  46. package/src/generic-metrics.ts +146 -0
  47. package/src/index.ts +7 -1
  48. package/src/metrics.types.ts +32 -16
  49. package/src/new-metrics.ts +100 -13
  50. package/src/operational-metrics.ts +24 -0
  51. package/src/rtcMetrics/constants.ts +3 -0
  52. package/src/rtcMetrics/index.ts +186 -0
  53. package/test/unit/spec/behavioral/behavioral-metrics.ts +51 -10
  54. package/test/unit/spec/business/business-metrics.ts +182 -0
  55. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +2 -1
  56. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +4 -6
  57. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +418 -12
  58. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +22 -8
  59. package/test/unit/spec/new-metrics.ts +32 -3
  60. package/test/unit/spec/operational/operational-metrics.ts +115 -0
  61. package/test/unit/spec/prelogin-metrics-batcher.ts +3 -1
  62. package/test/unit/spec/rtcMetrics/index.ts +155 -0
  63. package/dist/behavioral/behavioral-metrics.js.map +0 -1
  64. package/dist/behavioral/config.js +0 -11
  65. package/dist/behavioral/config.js.map +0 -1
  66. package/dist/types/behavioral/behavioral-metrics.d.ts +0 -63
  67. package/dist/types/behavioral/config.d.ts +0 -1
  68. package/src/behavioral/behavioral-metrics.ts +0 -179
  69. package/src/behavioral/config.ts +0 -3
@@ -0,0 +1,40 @@
1
+ import {MetricEventProduct, MetricEventAgent, MetricEventVerb, EventPayload} from './metrics.types';
2
+ import GenericMetrics from './generic-metrics';
3
+
4
+ /**
5
+ * @description Util class to handle Behavioral Metrics
6
+ * @export
7
+ * @class BehavioralMetrics
8
+ */
9
+ export default class BehavioralMetrics extends GenericMetrics {
10
+ /**
11
+ * Submit a behavioral metric to our metrics endpoint.
12
+ * @param {MetricEventProduct} product the product from which the metric is being submitted, e.g. 'webex' web client, 'wxcc_desktop'
13
+ * @param {MetricEventAgent} agent the source of the action for this metric
14
+ * @param {string} target the 'thing' that this metric includes information about
15
+ * @param {MetricEventVerb} verb the action that this metric includes information about
16
+ * @param {EventPayload} payload information specific to this event. This should be flat, i.e. it should not include nested objects.
17
+ * @returns {Promise<any>}
18
+ */
19
+ public submitBehavioralEvent({
20
+ product,
21
+ agent,
22
+ target,
23
+ verb,
24
+ payload,
25
+ }: {
26
+ product: MetricEventProduct;
27
+ agent: MetricEventAgent;
28
+ target: string;
29
+ verb: MetricEventVerb;
30
+ payload?: EventPayload;
31
+ }) {
32
+ const name = `${product}.${agent}.${target}.${verb}`;
33
+ const event = this.createTaggedEventObject({
34
+ type: ['behavioral'],
35
+ name,
36
+ payload,
37
+ });
38
+ this.submitEvent({kind: 'behavioral-events -> ', name, event});
39
+ }
40
+ }
@@ -0,0 +1,118 @@
1
+ import GenericMetrics from './generic-metrics';
2
+ import {EventPayload, Table} from './metrics.types';
3
+
4
+ /**
5
+ * @description Util class to handle Buisness Metrics
6
+ * @export
7
+ * @class BusinessMetrics
8
+ */
9
+ export default class BusinessMetrics extends GenericMetrics {
10
+ /**
11
+ * unfortunately, the pinot team does not allow changes to the schema of wbxapp_callend_metrics
12
+ * so we have to shim this layer specifically for this
13
+ * @param {EventPayload} payload payload of the metric
14
+ * @returns {Promise<any>}
15
+ */
16
+ private submitCallEndEvent({payload}: {payload: EventPayload}) {
17
+ const event = {
18
+ type: ['business'],
19
+ eventPayload: {
20
+ key: 'callEnd',
21
+ client_timestamp: Date.now(),
22
+ appType: 'Web Client',
23
+ value: {
24
+ ...payload,
25
+ },
26
+ },
27
+ };
28
+
29
+ return this.submitEvent({
30
+ kind: 'buisness-events:wbxapp_callend_metrics -> ',
31
+ name: 'wbxapp_callend_metrics',
32
+ event,
33
+ });
34
+ }
35
+
36
+ /**
37
+ * Submit a buisness metric to our metrics endpoint, going to the default business_ucf table
38
+ * all event payload keys are converted into a hex string value
39
+ * unfortunately, the pinot team does not allow changes to the schema of business_metrics
40
+ * so we have to shim this layer specifically for this
41
+ * @param {string} name of the metric
42
+ * @param {EventPayload} payload payload of the metric
43
+ * @returns {Promise<any>}
44
+ */
45
+ private submitBusinessMetricsEvent({name, payload}: {name: string; payload: EventPayload}) {
46
+ const event = {
47
+ type: ['business'],
48
+ eventPayload: {
49
+ key: name,
50
+ client_timestamp: Date.now(),
51
+ appType: 'Web Client',
52
+ value: {
53
+ ...this.getContext(),
54
+ ...this.getBrowserDetails(),
55
+ ...payload,
56
+ },
57
+ },
58
+ };
59
+
60
+ return this.submitEvent({kind: 'buisness-events:business_metrics -> ', name, event});
61
+ }
62
+
63
+ /**
64
+ * Submit a buisness metric to our metrics endpoint, going to the default business_ucf table
65
+ * all event payload keys are converted into a hex string value
66
+ * @param {string} name of the metric
67
+ * @param {EventPayload} user payload of the metric
68
+ * @returns {Promise<any>}
69
+ */
70
+ private submitDefaultEvent({name, payload}: {name: string; payload: EventPayload}) {
71
+ const event = {
72
+ type: ['business'],
73
+ eventPayload: {
74
+ key: name,
75
+ appType: 'Web Client',
76
+ client_timestamp: Date.now(),
77
+ context: this.getContext(),
78
+ browserDetails: this.getBrowserDetails(),
79
+ value: payload,
80
+ },
81
+ };
82
+
83
+ return this.submitEvent({kind: 'buisness-events:default -> ', name, event});
84
+ }
85
+
86
+ /**
87
+ * Submit a buisness metric to our metrics endpoint.
88
+ * routes to the correct table with the correct schema payload by table
89
+ * @param {string} name of the metric, ignored if going to wbxapp_callend_metrics
90
+ * @param {EventPayload} payload user payload of the metric
91
+ * @param {Table} table optional - to submit the metric to and adapt the sent schema
92
+ * @returns {Promise<any>}
93
+ */
94
+ public submitBusinessEvent({
95
+ name,
96
+ payload,
97
+ table,
98
+ }: {
99
+ name: string;
100
+ payload: EventPayload;
101
+ table?: Table;
102
+ }): Promise<void> {
103
+ if (!table) {
104
+ table = 'default';
105
+ }
106
+ switch (table) {
107
+ case 'wbxapp_callend_metrics':
108
+ return this.submitCallEndEvent({payload});
109
+ case 'business_metrics':
110
+ return this.submitBusinessMetricsEvent({name, payload});
111
+ case 'business_ucf':
112
+ return this.submitDefaultEvent({name, payload});
113
+ case 'default':
114
+ default:
115
+ return this.submitDefaultEvent({name, payload});
116
+ }
117
+ }
118
+ }
@@ -49,7 +49,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
49
49
  private getMeeting() {
50
50
  if (this.meetingId) {
51
51
  // @ts-ignore
52
- return this.webex.meetings.meetingCollection.get(this.meetingId);
52
+ return this.webex.meetings.getBasicMeetingInformation(this.meetingId);
53
53
  }
54
54
 
55
55
  return undefined;
@@ -75,6 +75,7 @@ type GetIdentifiersOptions = {
75
75
  meeting?: any;
76
76
  mediaConnections?: any[];
77
77
  correlationId?: string;
78
+ sessionCorrelationId?: string;
78
79
  preLoginId?: string;
79
80
  globalMeetingId?: string;
80
81
  webexConferenceIdStr?: string;
@@ -138,7 +139,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
138
139
  getIsConvergedArchitectureEnabled({meetingId}: {meetingId?: string}): boolean {
139
140
  if (meetingId) {
140
141
  // @ts-ignore
141
- const meeting = this.webex.meetings.meetingCollection.get(meetingId);
142
+ const meeting = this.webex.meetings.getBasicMeetingInformation(meetingId);
142
143
 
143
144
  return meeting?.meetingInfo?.enableConvergedArchitecture;
144
145
  }
@@ -244,7 +245,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
244
245
 
245
246
  if (meetingId) {
246
247
  // @ts-ignore
247
- const meeting = this.webex.meetings.meetingCollection.get(meetingId);
248
+ const meeting = this.webex.meetings.getBasicMeetingInformation(meetingId);
248
249
  if (meeting?.environment) {
249
250
  origin.environment = meeting.environment;
250
251
  }
@@ -285,19 +286,29 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
285
286
  webexConferenceIdStr,
286
287
  globalMeetingId,
287
288
  preLoginId,
289
+ sessionCorrelationId,
288
290
  } = options;
289
291
  const identifiers: Event['event']['identifiers'] = {
290
- correlationId: 'unknown',
292
+ correlationId: 'unknown', // concerned with setting this to unknown. This will fail diagnostic events parsing because it's not a uuid pattern
291
293
  };
292
294
 
293
295
  if (meeting) {
294
296
  identifiers.correlationId = meeting.correlationId;
297
+ if (meeting.sessionCorrelationId) {
298
+ identifiers.sessionCorrelationId = meeting.sessionCorrelationId;
299
+ }
300
+ }
301
+
302
+ if (sessionCorrelationId) {
303
+ identifiers.sessionCorrelationId = sessionCorrelationId;
295
304
  }
296
305
 
297
306
  if (correlationId) {
298
307
  identifiers.correlationId = correlationId;
299
308
  }
300
309
 
310
+ // TODO: should we use patterns.uuid to validate correlationId and session correlation id? they will fail the diagnostic events validation pipeline if improperly formatted
311
+
301
312
  if (this.device) {
302
313
  const {device} = this;
303
314
  const {installationId} = device?.config || {};
@@ -419,7 +430,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
419
430
  // events that will most likely happen in join phase
420
431
  if (meetingId) {
421
432
  // @ts-ignore
422
- const meeting = this.webex.meetings.meetingCollection.get(meetingId);
433
+ const meeting = this.webex.meetings.getBasicMeetingInformation(meetingId);
423
434
 
424
435
  if (!meeting) {
425
436
  console.warn(
@@ -620,10 +631,11 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
620
631
  });
621
632
  }
622
633
 
623
- // otherwise return unkown error
634
+ // otherwise return unkown error but passing serviceErrorCode and serviceErrorName so that we know the issue
624
635
  return this.getErrorPayloadForClientErrorCode({
625
636
  clientErrorCode: UNKNOWN_ERROR,
626
- serviceErrorCode: UNKNOWN_ERROR,
637
+ serviceErrorCode: serviceErrorCode || UNKNOWN_ERROR,
638
+ serviceErrorName: rawError?.name,
627
639
  payloadOverrides: rawError.payloadOverrides,
628
640
  rawErrorMessage,
629
641
  httpStatusCode,
@@ -646,10 +658,16 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
646
658
  options?: SubmitClientEventOptions;
647
659
  errors?: ClientEventPayloadError;
648
660
  }) {
649
- const {meetingId, mediaConnections, globalMeetingId, webexConferenceIdStr} = options;
661
+ const {
662
+ meetingId,
663
+ mediaConnections,
664
+ globalMeetingId,
665
+ webexConferenceIdStr,
666
+ sessionCorrelationId,
667
+ } = options;
650
668
 
651
669
  // @ts-ignore
652
- const meeting = this.webex.meetings.meetingCollection.get(meetingId);
670
+ const meeting = this.webex.meetings.getBasicMeetingInformation(meetingId);
653
671
 
654
672
  if (!meeting) {
655
673
  console.warn(
@@ -673,6 +691,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
673
691
  mediaConnections: meeting?.mediaConnections || mediaConnections,
674
692
  webexConferenceIdStr,
675
693
  globalMeetingId,
694
+ sessionCorrelationId,
676
695
  });
677
696
 
678
697
  // create client event object
@@ -714,11 +733,13 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
714
733
  options?: SubmitClientEventOptions;
715
734
  errors?: ClientEventPayloadError;
716
735
  }) {
717
- const {correlationId, globalMeetingId, webexConferenceIdStr, preLoginId} = options;
736
+ const {correlationId, globalMeetingId, webexConferenceIdStr, preLoginId, sessionCorrelationId} =
737
+ options;
718
738
 
719
739
  // grab identifiers
720
740
  const identifiers = this.getIdentifiers({
721
741
  correlationId,
742
+ sessionCorrelationId,
722
743
  preLoginId,
723
744
  globalMeetingId,
724
745
  webexConferenceIdStr,
@@ -195,10 +195,12 @@ export const isBrowserMediaErrorName = (errorName: any) => {
195
195
  };
196
196
 
197
197
  /**
198
+ * @param {Object} webex sdk instance
198
199
  * @param webClientDomain
199
200
  * @returns
200
201
  */
201
202
  export const getBuildType = (
203
+ webex,
202
204
  webClientDomain,
203
205
  markAsTestEvent = false
204
206
  ): Event['origin']['buildType'] => {
@@ -207,6 +209,10 @@ export const getBuildType = (
207
209
  return 'test';
208
210
  }
209
211
 
212
+ if (webex.internal.metrics?.config?.caBuildType) {
213
+ return webex.internal.metrics.config.caBuildType;
214
+ }
215
+
210
216
  if (
211
217
  webClientDomain?.includes('localhost') ||
212
218
  webClientDomain?.includes('127.0.0.1') ||
@@ -225,12 +231,19 @@ export const getBuildType = (
225
231
  * @returns {Object} prepared item
226
232
  */
227
233
  export const prepareDiagnosticMetricItem = (webex: any, item: any) => {
234
+ const buildType = getBuildType(
235
+ webex,
236
+ item.eventPayload?.event?.eventData?.webClientDomain,
237
+ item.eventPayload?.event?.eventData?.markAsTestEvent
238
+ );
239
+
240
+ // Set upgradeChannel to 'gold' if buildType is 'prod', otherwise to the buildType value
241
+ const upgradeChannel = buildType === 'prod' ? 'gold' : buildType;
242
+
228
243
  const origin: Partial<Event['origin']> = {
229
- buildType: getBuildType(
230
- item.eventPayload?.event?.eventData?.webClientDomain,
231
- item.eventPayload?.event?.eventData?.markAsTestEvent
232
- ),
244
+ buildType,
233
245
  networkType: 'unknown',
246
+ upgradeChannel,
234
247
  };
235
248
 
236
249
  // check event names and append latencies?
@@ -129,6 +129,7 @@ export const ERROR_DESCRIPTIONS = {
129
129
  ICE_AND_REACHABILITY_FAILED: 'ICEAndReachabilityFailed',
130
130
  SDP_OFFER_CREATION_ERROR: 'SdpOfferCreationError',
131
131
  SDP_OFFER_CREATION_ERROR_MISSING_CODEC: 'SdpOfferCreationErrorMissingCodec',
132
+ WDM_RESTRICTED_REGION: 'WdmRestrictedRegion',
132
133
  };
133
134
 
134
135
  export const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP = {
@@ -288,6 +289,12 @@ export const SERVICE_ERROR_CODES_TO_CLIENT_ERROR_CODES_MAP = {
288
289
  100005: 4103, // Depracated because of an issue in the UCF Clients
289
290
  // If both email-hash and domain-hash are null or undefined.
290
291
  100004: 4103,
292
+
293
+ // ---- WDM ----
294
+ // WDM_BLOCKED_ACCESS_BY_COUNTRY_CODE_BANNED_COUNTRY_ERROR_CODE
295
+ 4404002: 13000,
296
+ // WDM_BLOCKED_ACCESS_BY_COUNTRY_CODE_RESTRICTED_COUNTRY_ERROR_CODE
297
+ 4404003: 13000,
291
298
  };
292
299
 
293
300
  export const CLIENT_ERROR_CODE_TO_ERROR_PAYLOAD: Record<number, Partial<ClientEventError>> = {
@@ -687,6 +694,11 @@ export const CLIENT_ERROR_CODE_TO_ERROR_PAYLOAD: Record<number, Partial<ClientEv
687
694
  category: 'expected',
688
695
  fatal: true,
689
696
  },
697
+ 13000: {
698
+ errorDescription: ERROR_DESCRIPTIONS.WDM_RESTRICTED_REGION,
699
+ category: 'expected',
700
+ fatal: true,
701
+ },
690
702
  };
691
703
 
692
704
  export const CALL_DIAGNOSTIC_EVENT_FAILED_TO_SEND = 'js_sdk_call_diagnostic_event_failed_to_send';
@@ -0,0 +1,146 @@
1
+ import {StatelessWebexPlugin} from '@webex/webex-core';
2
+ import {BrowserDetection} from '@webex/common';
3
+ import {merge} from 'lodash';
4
+ import ClientMetricsBatcher from './client-metrics-batcher';
5
+ import {getOSNameInternal} from './metrics';
6
+ import {DeviceContext, TaggedEvent, EventPayload, MetricType} from './metrics.types';
7
+
8
+ const {getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
9
+
10
+ /**
11
+ * @description top-level abstract class to handle Metrics and common routines.
12
+ * @export
13
+ * @class GenericMetrics
14
+ */
15
+ export default abstract class GenericMetrics extends StatelessWebexPlugin {
16
+ // @ts-ignore
17
+ private clientMetricsBatcher: ClientMetricsBatcher;
18
+ private logger: any; // to avoid adding @ts-ignore everywhere
19
+ private device: any;
20
+ private version: string;
21
+ private deviceId = '';
22
+
23
+ /**
24
+ * Constructor
25
+ * @param {any[]} args
26
+ */
27
+ constructor(...args) {
28
+ super(...args);
29
+ // @ts-ignore
30
+ this.logger = this.webex.logger;
31
+ // @ts-ignore
32
+ this.clientMetricsBatcher = new ClientMetricsBatcher({}, {parent: this.webex});
33
+ // @ts-ignore
34
+ this.device = this.webex.internal.device;
35
+ // @ts-ignore
36
+ this.version = this.webex.version;
37
+ }
38
+
39
+ /**
40
+ * Submit a buisness metric to our metrics endpoint.
41
+ * @param {string} kind of metric for logging
42
+ * @param {string} name of the metric
43
+ * @param {object} event
44
+ * @returns {Promise<any>}
45
+ */
46
+ protected submitEvent({kind, name, event}: {kind: string; name: string; event: object}) {
47
+ this.logger.log(kind, `@submitEvent. Submit event: ${name}`);
48
+
49
+ return this.clientMetricsBatcher.request(event);
50
+ }
51
+
52
+ /**
53
+ * Returns the deviceId from our registration with WDM.
54
+ * @returns {string} deviceId or empty string
55
+ */
56
+ protected getDeviceId(): string {
57
+ if (this.deviceId === '') {
58
+ const {url} = this.device;
59
+ if (url && url.length !== 0) {
60
+ const n = url.lastIndexOf('/');
61
+ if (n !== -1) {
62
+ this.deviceId = url.substring(n + 1);
63
+ }
64
+ }
65
+ }
66
+
67
+ return this.deviceId;
68
+ }
69
+
70
+ /**
71
+ * Returns the context object to be submitted with all metrics.
72
+ * @returns {DeviceContext}
73
+ */
74
+ protected getContext(): DeviceContext {
75
+ return {
76
+ app: {
77
+ version: this.version,
78
+ },
79
+ device: {
80
+ id: this.getDeviceId(),
81
+ },
82
+ locale: window.navigator.language,
83
+ os: {
84
+ name: getOSNameInternal(),
85
+ version: getOSVersion(),
86
+ },
87
+ };
88
+ }
89
+
90
+ /**
91
+ * Returns the browser details to be included with all metrics.
92
+ * @returns {object}
93
+ */
94
+ protected getBrowserDetails(): object {
95
+ return {
96
+ browser: getBrowserName(),
97
+ browserHeight: window.innerHeight,
98
+ browserVersion: getBrowserVersion(),
99
+ browserWidth: window.innerWidth,
100
+ domain: window.location.hostname,
101
+ inIframe: window.self !== window.top,
102
+ locale: window.navigator.language,
103
+ os: getOSNameInternal(),
104
+ };
105
+ }
106
+
107
+ /**
108
+ * Returns true once we have the deviceId we need to submit behavioral/operational/buisness events
109
+ * @returns {boolean}
110
+ */
111
+ public isReadyToSubmitEvents(): boolean {
112
+ const deviceId = this.getDeviceId();
113
+
114
+ return deviceId && deviceId.length !== 0;
115
+ }
116
+
117
+ /**
118
+ * Creates the object to send to our metrics endpoint for a tagged event (i.e. behavoral or operational)
119
+ * @param {[MetricType]} list of event type (i.e. ['behavioral'], ['operational', 'behavioral'])
120
+ * @param {string} metric name
121
+ * @param {EventPayload} user payload
122
+ * @returns {EventPayload}
123
+ */
124
+ protected createTaggedEventObject({
125
+ type,
126
+ name,
127
+ payload,
128
+ }: {
129
+ type: [MetricType];
130
+ name: string;
131
+ payload: EventPayload;
132
+ }): TaggedEvent {
133
+ let allTags: EventPayload = payload;
134
+ allTags = merge(allTags, this.getBrowserDetails());
135
+
136
+ const event = {
137
+ context: this.getContext(),
138
+ metricName: name,
139
+ tags: allTags,
140
+ timestamp: Date.now(),
141
+ type,
142
+ };
143
+
144
+ return event;
145
+ }
146
+ }
package/src/index.ts CHANGED
@@ -22,7 +22,10 @@ import * as CALL_DIAGNOSTIC_CONFIG from './call-diagnostic/config';
22
22
  import * as CallDiagnosticUtils from './call-diagnostic/call-diagnostic-metrics.util';
23
23
  import CallDiagnosticMetrics from './call-diagnostic/call-diagnostic-metrics';
24
24
  import CallDiagnosticLatencies from './call-diagnostic/call-diagnostic-metrics-latencies';
25
- import BehavioralMetrics from './behavioral/behavioral-metrics';
25
+ import BehavioralMetrics from './behavioral-metrics';
26
+ import OperationalMetrics from './operational-metrics';
27
+ import BusinessMetrics from './business-metrics';
28
+ import RtcMetrics from './rtcMetrics';
26
29
 
27
30
  registerInternalPlugin('metrics', Metrics, {
28
31
  config,
@@ -43,6 +46,9 @@ export {
43
46
  CallDiagnosticLatencies,
44
47
  CallDiagnosticMetrics,
45
48
  BehavioralMetrics,
49
+ OperationalMetrics,
50
+ BusinessMetrics,
51
+ RtcMetrics,
46
52
  };
47
53
  export type {
48
54
  ClientEvent,
@@ -61,6 +61,7 @@ export type SubmitClientEventOptions = {
61
61
  mediaConnections?: any[];
62
62
  rawError?: any;
63
63
  correlationId?: string;
64
+ sessionCorrelationId?: string;
64
65
  preLoginId?: string;
65
66
  environment?: EnvironmentType;
66
67
  newEnvironmentType?: NewEnvironmentType;
@@ -102,7 +103,7 @@ export interface ClientEvent {
102
103
  options?: SubmitClientEventOptions;
103
104
  }
104
105
 
105
- export interface BehavioralEventContext {
106
+ export interface DeviceContext {
106
107
  app: {version: string};
107
108
  device: {id: string};
108
109
  locale: string;
@@ -112,23 +113,38 @@ export interface BehavioralEventContext {
112
113
  };
113
114
  }
114
115
 
115
- export interface BehavioralEvent {
116
- context: BehavioralEventContext;
116
+ export type MetricType = 'behavioral' | 'operational' | 'business';
117
+
118
+ export type Table = 'wbxapp_callend_metrics' | 'business_metrics' | 'business_ucf' | 'default';
119
+
120
+ type InternalEventPayload = string | number | boolean;
121
+ export type EventPayload = Record<string, InternalEventPayload>;
122
+ export type BehavioralEventPayload = EventPayload; // for compatibilty, can be remove after wxcc-desktop did change their imports.
123
+
124
+ export interface BusinessEventPayload {
117
125
  metricName: string;
118
- tags: Record<string, string | number | boolean>;
119
126
  timestamp: number;
120
- type: string[];
127
+ context: DeviceContext;
128
+ browserDetails: EventPayload;
129
+ value: EventPayload;
121
130
  }
122
131
 
123
- export type BehavioralEventPayload = BehavioralEvent['tags'];
132
+ export interface BusinessEvent {
133
+ type: string[];
134
+ eventPayload: BusinessEventPayload;
135
+ }
124
136
 
125
- export interface OperationalEvent {
126
- // TODO: not implemented
127
- name: never;
128
- payload?: never;
129
- options?: never;
137
+ export interface TaggedEvent {
138
+ context: DeviceContext;
139
+ metricName: string;
140
+ tags: EventPayload;
141
+ timestamp: number;
142
+ type: [MetricType];
130
143
  }
131
144
 
145
+ export type BehavioralEvent = TaggedEvent;
146
+ export type OperationalEvent = TaggedEvent;
147
+
132
148
  export interface FeatureEvent {
133
149
  // TODO: not implemented
134
150
  name: never;
@@ -154,7 +170,8 @@ export type MetricEventNames =
154
170
  | InternalEvent['name']
155
171
  | ClientEvent['name']
156
172
  | BehavioralEvent['metricName']
157
- | OperationalEvent['name']
173
+ | OperationalEvent['metricName']
174
+ | BusinessEvent['eventPayload']['metricName']
158
175
  | FeatureEvent['name']
159
176
  | MediaQualityEvent['name'];
160
177
 
@@ -190,7 +207,7 @@ export type SubmitBehavioralEvent = (args: {
190
207
  agent: MetricEventAgent;
191
208
  target: string;
192
209
  verb: MetricEventVerb;
193
- payload?: BehavioralEventPayload;
210
+ payload?: EventPayload;
194
211
  }) => void;
195
212
 
196
213
  export type SubmitClientEvent = (args: {
@@ -200,9 +217,8 @@ export type SubmitClientEvent = (args: {
200
217
  }) => Promise<any>;
201
218
 
202
219
  export type SubmitOperationalEvent = (args: {
203
- name: OperationalEvent['name'];
204
- payload?: RecursivePartial<OperationalEvent['payload']>;
205
- options?: any;
220
+ name: OperationalEvent['metricName'];
221
+ payload: EventPayload;
206
222
  }) => void;
207
223
 
208
224
  export type SubmitMQE = (args: {