@webex/internal-plugin-metrics 3.0.0-beta.4 → 3.0.0-beta.400

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 (74) hide show
  1. package/README.md +1 -3
  2. package/dist/batcher.js +42 -22
  3. package/dist/batcher.js.map +1 -1
  4. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js +65 -0
  5. package/dist/call-diagnostic/call-diagnostic-metrics-batcher.js.map +1 -0
  6. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +508 -0
  7. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -0
  8. package/dist/call-diagnostic/call-diagnostic-metrics.js +860 -0
  9. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -0
  10. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +367 -0
  11. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -0
  12. package/dist/call-diagnostic/config.js +627 -0
  13. package/dist/call-diagnostic/config.js.map +1 -0
  14. package/dist/client-metrics-batcher.js +3 -8
  15. package/dist/client-metrics-batcher.js.map +1 -1
  16. package/dist/config.js +23 -6
  17. package/dist/config.js.map +1 -1
  18. package/dist/index.js +46 -10
  19. package/dist/index.js.map +1 -1
  20. package/dist/metrics.js +47 -80
  21. package/dist/metrics.js.map +1 -1
  22. package/dist/metrics.types.js +7 -0
  23. package/dist/metrics.types.js.map +1 -0
  24. package/dist/new-metrics.js +300 -0
  25. package/dist/new-metrics.js.map +1 -0
  26. package/dist/prelogin-metrics-batcher.js +82 -0
  27. package/dist/prelogin-metrics-batcher.js.map +1 -0
  28. package/dist/types/batcher.d.ts +7 -0
  29. package/dist/types/call-diagnostic/call-diagnostic-metrics-batcher.d.ts +2 -0
  30. package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +218 -0
  31. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +421 -0
  32. package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +103 -0
  33. package/dist/types/call-diagnostic/config.d.ts +178 -0
  34. package/dist/types/client-metrics-batcher.d.ts +2 -0
  35. package/dist/types/config.d.ts +36 -0
  36. package/dist/types/index.d.ts +15 -0
  37. package/dist/types/metrics.d.ts +3 -0
  38. package/dist/types/metrics.types.d.ts +105 -0
  39. package/dist/types/new-metrics.d.ts +131 -0
  40. package/dist/types/prelogin-metrics-batcher.d.ts +2 -0
  41. package/dist/types/utils.d.ts +6 -0
  42. package/dist/utils.js +27 -0
  43. package/dist/utils.js.map +1 -0
  44. package/package.json +16 -8
  45. package/src/batcher.js +71 -26
  46. package/src/call-diagnostic/call-diagnostic-metrics-batcher.ts +72 -0
  47. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +467 -0
  48. package/src/call-diagnostic/call-diagnostic-metrics.ts +919 -0
  49. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +395 -0
  50. package/src/call-diagnostic/config.ts +685 -0
  51. package/src/client-metrics-batcher.js +4 -4
  52. package/src/config.js +26 -5
  53. package/src/index.ts +56 -0
  54. package/src/metrics.js +47 -58
  55. package/src/metrics.types.ts +170 -0
  56. package/src/new-metrics.ts +278 -0
  57. package/src/prelogin-metrics-batcher.ts +95 -0
  58. package/src/utils.ts +17 -0
  59. package/test/unit/spec/batcher.js +28 -15
  60. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +457 -0
  61. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +657 -0
  62. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +2303 -0
  63. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +634 -0
  64. package/test/unit/spec/client-metrics-batcher.js +28 -15
  65. package/test/unit/spec/metrics.js +94 -116
  66. package/test/unit/spec/new-metrics.ts +231 -0
  67. package/test/unit/spec/prelogin-metrics-batcher.ts +250 -0
  68. package/test/unit/spec/utils.ts +22 -0
  69. package/tsconfig.json +6 -0
  70. package/dist/call-diagnostic-events-batcher.js +0 -70
  71. package/dist/call-diagnostic-events-batcher.js.map +0 -1
  72. package/src/call-diagnostic-events-batcher.js +0 -62
  73. package/src/index.js +0 -17
  74. package/test/unit/spec/call-diagnostic-events-batcher.js +0 -180
package/src/config.js CHANGED
@@ -8,15 +8,36 @@ export const CLIENT_NAME = 'webex-js-sdk';
8
8
  export default {
9
9
  device: {
10
10
  preDiscoveryServices: {
11
- metricsServiceUrl: process.env.METRICS_SERVICE_URL || 'https://metrics-a.wbx2.com/metrics/api/v1',
12
- metrics: process.env.METRICS_SERVICE_URL || 'https://metrics-a.wbx2.com/metrics/api/v1'
13
- }
11
+ metricsServiceUrl:
12
+ process.env.METRICS_SERVICE_URL || 'https://metrics-a.wbx2.com/metrics/api/v1',
13
+ metrics: process.env.METRICS_SERVICE_URL || 'https://metrics-a.wbx2.com/metrics/api/v1',
14
+ },
14
15
  },
15
16
  metrics: {
16
17
  appType: inBrowser ? 'browser' : 'nodejs',
17
18
  batcherWait: 500,
18
19
  batcherMaxCalls: 50,
19
20
  batcherMaxWait: 1500,
20
- batcherRetryPlateau: 32000
21
- }
21
+ batcherRetryPlateau: 32000,
22
+ waitForServiceTimeout: 30,
23
+ },
24
+ };
25
+
26
+ export const OS_NAME = {
27
+ WINDOWS: 'windows',
28
+ MAC: 'mac',
29
+ IOS: 'ios',
30
+ ANDROID: 'android',
31
+ CHROME: 'chrome',
32
+ LINUX: 'linux',
33
+ OTHERS: 'other',
34
+ };
35
+
36
+ export const OSMap = {
37
+ 'Chrome OS': OS_NAME.CHROME,
38
+ macOS: OS_NAME.MAC,
39
+ Windows: OS_NAME.WINDOWS,
40
+ iOS: OS_NAME.IOS,
41
+ Android: OS_NAME.ANDROID,
42
+ Linux: OS_NAME.LINUX,
22
43
  };
package/src/index.ts ADDED
@@ -0,0 +1,56 @@
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ import '@webex/internal-plugin-device';
6
+
7
+ import {registerInternalPlugin} from '@webex/webex-core';
8
+
9
+ import Metrics from './metrics';
10
+ import config from './config';
11
+ import NewMetrics from './new-metrics';
12
+ import * as Utils from './utils';
13
+ import {
14
+ ClientEvent,
15
+ ClientEventLeaveReason,
16
+ SubmitBehavioralEvent,
17
+ SubmitClientEvent,
18
+ SubmitInternalEvent,
19
+ SubmitOperationalEvent,
20
+ SubmitMQE,
21
+ PreComputedLatencies,
22
+ } from './metrics.types';
23
+ import * as CALL_DIAGNOSTIC_CONFIG from './call-diagnostic/config';
24
+ import * as CallDiagnosticUtils from './call-diagnostic/call-diagnostic-metrics.util';
25
+ import CallDiagnosticMetrics from './call-diagnostic/call-diagnostic-metrics';
26
+ import CallDiagnosticLatencies from './call-diagnostic/call-diagnostic-metrics-latencies';
27
+
28
+ registerInternalPlugin('metrics', Metrics, {
29
+ config,
30
+ });
31
+
32
+ registerInternalPlugin('newMetrics', NewMetrics, {
33
+ config,
34
+ });
35
+
36
+ export {default, getOSNameInternal} from './metrics';
37
+
38
+ export {
39
+ config,
40
+ CALL_DIAGNOSTIC_CONFIG,
41
+ NewMetrics,
42
+ Utils,
43
+ CallDiagnosticUtils,
44
+ CallDiagnosticLatencies,
45
+ CallDiagnosticMetrics,
46
+ };
47
+ export type {
48
+ ClientEvent,
49
+ ClientEventLeaveReason,
50
+ SubmitBehavioralEvent,
51
+ SubmitClientEvent,
52
+ SubmitInternalEvent,
53
+ SubmitMQE,
54
+ SubmitOperationalEvent,
55
+ PreComputedLatencies,
56
+ };
package/src/metrics.js CHANGED
@@ -1,28 +1,24 @@
1
+ /* eslint-disable default-param-last */
2
+
1
3
  /*!
2
4
  * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
5
  */
4
6
 
5
7
  import {WebexPlugin} from '@webex/webex-core';
6
8
  import {BrowserDetection} from '@webex/common';
9
+ import {OS_NAME, OSMap, CLIENT_NAME} from './config';
7
10
 
8
- import {CLIENT_NAME} from './config';
9
11
  import Batcher from './batcher';
10
12
  import ClientMetricsBatcher from './client-metrics-batcher';
11
- import CallDiagnosticEventsBatcher from './call-diagnostic-events-batcher';
12
13
 
13
- const {
14
- getOSName,
15
- getOSVersion,
16
- getBrowserName,
17
- getBrowserVersion
18
- } = BrowserDetection();
14
+ const {getOSName, getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
15
+
16
+ export function getOSNameInternal() {
17
+ return OSMap[getOSName()] ?? OS_NAME.OTHERS;
18
+ }
19
19
 
20
20
  function getSparkUserAgent(webex) {
21
- const {
22
- appName,
23
- appVersion,
24
- appPlatform
25
- } = webex?.config ?? {};
21
+ const {appName, appVersion, appPlatform} = webex?.config ?? {};
26
22
 
27
23
  let sparkUserAgent = CLIENT_NAME;
28
24
 
@@ -37,80 +33,68 @@ function getSparkUserAgent(webex) {
37
33
  return sparkUserAgent;
38
34
  }
39
35
 
40
-
41
36
  const Metrics = WebexPlugin.extend({
42
37
  children: {
43
38
  batcher: Batcher,
44
39
  clientMetricsBatcher: ClientMetricsBatcher,
45
- callDiagnosticEventsBatcher: CallDiagnosticEventsBatcher
46
40
  },
47
41
 
48
42
  namespace: 'Metrics',
49
43
 
50
44
  submit(key, value) {
51
- return this.batcher.request(Object.assign({key}, value));
45
+ return this.batcher.request({key, ...value});
52
46
  },
53
47
 
54
-
55
48
  /**
56
- * This corresponds to #sendSemiStructured() in the deprecated metrics handler
49
+ * Returns the payload for submitting client metrics.
57
50
  * @param {string} eventName
58
- * @param {Object} props
59
- * @param {string} preLoginId
60
- * @returns {Object} HttpResponse object
51
+ * @param {any} props
52
+ * @returns {any} - the payload
61
53
  */
62
- submitClientMetrics(eventName, props = {}, preLoginId) {
54
+ getClientMetricsPayload(eventName, props) {
63
55
  if (!eventName) {
64
56
  throw Error('Missing behavioral metric name. Please provide one');
65
57
  }
66
58
  const payload = {metricName: eventName};
59
+ // @ts-ignore
60
+ const providedClientVersion = this.webex.meetings?.config?.metrics?.clientVersion;
67
61
 
68
62
  payload.tags = {
69
63
  ...props.tags,
70
64
  browser: getBrowserName(),
71
- os: getOSName(),
65
+ os: getOSNameInternal(),
66
+ appVersion: providedClientVersion,
72
67
 
73
68
  // Node does not like this so we need to check if it exists or not
74
69
  // eslint-disable-next-line no-undef
75
- domain: typeof window !== 'undefined' ? window.location.hostname || 'non-browser' : 'non-browser', // Check what else we could measure
76
- client_id: this.webex.credentials.config.client_id,
77
- user_id: this.webex.internal.device.userId
70
+ domain:
71
+ typeof window !== 'undefined' ? window.location.hostname || 'non-browser' : 'non-browser', // Check what else we could measure
78
72
  };
79
73
 
80
- try {
81
- payload.tags.org_id = this.webex.credentials.getOrgId();
82
- }
83
- catch {
84
- this.logger.info('metrics: unable to get orgId');
85
- }
86
-
87
-
88
74
  payload.fields = {
89
75
  ...props.fields,
90
76
  browser_version: getBrowserVersion(),
91
77
  os_version: getOSVersion(),
92
78
  sdk_version: this.webex.version,
93
79
  platform: 'Web',
94
- spark_user_agent: getSparkUserAgent(this.webex)
80
+ spark_user_agent: getSparkUserAgent(this.webex),
81
+ client_id: this.webex.credentials.config.client_id,
95
82
  };
96
83
 
97
-
98
84
  payload.type = props.type || this.webex.config.metrics.type;
99
85
 
100
-
101
86
  payload.context = {
102
87
  ...props.context,
103
88
  app: {
104
- version: this.webex.version
89
+ version: this.webex.version,
105
90
  },
106
91
  locale: 'en-US',
107
92
  os: {
108
- name: getOSName(),
109
- version: getOSVersion()
110
- }
93
+ name: getOSNameInternal(),
94
+ version: getOSVersion(),
95
+ },
111
96
  };
112
97
 
113
-
114
98
  if (props.eventPayload) {
115
99
  payload.eventPayload = props.eventPayload;
116
100
  }
@@ -119,9 +103,22 @@ const Metrics = WebexPlugin.extend({
119
103
  // is impossible so unable to use Date.now()
120
104
  payload.timestamp = new Date().valueOf();
121
105
 
106
+ return payload;
107
+ },
108
+
109
+ /**
110
+ * This corresponds to #sendSemiStructured() in the deprecated metrics handler
111
+ * @param {string} eventName
112
+ * @param {Object} props
113
+ * @param {string} preLoginId
114
+ * @returns {Object} HttpResponse object
115
+ */
116
+ submitClientMetrics(eventName, props = {}, preLoginId) {
117
+ const payload = this.getClientMetricsPayload(eventName, props);
118
+
122
119
  if (preLoginId) {
123
120
  const _payload = {
124
- metrics: [payload]
121
+ metrics: [payload],
125
122
  };
126
123
 
127
124
  // Do not batch these because pre-login events occur during onboarding, so we will be partially blind
@@ -144,12 +141,12 @@ const Metrics = WebexPlugin.extend({
144
141
  api: 'metrics',
145
142
  resource: 'clientmetrics',
146
143
  headers: {
147
- 'x-prelogin-userid': preLoginId
144
+ 'x-prelogin-userid': preLoginId,
148
145
  },
149
146
  body: {},
150
147
  qs: {
151
- alias: true
152
- }
148
+ alias: true,
149
+ },
153
150
  });
154
151
  },
155
152
 
@@ -161,20 +158,12 @@ const Metrics = WebexPlugin.extend({
161
158
  resource: 'clientmetrics-prelogin',
162
159
  headers: {
163
160
  authorization: token.toString(),
164
- 'x-prelogin-userid': preLoginId
161
+ 'x-prelogin-userid': preLoginId,
165
162
  },
166
- body: payload
167
- }));
163
+ body: payload,
164
+ })
165
+ );
168
166
  },
169
-
170
- submitCallDiagnosticEvents(payload) {
171
- const event = {
172
- type: 'diagnostic-event',
173
- eventPayload: payload
174
- };
175
-
176
- return this.callDiagnosticEventsBatcher.request(event);
177
- }
178
167
  });
179
168
 
180
169
  export default Metrics;
@@ -0,0 +1,170 @@
1
+ import {
2
+ ClientEvent as RawClientEvent,
3
+ Event as RawEvent,
4
+ MediaQualityEvent as RawMediaQualityEvent,
5
+ } from '@webex/event-dictionary-ts';
6
+
7
+ export type Event = Omit<RawEvent, 'event'> & {event: RawClientEvent | RawMediaQualityEvent};
8
+
9
+ export type ClientEventError = NonNullable<RawClientEvent['errors']>[0];
10
+
11
+ export type EnvironmentType = NonNullable<RawEvent['origin']['environment']>;
12
+
13
+ export type NewEnvironmentType = NonNullable<RawEvent['origin']['newEnvironment']>;
14
+
15
+ export type ClientLaunchMethodType = NonNullable<
16
+ RawEvent['origin']['clientInfo']
17
+ >['clientLaunchMethod'];
18
+
19
+ export type SubmitClientEventOptions = {
20
+ meetingId?: string;
21
+ mediaConnections?: any[];
22
+ rawError?: any;
23
+ correlationId?: string;
24
+ preLoginId?: string;
25
+ environment?: EnvironmentType;
26
+ newEnvironmentType?: NewEnvironmentType;
27
+ clientLaunchMethod?: ClientLaunchMethodType;
28
+ webexConferenceIdStr?: string;
29
+ globalMeetingId?: string;
30
+ };
31
+
32
+ export type SubmitMQEOptions = {
33
+ meetingId: string;
34
+ mediaConnections?: any[];
35
+ networkType?: Event['origin']['networkType'];
36
+ webexConferenceIdStr?: string;
37
+ globalMeetingId?: string;
38
+ };
39
+
40
+ export type InternalEvent = {
41
+ name:
42
+ | 'internal.client.meetinginfo.request'
43
+ | 'internal.client.meetinginfo.response'
44
+ | 'internal.register.device.request'
45
+ | 'internal.register.device.response'
46
+ | 'internal.reset.join.latencies'
47
+ | 'internal.client.meeting.click.joinbutton'
48
+ | 'internal.host.meeting.participant.admitted'
49
+ | 'internal.client.meeting.interstitial-window.showed'
50
+ | 'internal.client.interstitial-window.click.joinbutton'
51
+ | 'internal.client.add-media.turn-discovery.start'
52
+ | 'internal.client.add-media.turn-discovery.end';
53
+
54
+ payload?: never;
55
+ options?: never;
56
+ };
57
+
58
+ export interface ClientEvent {
59
+ name: RawClientEvent['name'];
60
+ payload?: RawClientEvent;
61
+ options?: SubmitClientEventOptions;
62
+ }
63
+
64
+ export interface BehavioralEvent {
65
+ // TODO: not implemented
66
+ name: 'host.meeting.participant.admitted' | 'sdk.media-flow.started';
67
+ payload?: never;
68
+ options?: never;
69
+ }
70
+
71
+ export interface OperationalEvent {
72
+ // TODO: not implemented
73
+ name: never;
74
+ payload?: never;
75
+ options?: never;
76
+ }
77
+
78
+ export interface FeatureEvent {
79
+ // TODO: not implemented
80
+ name: never;
81
+ payload?: never;
82
+ options?: never;
83
+ }
84
+
85
+ export interface MediaQualityEvent {
86
+ name: RawMediaQualityEvent['name'];
87
+ payload?: RawMediaQualityEvent;
88
+ options: SubmitMQEOptions;
89
+ }
90
+
91
+ export type RecursivePartial<T> = {
92
+ [P in keyof T]?: T[P] extends (infer U)[]
93
+ ? RecursivePartial<U>[]
94
+ : T[P] extends object
95
+ ? RecursivePartial<T[P]>
96
+ : T[P];
97
+ };
98
+
99
+ export type MetricEventNames =
100
+ | InternalEvent['name']
101
+ | ClientEvent['name']
102
+ | BehavioralEvent['name']
103
+ | OperationalEvent['name']
104
+ | FeatureEvent['name']
105
+ | MediaQualityEvent['name'];
106
+
107
+ export type ClientInfo = NonNullable<RawEvent['origin']['clientInfo']>;
108
+ export type ClientType = NonNullable<RawEvent['origin']['clientInfo']>['clientType'];
109
+ export type SubClientType = NonNullable<RawEvent['origin']['clientInfo']>['subClientType'];
110
+ export type NetworkType = NonNullable<RawEvent['origin']>['networkType'];
111
+
112
+ export type ClientSubServiceType = ClientEvent['payload']['webexSubServiceType'];
113
+ export type ClientEventPayload = RecursivePartial<ClientEvent['payload']>;
114
+ export type ClientEventLeaveReason = ClientEvent['payload']['leaveReason'];
115
+ export type ClientEventPayloadError = ClientEvent['payload']['errors'];
116
+
117
+ export type MediaQualityEventAudioSetupDelayPayload = NonNullable<
118
+ MediaQualityEvent['payload']
119
+ >['audioSetupDelay'];
120
+ export type MediaQualityEventVideoSetupDelayPayload = NonNullable<
121
+ MediaQualityEvent['payload']
122
+ >['videoSetupDelay'];
123
+
124
+ export type SubmitMQEPayload = RecursivePartial<MediaQualityEvent['payload']> & {
125
+ intervals: NonNullable<MediaQualityEvent['payload']>['intervals'];
126
+ };
127
+
128
+ export type SubmitInternalEvent = (args: {
129
+ name: InternalEvent['name'];
130
+ payload?: RecursivePartial<InternalEvent['payload']>;
131
+ options?: any;
132
+ }) => void;
133
+
134
+ export type SubmitBehavioralEvent = (args: {
135
+ name: BehavioralEvent['name'];
136
+ payload?: RecursivePartial<BehavioralEvent['payload']>;
137
+ options?: any;
138
+ }) => void;
139
+
140
+ export type SubmitClientEvent = (args: {
141
+ name: ClientEvent['name'];
142
+ payload?: RecursivePartial<ClientEvent['payload']>;
143
+ options?: SubmitClientEventOptions;
144
+ }) => Promise<any>;
145
+
146
+ export type SubmitOperationalEvent = (args: {
147
+ name: OperationalEvent['name'];
148
+ payload?: RecursivePartial<OperationalEvent['payload']>;
149
+ options?: any;
150
+ }) => void;
151
+
152
+ export type SubmitMQE = (args: {
153
+ name: MediaQualityEvent['name'];
154
+ payload: SubmitMQEPayload;
155
+ options: any;
156
+ }) => void;
157
+
158
+ export type BuildClientEventFetchRequestOptions = (args: {
159
+ name: ClientEvent['name'];
160
+ payload?: RecursivePartial<ClientEvent['payload']>;
161
+ options?: SubmitClientEventOptions;
162
+ }) => Promise<any>;
163
+
164
+ export type PreComputedLatencies =
165
+ | 'internal.client.pageJMT'
166
+ | 'internal.download.time'
167
+ | 'internal.click.to.interstitial'
168
+ | 'internal.get.u2c.time'
169
+ | 'internal.call.init.join.req'
170
+ | 'internal.other.app.api.time';