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

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 (52) 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 +62 -0
  4. package/dist/business-metrics.js.map +1 -0
  5. package/dist/call-diagnostic/call-diagnostic-metrics.js +15 -5
  6. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
  7. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +14 -4
  8. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
  9. package/dist/{behavioral/behavioral-metrics.js → generic-metrics.js} +77 -92
  10. package/dist/generic-metrics.js.map +1 -0
  11. package/dist/index.js +15 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/metrics.js +1 -1
  14. package/dist/metrics.types.js.map +1 -1
  15. package/dist/new-metrics.js +122 -24
  16. package/dist/new-metrics.js.map +1 -1
  17. package/dist/operational-metrics.js +56 -0
  18. package/dist/operational-metrics.js.map +1 -0
  19. package/dist/types/behavioral-metrics.d.ts +25 -0
  20. package/dist/types/business-metrics.d.ts +19 -0
  21. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +21 -5
  22. package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +2 -1
  23. package/dist/types/generic-metrics.d.ts +63 -0
  24. package/dist/types/index.d.ts +4 -2
  25. package/dist/types/metrics.types.d.ts +26 -14
  26. package/dist/types/new-metrics.d.ts +41 -9
  27. package/dist/types/operational-metrics.d.ts +19 -0
  28. package/package.json +12 -12
  29. package/src/behavioral-metrics.ts +40 -0
  30. package/src/business-metrics.ts +30 -0
  31. package/src/call-diagnostic/call-diagnostic-metrics.ts +19 -2
  32. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +17 -4
  33. package/src/generic-metrics.ts +146 -0
  34. package/src/index.ts +5 -1
  35. package/src/metrics.types.ts +30 -16
  36. package/src/new-metrics.ts +95 -17
  37. package/src/operational-metrics.ts +24 -0
  38. package/test/unit/spec/behavioral/behavioral-metrics.ts +51 -10
  39. package/test/unit/spec/business/business-metrics.ts +120 -0
  40. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +2 -1
  41. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +167 -1
  42. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +22 -8
  43. package/test/unit/spec/new-metrics.ts +14 -0
  44. package/test/unit/spec/operational/operational-metrics.ts +115 -0
  45. package/test/unit/spec/prelogin-metrics-batcher.ts +3 -1
  46. package/dist/behavioral/behavioral-metrics.js.map +0 -1
  47. package/dist/behavioral/config.js +0 -11
  48. package/dist/behavioral/config.js.map +0 -1
  49. package/dist/types/behavioral/behavioral-metrics.d.ts +0 -63
  50. package/dist/types/behavioral/config.d.ts +0 -1
  51. package/src/behavioral/behavioral-metrics.ts +0 -179
  52. package/src/behavioral/config.ts +0 -3
@@ -0,0 +1,63 @@
1
+ import { StatelessWebexPlugin } from '@webex/webex-core';
2
+ import { DeviceContext, TaggedEvent, EventPayload, MetricType } from './metrics.types';
3
+ /**
4
+ * @description top-level abstract class to handle Metrics and common routines.
5
+ * @export
6
+ * @class GenericMetrics
7
+ */
8
+ export default abstract class GenericMetrics extends StatelessWebexPlugin {
9
+ private clientMetricsBatcher;
10
+ private logger;
11
+ private device;
12
+ private version;
13
+ private deviceId;
14
+ /**
15
+ * Constructor
16
+ * @param {any[]} args
17
+ */
18
+ constructor(...args: any[]);
19
+ /**
20
+ * Submit a buisness metric to our metrics endpoint.
21
+ * @param {string} kind of metric for logging
22
+ * @param {string} name of the metric
23
+ * @param {object} event
24
+ * @returns {Promise<any>}
25
+ */
26
+ protected submitEvent({ kind, name, event }: {
27
+ kind: string;
28
+ name: string;
29
+ event: object;
30
+ }): any;
31
+ /**
32
+ * Returns the deviceId from our registration with WDM.
33
+ * @returns {string} deviceId or empty string
34
+ */
35
+ protected getDeviceId(): string;
36
+ /**
37
+ * Returns the context object to be submitted with all metrics.
38
+ * @returns {DeviceContext}
39
+ */
40
+ protected getContext(): DeviceContext;
41
+ /**
42
+ * Returns the browser details to be included with all metrics.
43
+ * @returns {object}
44
+ */
45
+ protected getBrowserDetails(): object;
46
+ /**
47
+ * Returns true once we have the deviceId we need to submit behavioral/operational/buisness events
48
+ * @returns {boolean}
49
+ */
50
+ isReadyToSubmitEvents(): boolean;
51
+ /**
52
+ * Creates the object to send to our metrics endpoint for a tagged event (i.e. behavoral or operational)
53
+ * @param {[MetricType]} list of event type (i.e. ['behavioral'], ['operational', 'behavioral'])
54
+ * @param {string} metric name
55
+ * @param {EventPayload} user payload
56
+ * @returns {EventPayload}
57
+ */
58
+ protected createTaggedEventObject({ type, name, payload, }: {
59
+ type: [MetricType];
60
+ name: string;
61
+ payload: EventPayload;
62
+ }): TaggedEvent;
63
+ }
@@ -9,7 +9,9 @@ import * as CALL_DIAGNOSTIC_CONFIG from './call-diagnostic/config';
9
9
  import * as CallDiagnosticUtils from './call-diagnostic/call-diagnostic-metrics.util';
10
10
  import CallDiagnosticMetrics from './call-diagnostic/call-diagnostic-metrics';
11
11
  import CallDiagnosticLatencies from './call-diagnostic/call-diagnostic-metrics-latencies';
12
- import BehavioralMetrics from './behavioral/behavioral-metrics';
12
+ import BehavioralMetrics from './behavioral-metrics';
13
+ import OperationalMetrics from './operational-metrics';
14
+ import BusinessMetrics from './business-metrics';
13
15
  export { default, getOSNameInternal } from './metrics';
14
- export { config, CALL_DIAGNOSTIC_CONFIG, NewMetrics, Utils, CallDiagnosticUtils, CallDiagnosticLatencies, CallDiagnosticMetrics, BehavioralMetrics, };
16
+ export { config, CALL_DIAGNOSTIC_CONFIG, NewMetrics, Utils, CallDiagnosticUtils, CallDiagnosticLatencies, CallDiagnosticMetrics, BehavioralMetrics, OperationalMetrics, BusinessMetrics, };
15
17
  export type { ClientEvent, ClientEventLeaveReason, SubmitBehavioralEvent, SubmitClientEvent, SubmitInternalEvent, SubmitMQE, SubmitOperationalEvent, PreComputedLatencies, };
@@ -15,6 +15,7 @@ export type SubmitClientEventOptions = {
15
15
  mediaConnections?: any[];
16
16
  rawError?: any;
17
17
  correlationId?: string;
18
+ sessionCorrelationId?: string;
18
19
  preLoginId?: string;
19
20
  environment?: EnvironmentType;
20
21
  newEnvironmentType?: NewEnvironmentType;
@@ -40,7 +41,7 @@ export interface ClientEvent {
40
41
  payload?: RawClientEvent;
41
42
  options?: SubmitClientEventOptions;
42
43
  }
43
- export interface BehavioralEventContext {
44
+ export interface DeviceContext {
44
45
  app: {
45
46
  version: string;
46
47
  };
@@ -53,19 +54,30 @@ export interface BehavioralEventContext {
53
54
  version: string;
54
55
  };
55
56
  }
56
- export interface BehavioralEvent {
57
- context: BehavioralEventContext;
57
+ export type MetricType = 'behavioral' | 'operational' | 'business';
58
+ type InternalEventPayload = string | number | boolean;
59
+ export type EventPayload = Record<string, InternalEventPayload>;
60
+ export type BehavioralEventPayload = EventPayload;
61
+ export interface BusinessEventPayload {
58
62
  metricName: string;
59
- tags: Record<string, string | number | boolean>;
60
63
  timestamp: number;
64
+ context: DeviceContext;
65
+ browserDetails: EventPayload;
66
+ value: EventPayload;
67
+ }
68
+ export interface BusinessEvent {
61
69
  type: string[];
70
+ eventPayload: BusinessEventPayload;
62
71
  }
63
- export type BehavioralEventPayload = BehavioralEvent['tags'];
64
- export interface OperationalEvent {
65
- name: never;
66
- payload?: never;
67
- options?: never;
72
+ export interface TaggedEvent {
73
+ context: DeviceContext;
74
+ metricName: string;
75
+ tags: EventPayload;
76
+ timestamp: number;
77
+ type: [MetricType];
68
78
  }
79
+ export type BehavioralEvent = TaggedEvent;
80
+ export type OperationalEvent = TaggedEvent;
69
81
  export interface FeatureEvent {
70
82
  name: never;
71
83
  payload?: never;
@@ -79,7 +91,7 @@ export interface MediaQualityEvent {
79
91
  export type RecursivePartial<T> = {
80
92
  [P in keyof T]?: T[P] extends (infer U)[] ? RecursivePartial<U>[] : T[P] extends object ? RecursivePartial<T[P]> : T[P];
81
93
  };
82
- export type MetricEventNames = InternalEvent['name'] | ClientEvent['name'] | BehavioralEvent['metricName'] | OperationalEvent['name'] | FeatureEvent['name'] | MediaQualityEvent['name'];
94
+ export type MetricEventNames = InternalEvent['name'] | ClientEvent['name'] | BehavioralEvent['metricName'] | OperationalEvent['metricName'] | BusinessEvent['eventPayload']['metricName'] | FeatureEvent['name'] | MediaQualityEvent['name'];
83
95
  export type ClientInfo = NonNullable<RawEvent['origin']['clientInfo']>;
84
96
  export type ClientType = NonNullable<RawEvent['origin']['clientInfo']>['clientType'];
85
97
  export type SubClientType = NonNullable<RawEvent['origin']['clientInfo']>['subClientType'];
@@ -103,7 +115,7 @@ export type SubmitBehavioralEvent = (args: {
103
115
  agent: MetricEventAgent;
104
116
  target: string;
105
117
  verb: MetricEventVerb;
106
- payload?: BehavioralEventPayload;
118
+ payload?: EventPayload;
107
119
  }) => void;
108
120
  export type SubmitClientEvent = (args: {
109
121
  name: ClientEvent['name'];
@@ -111,9 +123,8 @@ export type SubmitClientEvent = (args: {
111
123
  options?: SubmitClientEventOptions;
112
124
  }) => Promise<any>;
113
125
  export type SubmitOperationalEvent = (args: {
114
- name: OperationalEvent['name'];
115
- payload?: RecursivePartial<OperationalEvent['payload']>;
116
- options?: any;
126
+ name: OperationalEvent['metricName'];
127
+ payload: EventPayload;
117
128
  }) => void;
118
129
  export type SubmitMQE = (args: {
119
130
  name: MediaQualityEvent['name'];
@@ -126,3 +137,4 @@ export type BuildClientEventFetchRequestOptions = (args: {
126
137
  options?: SubmitClientEventOptions;
127
138
  }) => Promise<any>;
128
139
  export type PreComputedLatencies = 'internal.client.pageJMT' | 'internal.download.time' | 'internal.get.cluster.time' | 'internal.click.to.interstitial' | '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';
140
+ export {};
@@ -1,7 +1,9 @@
1
1
  import { WebexPlugin } from '@webex/webex-core';
2
2
  import CallDiagnosticMetrics from './call-diagnostic/call-diagnostic-metrics';
3
- import BehavioralMetrics from './behavioral/behavioral-metrics';
4
- import { RecursivePartial, MetricEventProduct, MetricEventAgent, MetricEventVerb, ClientEvent, FeatureEvent, BehavioralEventPayload, OperationalEvent, MediaQualityEvent, InternalEvent, SubmitClientEventOptions } from './metrics.types';
3
+ import BehavioralMetrics from './behavioral-metrics';
4
+ import OperationalMetrics from './operational-metrics';
5
+ import BusinessMetrics from './business-metrics';
6
+ import { RecursivePartial, MetricEventProduct, MetricEventAgent, MetricEventVerb, ClientEvent, FeatureEvent, EventPayload, MediaQualityEvent, InternalEvent, SubmitClientEventOptions } from './metrics.types';
5
7
  import CallDiagnosticLatencies from './call-diagnostic/call-diagnostic-metrics-latencies';
6
8
  /**
7
9
  * Metrics plugin to centralize all types of metrics.
@@ -12,6 +14,9 @@ declare class Metrics extends WebexPlugin {
12
14
  callDiagnosticLatencies: CallDiagnosticLatencies;
13
15
  callDiagnosticMetrics: CallDiagnosticMetrics;
14
16
  behavioralMetrics: BehavioralMetrics;
17
+ operationalMetrics: OperationalMetrics;
18
+ businessMetrics: BusinessMetrics;
19
+ isReady: boolean;
15
20
  /**
16
21
  * Constructor
17
22
  * @param args
@@ -33,10 +38,30 @@ declare class Metrics extends WebexPlugin {
33
38
  payload?: RecursivePartial<InternalEvent['payload']>;
34
39
  options?: any;
35
40
  }): void;
41
+ /**
42
+ * if webex metrics is ready, build behavioral metric backend if not already done.
43
+ */
44
+ private lazyBuildBehavioralMetrics;
45
+ /**
46
+ * if webex metrics is ready, build operational metric backend if not already done.
47
+ */
48
+ private lazyBuildOperationalMetrics;
49
+ /**
50
+ * if webex metrics is ready, build business metric backend if not already done.
51
+ */
52
+ private lazyBuildBusinessMetrics;
36
53
  /**
37
54
  * @returns true once we have the deviceId we need to submit behavioral events to Amplitude
38
55
  */
39
56
  isReadyToSubmitBehavioralEvents(): boolean;
57
+ /**
58
+ * @returns true once we have the deviceId we need to submit operational events
59
+ */
60
+ isReadyToSubmitOperationalEvents(): boolean;
61
+ /**
62
+ * @returns true once we have the deviceId we need to submit buisness events
63
+ */
64
+ isReadyToSubmitBusinessEvents(): boolean;
40
65
  /**
41
66
  * Behavioral event
42
67
  * @param args
@@ -46,17 +71,24 @@ declare class Metrics extends WebexPlugin {
46
71
  agent: MetricEventAgent;
47
72
  target: string;
48
73
  verb: MetricEventVerb;
49
- payload?: BehavioralEventPayload;
50
- }): any;
74
+ payload?: EventPayload;
75
+ }): void | Promise<void>;
51
76
  /**
52
77
  * Operational event
53
78
  * @param args
54
79
  */
55
- submitOperationalEvent({ name, payload, options, }: {
56
- name: OperationalEvent['name'];
57
- payload?: RecursivePartial<OperationalEvent['payload']>;
58
- options?: any;
59
- }): void;
80
+ submitOperationalEvent({ name, payload }: {
81
+ name: string;
82
+ payload?: EventPayload;
83
+ }): void | Promise<void>;
84
+ /**
85
+ * Buisness event
86
+ * @param args
87
+ */
88
+ submitBusinessEvent({ name, payload }: {
89
+ name: string;
90
+ payload: EventPayload;
91
+ }): void | Promise<void>;
60
92
  /**
61
93
  * Call Analyzer: Media Quality Event
62
94
  * @param args
@@ -0,0 +1,19 @@
1
+ import GenericMetrics from './generic-metrics';
2
+ import { EventPayload } from './metrics.types';
3
+ /**
4
+ * @description Util class to handle Operational Metrics
5
+ * @export
6
+ * @class OperationalMetrics
7
+ */
8
+ export default class OperationalMetrics extends GenericMetrics {
9
+ /**
10
+ * Submit an operational metric to our metrics endpoint.
11
+ * @param {string} name of the metric
12
+ * @param {EventPayload} user payload of the metric
13
+ * @returns {Promise<any>}
14
+ */
15
+ submitOperationalEvent({ name, payload }: {
16
+ name: string;
17
+ payload: EventPayload;
18
+ }): void;
19
+ }
package/package.json CHANGED
@@ -26,22 +26,22 @@
26
26
  "@webex/eslint-config-legacy": "0.0.0",
27
27
  "@webex/jest-config-legacy": "0.0.0",
28
28
  "@webex/legacy-tools": "0.0.0",
29
- "@webex/test-helper-chai": "3.4.0",
30
- "@webex/test-helper-mocha": "3.4.0",
31
- "@webex/test-helper-mock-webex": "3.4.0",
32
- "@webex/test-helper-test-users": "3.4.0",
29
+ "@webex/test-helper-chai": "3.5.0-next.2",
30
+ "@webex/test-helper-mocha": "3.5.0-next.2",
31
+ "@webex/test-helper-mock-webex": "3.5.0-next.2",
32
+ "@webex/test-helper-test-users": "3.5.0-next.2",
33
33
  "eslint": "^8.24.0",
34
34
  "prettier": "^2.7.1",
35
35
  "sinon": "^9.2.4"
36
36
  },
37
37
  "dependencies": {
38
- "@webex/common": "3.4.0",
39
- "@webex/common-timers": "3.4.0",
40
- "@webex/event-dictionary-ts": "^1.0.1406",
41
- "@webex/internal-plugin-metrics": "3.4.0",
42
- "@webex/test-helper-chai": "3.4.0",
43
- "@webex/test-helper-mock-webex": "3.4.0",
44
- "@webex/webex-core": "3.4.0",
38
+ "@webex/common": "3.5.0-next.2",
39
+ "@webex/common-timers": "3.5.0-next.2",
40
+ "@webex/event-dictionary-ts": "^1.0.1546",
41
+ "@webex/internal-plugin-metrics": "3.5.0-next.2",
42
+ "@webex/test-helper-chai": "3.5.0-next.2",
43
+ "@webex/test-helper-mock-webex": "3.5.0-next.2",
44
+ "@webex/webex-core": "3.5.0-next.2",
45
45
  "ip-anonymize": "^0.1.0",
46
46
  "lodash": "^4.17.21",
47
47
  "uuid": "^3.3.2"
@@ -54,5 +54,5 @@
54
54
  "test:style": "eslint ./src/**/*.*",
55
55
  "test:unit": "webex-legacy-tools test --unit --runner mocha"
56
56
  },
57
- "version": "3.4.0"
57
+ "version": "3.5.0-next.2"
58
58
  }
@@ -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,30 @@
1
+ import GenericMetrics from './generic-metrics';
2
+ import {EventPayload} 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
+ * Submit a buisness metric to our metrics endpoint.
12
+ * @param {string} name of the metric
13
+ * @param {EventPayload} user payload of the metric
14
+ * @returns {Promise<any>}
15
+ */
16
+ public submitBusinessEvent({name, payload}: {name: string; payload: EventPayload}) {
17
+ const event = {
18
+ type: ['business'],
19
+ eventPayload: {
20
+ key: name,
21
+ client_timestamp: Date.now(),
22
+ context: this.getContext(),
23
+ browserDetails: this.getBrowserDetails(),
24
+ value: payload,
25
+ },
26
+ };
27
+
28
+ this.submitEvent({kind: 'buisness-events -> ', name, event});
29
+ }
30
+ }
@@ -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;
@@ -285,13 +286,20 @@ 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
292
  correlationId: 'unknown',
293
+ sessionCorrelationId: 'unknown',
291
294
  };
292
295
 
293
296
  if (meeting) {
294
297
  identifiers.correlationId = meeting.correlationId;
298
+ identifiers.sessionCorrelationId = meeting.sessionCorrelationId;
299
+ }
300
+
301
+ if (sessionCorrelationId) {
302
+ identifiers.sessionCorrelationId = sessionCorrelationId;
295
303
  }
296
304
 
297
305
  if (correlationId) {
@@ -646,7 +654,13 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
646
654
  options?: SubmitClientEventOptions;
647
655
  errors?: ClientEventPayloadError;
648
656
  }) {
649
- const {meetingId, mediaConnections, globalMeetingId, webexConferenceIdStr} = options;
657
+ const {
658
+ meetingId,
659
+ mediaConnections,
660
+ globalMeetingId,
661
+ webexConferenceIdStr,
662
+ sessionCorrelationId,
663
+ } = options;
650
664
 
651
665
  // @ts-ignore
652
666
  const meeting = this.webex.meetings.meetingCollection.get(meetingId);
@@ -673,6 +687,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
673
687
  mediaConnections: meeting?.mediaConnections || mediaConnections,
674
688
  webexConferenceIdStr,
675
689
  globalMeetingId,
690
+ sessionCorrelationId,
676
691
  });
677
692
 
678
693
  // create client event object
@@ -714,11 +729,13 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
714
729
  options?: SubmitClientEventOptions;
715
730
  errors?: ClientEventPayloadError;
716
731
  }) {
717
- const {correlationId, globalMeetingId, webexConferenceIdStr, preLoginId} = options;
732
+ const {correlationId, globalMeetingId, webexConferenceIdStr, preLoginId, sessionCorrelationId} =
733
+ options;
718
734
 
719
735
  // grab identifiers
720
736
  const identifiers = this.getIdentifiers({
721
737
  correlationId,
738
+ sessionCorrelationId,
722
739
  preLoginId,
723
740
  globalMeetingId,
724
741
  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?
@@ -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,9 @@ 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';
26
28
 
27
29
  registerInternalPlugin('metrics', Metrics, {
28
30
  config,
@@ -43,6 +45,8 @@ export {
43
45
  CallDiagnosticLatencies,
44
46
  CallDiagnosticMetrics,
45
47
  BehavioralMetrics,
48
+ OperationalMetrics,
49
+ BusinessMetrics,
46
50
  };
47
51
  export type {
48
52
  ClientEvent,