@webex/internal-plugin-metrics 3.4.0 → 3.5.0

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 (45) 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 +12 -4
  6. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
  7. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +8 -3
  8. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
  9. package/dist/generic-metrics.js +184 -0
  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 +17 -2
  32. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +7 -0
  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.ts +13 -1
  41. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +15 -5
  42. package/test/unit/spec/new-metrics.ts +14 -0
  43. package/test/unit/spec/operational/operational-metrics.ts +115 -0
  44. package/src/behavioral/behavioral-metrics.ts +0 -179
  45. package/src/behavioral/config.ts +0 -3
@@ -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,36 @@ 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
+ type InternalEventPayload = string | number | boolean;
119
+ export type EventPayload = Record<string, InternalEventPayload>;
120
+ export type BehavioralEventPayload = EventPayload; // for compatibilty, can be remove after wxcc-desktop did change their imports.
121
+
122
+ export interface BusinessEventPayload {
117
123
  metricName: string;
118
- tags: Record<string, string | number | boolean>;
119
124
  timestamp: number;
120
- type: string[];
125
+ context: DeviceContext;
126
+ browserDetails: EventPayload;
127
+ value: EventPayload;
121
128
  }
122
129
 
123
- export type BehavioralEventPayload = BehavioralEvent['tags'];
130
+ export interface BusinessEvent {
131
+ type: string[];
132
+ eventPayload: BusinessEventPayload;
133
+ }
124
134
 
125
- export interface OperationalEvent {
126
- // TODO: not implemented
127
- name: never;
128
- payload?: never;
129
- options?: never;
135
+ export interface TaggedEvent {
136
+ context: DeviceContext;
137
+ metricName: string;
138
+ tags: EventPayload;
139
+ timestamp: number;
140
+ type: [MetricType];
130
141
  }
131
142
 
143
+ export type BehavioralEvent = TaggedEvent;
144
+ export type OperationalEvent = TaggedEvent;
145
+
132
146
  export interface FeatureEvent {
133
147
  // TODO: not implemented
134
148
  name: never;
@@ -154,7 +168,8 @@ export type MetricEventNames =
154
168
  | InternalEvent['name']
155
169
  | ClientEvent['name']
156
170
  | BehavioralEvent['metricName']
157
- | OperationalEvent['name']
171
+ | OperationalEvent['metricName']
172
+ | BusinessEvent['eventPayload']['metricName']
158
173
  | FeatureEvent['name']
159
174
  | MediaQualityEvent['name'];
160
175
 
@@ -190,7 +205,7 @@ export type SubmitBehavioralEvent = (args: {
190
205
  agent: MetricEventAgent;
191
206
  target: string;
192
207
  verb: MetricEventVerb;
193
- payload?: BehavioralEventPayload;
208
+ payload?: EventPayload;
194
209
  }) => void;
195
210
 
196
211
  export type SubmitClientEvent = (args: {
@@ -200,9 +215,8 @@ export type SubmitClientEvent = (args: {
200
215
  }) => Promise<any>;
201
216
 
202
217
  export type SubmitOperationalEvent = (args: {
203
- name: OperationalEvent['name'];
204
- payload?: RecursivePartial<OperationalEvent['payload']>;
205
- options?: any;
218
+ name: OperationalEvent['metricName'];
219
+ payload: EventPayload;
206
220
  }) => void;
207
221
 
208
222
  export type SubmitMQE = (args: {
@@ -6,7 +6,9 @@
6
6
  import {WebexPlugin} from '@webex/webex-core';
7
7
 
8
8
  import CallDiagnosticMetrics from './call-diagnostic/call-diagnostic-metrics';
9
- import BehavioralMetrics from './behavioral/behavioral-metrics';
9
+ import BehavioralMetrics from './behavioral-metrics';
10
+ import OperationalMetrics from './operational-metrics';
11
+ import BusinessMetrics from './business-metrics';
10
12
  import {
11
13
  RecursivePartial,
12
14
  MetricEventProduct,
@@ -14,7 +16,7 @@ import {
14
16
  MetricEventVerb,
15
17
  ClientEvent,
16
18
  FeatureEvent,
17
- BehavioralEventPayload,
19
+ EventPayload,
18
20
  OperationalEvent,
19
21
  MediaQualityEvent,
20
22
  InternalEvent,
@@ -37,6 +39,9 @@ class Metrics extends WebexPlugin {
37
39
  // Helper classes to handle the different types of metrics
38
40
  callDiagnosticMetrics: CallDiagnosticMetrics;
39
41
  behavioralMetrics: BehavioralMetrics;
42
+ operationalMetrics: OperationalMetrics;
43
+ businessMetrics: BusinessMetrics;
44
+ isReady = false;
40
45
 
41
46
  /**
42
47
  * Constructor
@@ -61,8 +66,7 @@ class Metrics extends WebexPlugin {
61
66
  this.webex.once('ready', () => {
62
67
  // @ts-ignore
63
68
  this.callDiagnosticMetrics = new CallDiagnosticMetrics({}, {parent: this.webex});
64
- // @ts-ignore
65
- this.behavioralMetrics = new BehavioralMetrics({}, {parent: this.webex});
69
+ this.isReady = true;
66
70
  });
67
71
  }
68
72
 
@@ -86,11 +90,61 @@ class Metrics extends WebexPlugin {
86
90
  }
87
91
  }
88
92
 
93
+ /**
94
+ * if webex metrics is ready, build behavioral metric backend if not already done.
95
+ */
96
+ private lazyBuildBehavioralMetrics() {
97
+ if (this.isReady && !this.behavioralMetrics) {
98
+ // @ts-ignore
99
+ this.behavioralMetrics = new BehavioralMetrics({}, {parent: this.webex});
100
+ }
101
+ }
102
+
103
+ /**
104
+ * if webex metrics is ready, build operational metric backend if not already done.
105
+ */
106
+ private lazyBuildOperationalMetrics() {
107
+ if (this.isReady && !this.operationalMetrics) {
108
+ // @ts-ignore
109
+ this.operationalMetrics = new OperationalMetrics({}, {parent: this.webex});
110
+ }
111
+ }
112
+
113
+ /**
114
+ * if webex metrics is ready, build business metric backend if not already done.
115
+ */
116
+ private lazyBuildBusinessMetrics() {
117
+ if (this.isReady && !this.businessMetrics) {
118
+ // @ts-ignore
119
+ this.businessMetrics = new BusinessMetrics({}, {parent: this.webex});
120
+ }
121
+ }
122
+
89
123
  /**
90
124
  * @returns true once we have the deviceId we need to submit behavioral events to Amplitude
91
125
  */
92
126
  isReadyToSubmitBehavioralEvents() {
93
- return this.behavioralMetrics.isReadyToSubmitBehavioralEvents();
127
+ this.lazyBuildBehavioralMetrics();
128
+
129
+ return this.behavioralMetrics?.isReadyToSubmitEvents() ?? false;
130
+ }
131
+
132
+ /**
133
+ * @returns true once we have the deviceId we need to submit operational events
134
+ */
135
+ isReadyToSubmitOperationalEvents() {
136
+ this.lazyBuildOperationalMetrics();
137
+
138
+ return this.operationalMetrics?.isReadyToSubmitEvents() ?? false;
139
+ }
140
+
141
+ /**
142
+ * @returns true once we have the deviceId we need to submit buisness events
143
+ */
144
+ isReadyToSubmitBusinessEvents() {
145
+ this.lazyBuildBusinessMetrics();
146
+
147
+ return this.businessMetrics?.isReadyToSubmitEvents() ?? false;
94
148
  }
95
149
 
96
150
  /**
@@ -108,9 +162,9 @@ class Metrics extends WebexPlugin {
108
162
  agent: MetricEventAgent;
109
163
  target: string;
110
164
  verb: MetricEventVerb;
111
- payload?: BehavioralEventPayload;
165
+ payload?: EventPayload;
112
166
  }) {
113
- if (!this.behavioralMetrics) {
167
+ if (!this.isReady) {
114
168
  // @ts-ignore
115
169
  this.webex.logger.log(
116
170
  `NewMetrics: @submitBehavioralEvent. Attempted to submit before webex.ready: ${product}.${agent}.${target}.${verb}`
@@ -119,6 +173,8 @@ class Metrics extends WebexPlugin {
119
173
  return Promise.resolve();
120
174
  }
121
175
 
176
+ this.lazyBuildBehavioralMetrics();
177
+
122
178
  return this.behavioralMetrics.submitBehavioralEvent({product, agent, target, verb, payload});
123
179
  }
124
180
 
@@ -126,16 +182,38 @@ class Metrics extends WebexPlugin {
126
182
  * Operational event
127
183
  * @param args
128
184
  */
129
- submitOperationalEvent({
130
- name,
131
- payload,
132
- options,
133
- }: {
134
- name: OperationalEvent['name'];
135
- payload?: RecursivePartial<OperationalEvent['payload']>;
136
- options?: any;
137
- }) {
138
- throw new Error('Not implemented.');
185
+ submitOperationalEvent({name, payload}: {name: string; payload?: EventPayload}) {
186
+ if (!this.isReady) {
187
+ // @ts-ignore
188
+ this.webex.logger.log(
189
+ `NewMetrics: @submitOperationalEvent. Attempted to submit before webex.ready: ${name}`
190
+ );
191
+
192
+ return Promise.resolve();
193
+ }
194
+
195
+ this.lazyBuildOperationalMetrics();
196
+
197
+ return this.operationalMetrics.submitOperationalEvent({name, payload});
198
+ }
199
+
200
+ /**
201
+ * Buisness event
202
+ * @param args
203
+ */
204
+ submitBusinessEvent({name, payload}: {name: string; payload: EventPayload}) {
205
+ if (!this.isReady) {
206
+ // @ts-ignore
207
+ this.webex.logger.log(
208
+ `NewMetrics: @submitBusinessEvent. Attempted to submit before webex.ready: ${name}`
209
+ );
210
+
211
+ return Promise.resolve();
212
+ }
213
+
214
+ this.lazyBuildBusinessMetrics();
215
+
216
+ return this.businessMetrics.submitBusinessEvent({name, payload});
139
217
  }
140
218
 
141
219
  /**
@@ -0,0 +1,24 @@
1
+ import GenericMetrics from './generic-metrics';
2
+ import {EventPayload} from './metrics.types';
3
+
4
+ /**
5
+ * @description Util class to handle Operational Metrics
6
+ * @export
7
+ * @class OperationalMetrics
8
+ */
9
+ export default class OperationalMetrics extends GenericMetrics {
10
+ /**
11
+ * Submit an operational 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 submitOperationalEvent({name, payload}: {name: string; payload: EventPayload}) {
17
+ const event = this.createTaggedEventObject({
18
+ type: ['operational'],
19
+ name,
20
+ payload,
21
+ });
22
+ this.submitEvent({kind: 'operational-events -> ', name, event});
23
+ }
24
+ }
@@ -74,6 +74,45 @@ describe('internal-plugin-metrics', () => {
74
74
  sinon.restore();
75
75
  });
76
76
 
77
+ describe('#sendEvent', () => {
78
+ it('should send correctly shaped behavioral event (check name building and internal tagged event building)', () => {
79
+ // For some reasons `jest` isn't available when testing form build server - so can't use `jest.fn()` here...
80
+ const requestCalls = [];
81
+ const request = function(arg) { requestCalls.push(arg) }
82
+
83
+ behavioralMetrics.clientMetricsBatcher.request = request;
84
+
85
+ assert.equal(requestCalls.length, 0)
86
+ behavioralMetrics.submitBehavioralEvent({ product: "webex", agent: "user", target: "foo", verb: "get", payload: {bar:"gee"} })
87
+ assert.equal(requestCalls.length, 1)
88
+ assert.deepEqual(requestCalls[0], {
89
+ context: {
90
+ app: {version: 'webex-version'},
91
+ device: {id: 'deviceId'},
92
+ locale: 'language',
93
+ os: {
94
+ name: getOSNameInternal(),
95
+ version: getOSVersion(),
96
+ },
97
+ },
98
+ metricName: 'webex.user.foo.get',
99
+ tags: {
100
+ browser: getBrowserName(),
101
+ browserHeight: window.innerHeight,
102
+ browserVersion: getBrowserVersion(),
103
+ browserWidth: window.innerWidth,
104
+ domain: window.location.hostname,
105
+ inIframe: false,
106
+ locale: window.navigator.language,
107
+ os: getOSNameInternal(),
108
+ bar:"gee"
109
+ },
110
+ timestamp: requestCalls[0].timestamp, // This is to bypass time check, which is correctly tested below.
111
+ type: ['behavioral'],
112
+ });
113
+ })
114
+ })
115
+
77
116
  describe('#getContext', () => {
78
117
  it('should build context correctly', () => {
79
118
  const res = behavioralMetrics.getContext();
@@ -96,7 +135,7 @@ describe('internal-plugin-metrics', () => {
96
135
 
97
136
  describe('#getDefaultTags', () => {
98
137
  it('should build tags correctly', () => {
99
- const res = behavioralMetrics.getDefaultTags();
138
+ const res = behavioralMetrics.getBrowserDetails();
100
139
 
101
140
  assert.deepEqual(res, {
102
141
  browser: getBrowserName(),
@@ -111,25 +150,27 @@ describe('internal-plugin-metrics', () => {
111
150
  });
112
151
  });
113
152
 
114
- describe('#isReadyToSubmitBehavioralEvents', () => {
153
+ describe('#isReadyToSubmitEvents', () => {
115
154
  it('should return true when we have a deviceId, false when deviceId is empty or undefined', async () => {
116
- assert.equal(true, behavioralMetrics.isReadyToSubmitBehavioralEvents());
155
+ let deviceIdUrl = webex.internal.device.url;
117
156
 
157
+ // testing case w/o device id url first, as the internal deviceId cache would bypass that flow.
118
158
  webex.internal.device.url = "";
119
- assert.equal(false, behavioralMetrics.isReadyToSubmitBehavioralEvents());
159
+ assert.equal(false, behavioralMetrics.isReadyToSubmitEvents());
120
160
 
121
161
  delete webex.internal.device.url;
122
- assert.equal(false, behavioralMetrics.isReadyToSubmitBehavioralEvents());
162
+ assert.equal(false, behavioralMetrics.isReadyToSubmitEvents());
163
+
164
+ webex.internal.device.url = deviceIdUrl;
165
+ assert.equal(true, behavioralMetrics.isReadyToSubmitEvents());
123
166
  });
124
167
  });
125
168
 
126
169
  describe('#createEventObject', () => {
127
170
  it('should build event object correctly', async () => {
128
- const res = behavioralMetrics.createEventObject({
129
- product: 'webex',
130
- agent: 'user',
131
- target: 'target',
132
- verb: 'create',
171
+ const res = behavioralMetrics.createTaggedEventObject({
172
+ type:['behavioral'],
173
+ name:'webex.user.target.create',
133
174
  payload: tags,
134
175
  });
135
176
 
@@ -0,0 +1,120 @@
1
+ import sinon from 'sinon';
2
+ import {assert} from '@webex/test-helper-chai';
3
+ import {BrowserDetection} from '@webex/common';
4
+ import {BusinessMetrics, config, getOSNameInternal} from '@webex/internal-plugin-metrics';
5
+ import uuid from 'uuid';
6
+
7
+ //@ts-ignore
8
+ global.window = {location: {hostname: 'whatever'}, navigator: {language: 'language'}};
9
+ process.env.NODE_ENV = 'test';
10
+
11
+ const {getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
12
+
13
+ describe('internal-plugin-metrics', () => {
14
+ describe('BusinessMetrics', () => {
15
+ let webex;
16
+ let now;
17
+ let businessMetrics: BusinessMetrics;
18
+
19
+ const tags = {key: 'val'};
20
+
21
+ beforeEach(() => {
22
+ now = new Date();
23
+
24
+ webex = {
25
+ canAuthorize: true,
26
+ version: 'webex-version',
27
+ internal: {
28
+ services: {
29
+ get: () => 'locus-url',
30
+ },
31
+ metrics: {
32
+ submitClientMetrics: sinon.stub(),
33
+ config: {...config.metrics},
34
+ },
35
+ newMetrics: {},
36
+ device: {
37
+ userId: 'userId',
38
+ url: 'https://wdm-intb.ciscospark.com/wdm/api/v1/devices/deviceId',
39
+ orgId: 'orgId',
40
+ },
41
+ },
42
+ meetings: {
43
+ config: {
44
+ metrics: {
45
+ clientType: 'TEAMS_CLIENT',
46
+ subClientType: 'WEB_APP',
47
+ clientName: 'Cantina',
48
+ },
49
+ },
50
+ geoHintInfo: {
51
+ clientAddress: '1.3.4.5',
52
+ countryCode: 'UK',
53
+ },
54
+ },
55
+ credentials: {
56
+ isUnverifiedGuest: false,
57
+ },
58
+ prepareFetchOptions: sinon.stub().callsFake((opts: any) => ({...opts, foo: 'bar'})),
59
+ request: sinon.stub().resolves({body: {}}),
60
+ logger: {
61
+ log: sinon.stub(),
62
+ error: sinon.stub(),
63
+ },
64
+ };
65
+
66
+ sinon.createSandbox();
67
+ sinon.useFakeTimers(now.getTime());
68
+ businessMetrics = new BusinessMetrics({}, {parent: webex});
69
+ sinon.stub(uuid, 'v4').returns('my-fake-id');
70
+ });
71
+
72
+ afterEach(() => {
73
+ sinon.restore();
74
+ });
75
+
76
+ describe('#sendEvent', () => {
77
+ it('should send correctly shaped business event (check name building and internal tagged event building)', () => {
78
+ // For some reasons `jest` isn't available when testing form build server - so can't use `jest.fn()` here...
79
+ const requestCalls = [];
80
+ const request = function(arg) { requestCalls.push(arg) }
81
+
82
+ businessMetrics.clientMetricsBatcher.request = request;
83
+
84
+ assert.equal(requestCalls.length, 0)
85
+ businessMetrics.submitBusinessEvent({ name: "foobar", payload: {bar:"gee"} })
86
+ assert.equal(requestCalls.length, 1)
87
+ assert.deepEqual(requestCalls[0], {
88
+ eventPayload: {
89
+ context: {
90
+ app: {version: 'webex-version'},
91
+ device: {id: 'deviceId'},
92
+ locale: 'language',
93
+ os: {
94
+ name: getOSNameInternal(),
95
+ version: getOSVersion(),
96
+ },
97
+ },
98
+ key: 'foobar',
99
+ browserDetails: {
100
+ browser: getBrowserName(),
101
+ browserHeight: window.innerHeight,
102
+ browserVersion: getBrowserVersion(),
103
+ browserWidth: window.innerWidth,
104
+ domain: window.location.hostname,
105
+ inIframe: false,
106
+ locale: window.navigator.language,
107
+ os: getOSNameInternal(),
108
+ },
109
+ client_timestamp: requestCalls[0].eventPayload.client_timestamp, // This is to bypass time check, which is checked below.
110
+ value: {
111
+ bar: "gee"
112
+ }
113
+ },
114
+ type: ['business'],
115
+ });
116
+ assert.isNumber(requestCalls[0].eventPayload.client_timestamp)
117
+ })
118
+ })
119
+ });
120
+ });
@@ -372,6 +372,7 @@ describe('internal-plugin-metrics', () => {
372
372
  {mediaAgentAlias: 'mediaAgentAlias', mediaAgentGroupId: 'mediaAgentGroupId'},
373
373
  ],
374
374
  webexConferenceIdStr: 'webexConferenceIdStr',
375
+ sessionCorrelationId: 'sessionCorrelationId',
375
376
  globalMeetingId: 'globalMeetingId',
376
377
  meeting: {
377
378
  ...fakeMeeting,
@@ -386,6 +387,7 @@ describe('internal-plugin-metrics', () => {
386
387
  assert.deepEqual(res, {
387
388
  correlationId: 'correlationId',
388
389
  webexConferenceIdStr: 'webexConferenceIdStr1',
390
+ sessionCorrelationId: 'sessionCorrelationId',
389
391
  globalMeetingId: 'globalMeetingId1',
390
392
  deviceId: 'deviceUrl',
391
393
  locusId: 'url',
@@ -608,6 +610,7 @@ describe('internal-plugin-metrics', () => {
608
610
  meeting: fakeMeeting,
609
611
  mediaConnections: [{mediaAgentAlias: 'alias', mediaAgentGroupId: '1'}],
610
612
  webexConferenceIdStr: undefined,
613
+ sessionCorrelationId: undefined,
611
614
  globalMeetingId: undefined,
612
615
  });
613
616
  assert.notCalled(generateClientEventErrorPayloadSpy);
@@ -762,7 +765,7 @@ describe('internal-plugin-metrics', () => {
762
765
  ]);
763
766
  });
764
767
 
765
- it('should submit client event successfully with correlationId, webexConferenceIdStr and globalMeetingId', () => {
768
+ it('should submit client event successfully with correlationId, webexConferenceIdStr, sessionCorrelationId, and globalMeetingId', () => {
766
769
  const prepareDiagnosticEventSpy = sinon.spy(cd, 'prepareDiagnosticEvent');
767
770
  const submitToCallDiagnosticsSpy = sinon.spy(cd, 'submitToCallDiagnostics');
768
771
  const generateClientEventErrorPayloadSpy = sinon.spy(cd, 'generateClientEventErrorPayload');
@@ -773,6 +776,7 @@ describe('internal-plugin-metrics', () => {
773
776
  correlationId: 'correlationId',
774
777
  webexConferenceIdStr: 'webexConferenceIdStr1',
775
778
  globalMeetingId: 'globalMeetingId1',
779
+ sessionCorrelationId: 'sessionCorrelationId1'
776
780
  };
777
781
 
778
782
  cd.submitClientEvent({
@@ -784,6 +788,7 @@ describe('internal-plugin-metrics', () => {
784
788
  correlationId: 'correlationId',
785
789
  webexConferenceIdStr: 'webexConferenceIdStr1',
786
790
  globalMeetingId: 'globalMeetingId1',
791
+ sessionCorrelationId: 'sessionCorrelationId1',
787
792
  preLoginId: undefined,
788
793
  });
789
794
 
@@ -798,6 +803,7 @@ describe('internal-plugin-metrics', () => {
798
803
  identifiers: {
799
804
  correlationId: 'correlationId',
800
805
  webexConferenceIdStr: 'webexConferenceIdStr1',
806
+ sessionCorrelationId: 'sessionCorrelationId1',
801
807
  globalMeetingId: 'globalMeetingId1',
802
808
  deviceId: 'deviceUrl',
803
809
  locusUrl: 'locus-url',
@@ -818,6 +824,7 @@ describe('internal-plugin-metrics', () => {
818
824
  identifiers: {
819
825
  correlationId: 'correlationId',
820
826
  webexConferenceIdStr: 'webexConferenceIdStr1',
827
+ sessionCorrelationId: 'sessionCorrelationId1',
821
828
  globalMeetingId: 'globalMeetingId1',
822
829
  deviceId: 'deviceUrl',
823
830
  locusUrl: 'locus-url',
@@ -863,6 +870,7 @@ describe('internal-plugin-metrics', () => {
863
870
  webexConferenceIdStr: 'webexConferenceIdStr1',
864
871
  globalMeetingId: 'globalMeetingId1',
865
872
  preLoginId: 'myPreLoginId',
873
+ sessionCorrelationId: 'sessionCorrelationId1'
866
874
  };
867
875
 
868
876
  cd.submitClientEvent({
@@ -875,6 +883,7 @@ describe('internal-plugin-metrics', () => {
875
883
  webexConferenceIdStr: 'webexConferenceIdStr1',
876
884
  globalMeetingId: 'globalMeetingId1',
877
885
  preLoginId: 'myPreLoginId',
886
+ sessionCorrelationId: 'sessionCorrelationId1'
878
887
  });
879
888
 
880
889
  assert.notCalled(generateClientEventErrorPayloadSpy);
@@ -887,6 +896,7 @@ describe('internal-plugin-metrics', () => {
887
896
  },
888
897
  identifiers: {
889
898
  correlationId: 'correlationId',
899
+ sessionCorrelationId: 'sessionCorrelationId1',
890
900
  webexConferenceIdStr: 'webexConferenceIdStr1',
891
901
  globalMeetingId: 'globalMeetingId1',
892
902
  deviceId: 'deviceUrl',
@@ -913,6 +923,7 @@ describe('internal-plugin-metrics', () => {
913
923
  canProceed: true,
914
924
  identifiers: {
915
925
  correlationId: 'correlationId',
926
+ sessionCorrelationId: 'sessionCorrelationId1',
916
927
  userId: 'myPreLoginId',
917
928
  deviceId: 'deviceUrl',
918
929
  orgId: 'orgId',
@@ -1417,6 +1428,7 @@ describe('internal-plugin-metrics', () => {
1417
1428
  meetingId: fakeMeeting.id,
1418
1429
  webexConferenceIdStr: 'webexConferenceIdStr1',
1419
1430
  globalMeetingId: 'globalMeetingId1',
1431
+ sessionCorrelationId: 'sessionCorrelationId1'
1420
1432
  };
1421
1433
 
1422
1434
  cd.submitMQE({
@@ -235,6 +235,8 @@ describe('internal-plugin-metrics', () => {
235
235
  });
236
236
 
237
237
  describe('getBuildType', () => {
238
+ const webex = {internal: {metrics: {config: {}}}};
239
+
238
240
  beforeEach(() => {
239
241
  process.env.NODE_ENV = 'production';
240
242
  });
@@ -246,18 +248,26 @@ describe('internal-plugin-metrics', () => {
246
248
  ['https://web.webex.com', true, 'test'],
247
249
  ].forEach(([webClientDomain, markAsTestEvent, expected]) => {
248
250
  it(`returns expected result for ${webClientDomain}`, () => {
249
- assert.deepEqual(getBuildType(webClientDomain, markAsTestEvent as any), expected);
251
+ assert.deepEqual(getBuildType(webex, webClientDomain, markAsTestEvent as any), expected);
250
252
  });
251
253
  });
252
254
 
253
255
  it('returns "test" for NODE_ENV "foo"', () => {
254
256
  process.env.NODE_ENV = 'foo';
255
- assert.deepEqual(getBuildType('production'), 'test');
257
+ assert.deepEqual(getBuildType(webex, 'production'), 'test');
256
258
  });
257
259
 
258
260
  it('returns "test" for NODE_ENV "production" and markAsTestEvent = true', () => {
259
261
  process.env.NODE_ENV = 'production';
260
- assert.deepEqual(getBuildType('my.domain', true), 'test');
262
+ assert.deepEqual(getBuildType(webex, 'my.domain', true), 'test');
263
+ });
264
+
265
+ it('returns "test" for NODE_ENV "production" when webex.caBuildType = "test"', () => {
266
+ process.env.NODE_ENV = 'production';
267
+ assert.deepEqual(
268
+ getBuildType({internal: {metrics: {config: {caBuildType: 'test'}}}}, 'my.domain'),
269
+ 'test'
270
+ );
261
271
  });
262
272
  });
263
273
 
@@ -418,8 +428,8 @@ describe('internal-plugin-metrics', () => {
418
428
  name: 'client.exit.app',
419
429
  eventData: {
420
430
  markAsTestEvent: true,
421
- webClientDomain: 'https://web.webex.com'
422
- }
431
+ webClientDomain: 'https://web.webex.com',
432
+ },
423
433
  },
424
434
  },
425
435
  type: ['diagnostic-event'],
@@ -73,6 +73,20 @@ describe('internal-plugin-metrics', () => {
73
73
  sinon.restore();
74
74
  })
75
75
 
76
+ it('lazy metrics backend initialization when checking if backend ready', () => {
77
+ assert.isUndefined(webex.internal.newMetrics.behavioralMetrics);
78
+ webex.internal.newMetrics.isReadyToSubmitBehavioralEvents();
79
+ assert.isDefined(webex.internal.newMetrics.behavioralMetrics);
80
+
81
+ assert.isUndefined(webex.internal.newMetrics.operationalMetrics);
82
+ webex.internal.newMetrics.isReadyToSubmitOperationalEvents();
83
+ assert.isDefined(webex.internal.newMetrics.operationalMetrics);
84
+
85
+ assert.isUndefined(webex.internal.newMetrics.businessMetrics)
86
+ webex.internal.newMetrics.isReadyToSubmitBusinessEvents();
87
+ assert.isDefined(webex.internal.newMetrics.businessMetrics);
88
+ })
89
+
76
90
  it('submits Client Event successfully', () => {
77
91
  webex.internal.newMetrics.submitClientEvent({
78
92
  name: 'client.alert.displayed',