@webex/internal-plugin-metrics 3.12.0 → 3.13.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 (98) hide show
  1. package/.repo-context.json +466 -0
  2. package/.sdd/manifest.json +626 -0
  3. package/AGENTS.md +208 -0
  4. package/README.md +274 -0
  5. package/dist/automated-user.js +19 -0
  6. package/dist/automated-user.js.map +1 -0
  7. package/dist/batcher.js +3 -0
  8. package/dist/batcher.js.map +1 -1
  9. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +639 -66
  10. package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
  11. package/dist/call-diagnostic/call-diagnostic-metrics.js +240 -103
  12. package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
  13. package/dist/call-diagnostic/call-diagnostic-metrics.util.js +7 -2
  14. package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
  15. package/dist/call-diagnostic/config.js +19 -4
  16. package/dist/call-diagnostic/config.js.map +1 -1
  17. package/dist/config.js +8 -0
  18. package/dist/config.js.map +1 -1
  19. package/dist/index.js +25 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/metrics.js +118 -5
  22. package/dist/metrics.js.map +1 -1
  23. package/dist/metrics.types.js +4 -0
  24. package/dist/metrics.types.js.map +1 -1
  25. package/dist/network-telemetry.js +610 -0
  26. package/dist/network-telemetry.js.map +1 -0
  27. package/dist/new-metrics.js +63 -17
  28. package/dist/new-metrics.js.map +1 -1
  29. package/dist/privacy-and-security-permission-enricher/constants.js +18 -0
  30. package/dist/privacy-and-security-permission-enricher/constants.js.map +1 -0
  31. package/dist/privacy-and-security-permission-enricher/index.js +143 -0
  32. package/dist/privacy-and-security-permission-enricher/index.js.map +1 -0
  33. package/dist/privacy-and-security-permission-enricher/types.js +7 -0
  34. package/dist/privacy-and-security-permission-enricher/types.js.map +1 -0
  35. package/dist/privacy-and-security-permission-enricher/utils.js +71 -0
  36. package/dist/privacy-and-security-permission-enricher/utils.js.map +1 -0
  37. package/dist/types/automated-user.d.ts +2 -0
  38. package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +208 -5
  39. package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +83 -17
  40. package/dist/types/call-diagnostic/config.d.ts +6 -0
  41. package/dist/types/config.d.ts +9 -0
  42. package/dist/types/index.d.ts +5 -3
  43. package/dist/types/metrics.types.d.ts +11 -5
  44. package/dist/types/network-telemetry.d.ts +108 -0
  45. package/dist/types/new-metrics.d.ts +17 -1
  46. package/dist/types/privacy-and-security-permission-enricher/constants.d.ts +6 -0
  47. package/dist/types/privacy-and-security-permission-enricher/index.d.ts +40 -0
  48. package/dist/types/privacy-and-security-permission-enricher/types.d.ts +14 -0
  49. package/dist/types/privacy-and-security-permission-enricher/utils.d.ts +5 -0
  50. package/dist/types/unhandled-exception-telemetry/index.d.ts +60 -0
  51. package/dist/types/unhandled-exception-telemetry/utils.d.ts +6 -0
  52. package/dist/unhandled-exception-telemetry/index.js +331 -0
  53. package/dist/unhandled-exception-telemetry/index.js.map +1 -0
  54. package/dist/unhandled-exception-telemetry/utils.js +105 -0
  55. package/dist/unhandled-exception-telemetry/utils.js.map +1 -0
  56. package/docs/adr/index.md +27 -0
  57. package/docs/architecture.md +437 -0
  58. package/docs/getting-started.md +131 -0
  59. package/docs/index.md +52 -0
  60. package/docs/specs/README.md +88 -0
  61. package/package.json +12 -11
  62. package/schemas/repo-context.schema.json +796 -0
  63. package/src/automated-user.ts +16 -0
  64. package/src/batcher.js +4 -0
  65. package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +801 -74
  66. package/src/call-diagnostic/call-diagnostic-metrics.ts +184 -42
  67. package/src/call-diagnostic/call-diagnostic-metrics.util.ts +7 -1
  68. package/src/call-diagnostic/config.ts +16 -0
  69. package/src/call-diagnostic/docs/README.md +535 -0
  70. package/src/config.js +8 -0
  71. package/src/docs/README.md +703 -0
  72. package/src/index.ts +16 -0
  73. package/src/metrics.js +123 -5
  74. package/src/metrics.types.ts +29 -6
  75. package/src/network-telemetry.ts +757 -0
  76. package/src/new-metrics.ts +56 -6
  77. package/src/privacy-and-security-permission-enricher/constants.ts +33 -0
  78. package/src/privacy-and-security-permission-enricher/docs/README.md +356 -0
  79. package/src/privacy-and-security-permission-enricher/index.ts +142 -0
  80. package/src/privacy-and-security-permission-enricher/types.ts +21 -0
  81. package/src/privacy-and-security-permission-enricher/utils.ts +82 -0
  82. package/src/rtcMetrics/docs/README.md +447 -0
  83. package/src/unhandled-exception-telemetry/docs/README.md +536 -0
  84. package/src/unhandled-exception-telemetry/index.ts +404 -0
  85. package/src/unhandled-exception-telemetry/utils.ts +101 -0
  86. package/test/unit/spec/automated-user.ts +43 -0
  87. package/test/unit/spec/batcher.js +43 -0
  88. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +14 -2
  89. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +1435 -304
  90. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +1265 -207
  91. package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +27 -0
  92. package/test/unit/spec/metrics.js +14 -5
  93. package/test/unit/spec/network-telemetry.ts +610 -0
  94. package/test/unit/spec/new-metrics.ts +203 -50
  95. package/test/unit/spec/prelogin-metrics-batcher.ts +71 -36
  96. package/test/unit/spec/privacy-and-security-permission-enricher.ts +318 -0
  97. package/test/unit/spec/unhandled-exception-telemetry/utils.ts +109 -0
  98. package/test/unit/spec/unhandled-exception-telemetry.ts +689 -0
package/src/index.ts CHANGED
@@ -2,12 +2,15 @@
2
2
  * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
3
  */
4
4
 
5
+ /* eslint-disable valid-jsdoc */
6
+
5
7
  import {registerInternalPlugin} from '@webex/webex-core';
6
8
 
7
9
  import Metrics from './metrics';
8
10
  import config from './config';
9
11
  import NewMetrics from './new-metrics';
10
12
  import * as Utils from './utils';
13
+ import * as AutomatedUserUtils from './automated-user';
11
14
  import {
12
15
  ClientEvent,
13
16
  ClientEventLeaveReason,
@@ -19,6 +22,8 @@ import {
19
22
  SubmitMQE,
20
23
  PreComputedLatencies,
21
24
  SubmitFeatureEvent,
25
+ LocusSyncLatencyEventName,
26
+ PrivacyAndSecurityPermission,
22
27
  } from './metrics.types';
23
28
  import * as CALL_DIAGNOSTIC_CONFIG from './call-diagnostic/config';
24
29
  import * as CallDiagnosticUtils from './call-diagnostic/call-diagnostic-metrics.util';
@@ -32,6 +37,13 @@ import PreLoginMetrics from './prelogin-metrics';
32
37
 
33
38
  registerInternalPlugin('metrics', Metrics, {
34
39
  config,
40
+ /**
41
+ * Stops network telemetry before SDK logout.
42
+ * @returns
43
+ */
44
+ onBeforeLogout() {
45
+ return this.stopNetworkTelemetry();
46
+ },
35
47
  });
36
48
 
37
49
  registerInternalPlugin('newMetrics', NewMetrics, {
@@ -43,6 +55,7 @@ export {default, getOSNameInternal} from './metrics';
43
55
  export {
44
56
  config,
45
57
  CALL_DIAGNOSTIC_CONFIG,
58
+ AutomatedUserUtils,
46
59
  NewMetrics,
47
60
  Utils,
48
61
  CallDiagnosticUtils,
@@ -54,6 +67,7 @@ export {
54
67
  RtcMetrics,
55
68
  PreLoginMetrics,
56
69
  };
70
+ export {isAutomatedUser, isAutomatedUserAgent} from './automated-user';
57
71
  export type {
58
72
  ClientEvent,
59
73
  ClientEventLeaveReason,
@@ -65,4 +79,6 @@ export type {
65
79
  SubmitBusinessEvent,
66
80
  PreComputedLatencies,
67
81
  SubmitFeatureEvent,
82
+ LocusSyncLatencyEventName,
83
+ PrivacyAndSecurityPermission,
68
84
  };
package/src/metrics.js CHANGED
@@ -1,4 +1,5 @@
1
1
  /* eslint-disable default-param-last */
2
+ /* eslint-disable valid-jsdoc */
2
3
 
3
4
  /*!
4
5
  * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
@@ -11,6 +12,7 @@ import {OS_NAME, OSMap, CLIENT_NAME} from './config';
11
12
  import Batcher from './batcher';
12
13
  import ClientMetricsBatcher from './client-metrics-batcher';
13
14
  import ClientMetricsPreloginBatcher from './client-metrics-prelogin-batcher';
15
+ import {createNetworkTelemetryCollector} from './network-telemetry';
14
16
 
15
17
  const {getOSName, getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
16
18
 
@@ -43,6 +45,119 @@ const Metrics = WebexPlugin.extend({
43
45
 
44
46
  namespace: 'Metrics',
45
47
 
48
+ /**
49
+ * Registers SDK request outcome monitoring.
50
+ * @param args
51
+ * @returns
52
+ */
53
+ initialize(...args) {
54
+ WebexPlugin.prototype.initialize.call(this, ...args);
55
+
56
+ // Metrics may also be constructed as a standalone plugin. Request events are
57
+ // available only when it is attached to a Webex instance.
58
+ if (!this.parent && !this.collection) {
59
+ return;
60
+ }
61
+
62
+ const initializeNetworkTelemetry = () => {
63
+ if (
64
+ this.networkTelemetry ||
65
+ this.webex?.config?.metrics?.networkTelemetry?.enabled !== true
66
+ ) {
67
+ return;
68
+ }
69
+
70
+ this.networkTelemetry = createNetworkTelemetryCollector({
71
+ intervalMs: this.webex.config.metrics.networkTelemetry.intervalMs,
72
+ submitMetric: this.submitNetworkTelemetryMetric.bind(this),
73
+ onSubmissionFailure: this.handleNetworkTelemetrySubmissionFailure.bind(this),
74
+ });
75
+ this.listenTo(this.webex, 'request:start', this.recordNetworkRequestStart);
76
+ this.listenTo(this.webex, 'request:success', this.recordNetworkRequestSuccess);
77
+ this.listenTo(this.webex, 'request:failure', this.recordNetworkRequestFailure);
78
+ };
79
+
80
+ // Ampersand initializes children before WebexCore.initialize() populates
81
+ // webex.config. Run immediately for already-configured hosts (including
82
+ // MockWebex), and listen for the real core's post-initialization notification.
83
+ this.listenToOnce(this.webex, 'change:config', initializeNetworkTelemetry);
84
+ initializeNetworkTelemetry();
85
+ },
86
+
87
+ /**
88
+ * Records an SDK request being sent in the current reporting window.
89
+ * @param options
90
+ * @returns
91
+ */
92
+ recordNetworkRequestStart(options) {
93
+ this.networkTelemetry.recordRequest(options);
94
+ },
95
+
96
+ /**
97
+ * Records a successful SDK request for the current reporting window.
98
+ * @param options
99
+ * @returns
100
+ */
101
+ recordNetworkRequestSuccess(options) {
102
+ this.networkTelemetry.recordResponse(options);
103
+ },
104
+
105
+ /**
106
+ * Records a failed SDK request for the current reporting window.
107
+ * @param options
108
+ * @param reason
109
+ * @returns
110
+ */
111
+ recordNetworkRequestFailure(options, reason) {
112
+ this.networkTelemetry.recordFailure(options, reason);
113
+ },
114
+
115
+ /**
116
+ * Submits the current network telemetry window immediately.
117
+ * @returns
118
+ */
119
+ flushNetworkTelemetry() {
120
+ if (!this.networkTelemetry) {
121
+ return Promise.resolve();
122
+ }
123
+
124
+ return this.networkTelemetry.flush();
125
+ },
126
+
127
+ /**
128
+ * Submits a completed network telemetry window through client metrics.
129
+ * @param name
130
+ * @param properties
131
+ * @returns
132
+ */
133
+ submitNetworkTelemetryMetric(name, properties) {
134
+ return this.submitClientMetrics(name, properties);
135
+ },
136
+
137
+ /**
138
+ * Logs a network telemetry submission failure without affecting SDK requests.
139
+ * @returns
140
+ */
141
+ handleNetworkTelemetrySubmissionFailure() {
142
+ this.webex.logger?.warn('metrics: failed to submit network request summary telemetry');
143
+ },
144
+
145
+ /**
146
+ * Stops network telemetry collection and submission.
147
+ * @returns
148
+ */
149
+ stopNetworkTelemetry() {
150
+ if (!this.networkTelemetry) {
151
+ return Promise.resolve();
152
+ }
153
+
154
+ this.stopListening(this.webex, 'request:start', this.recordNetworkRequestStart);
155
+ this.stopListening(this.webex, 'request:success', this.recordNetworkRequestSuccess);
156
+ this.stopListening(this.webex, 'request:failure', this.recordNetworkRequestFailure);
157
+
158
+ return this.networkTelemetry.stop();
159
+ },
160
+
46
161
  submit(key, value) {
47
162
  return this.batcher.request({key, ...value});
48
163
  },
@@ -60,17 +175,20 @@ const Metrics = WebexPlugin.extend({
60
175
  const payload = {metricName: eventName};
61
176
  // @ts-ignore
62
177
  const providedClientVersion = this.webex.meetings?.config?.metrics?.clientVersion;
178
+ const {appName, appVersion} = this.webex.config;
179
+ // Browser location is unavailable when the SDK runs in Node.js.
180
+ // eslint-disable-next-line no-undef
181
+ const browserLocation = typeof window !== 'undefined' ? window.location : undefined;
63
182
 
64
183
  payload.tags = {
65
184
  ...props.tags,
185
+ app_name: appName ?? 'unknown',
186
+ app_url: browserLocation?.origin || browserLocation?.hostname || 'non-browser',
187
+ app_version: appVersion ?? 'unknown',
66
188
  browser: getBrowserName(),
67
189
  os: getOSNameInternal(),
68
190
  appVersion: providedClientVersion,
69
-
70
- // Node does not like this so we need to check if it exists or not
71
- // eslint-disable-next-line no-undef
72
- domain:
73
- typeof window !== 'undefined' ? window.location.hostname || 'non-browser' : 'non-browser', // Check what else we could measure
191
+ domain: browserLocation?.hostname || 'non-browser',
74
192
  };
75
193
 
76
194
  payload.fields = {
@@ -23,6 +23,15 @@ export type ClientUserNameInput = NonNullable<RawClientEvent['userNameInput']>;
23
23
 
24
24
  export type ClientEmailInput = NonNullable<RawClientEvent['emailInput']>;
25
25
 
26
+ export type PrivacyAndSecurityPermission = NonNullable<
27
+ RawClientEvent['privacyAndSecurityPermission']
28
+ >;
29
+
30
+ export type PrivacyAndSecurityPermissionResource = keyof PrivacyAndSecurityPermission;
31
+
32
+ export type PrivacyAndSecurityPermissionState =
33
+ PrivacyAndSecurityPermission[PrivacyAndSecurityPermissionResource];
34
+
26
35
  export type BrowserLaunchMethodType = NonNullable<
27
36
  RawEvent['origin']['clientInfo']
28
37
  >['browserLaunchMethod'];
@@ -133,6 +142,7 @@ export type SubmitClientEventOptions = {
133
142
  browserLaunchMethod?: BrowserLaunchMethodType;
134
143
  webexConferenceIdStr?: string;
135
144
  globalMeetingId?: string;
145
+ locusCluster?: string;
136
146
  joinFlowVersion?: MetricEventJoinFlowVersion;
137
147
  meetingJoinPhase?: MetricEventMeetingJoinPhase;
138
148
  triggeredTime?: string;
@@ -149,6 +159,17 @@ export type SubmitMQEOptions = {
149
159
  globalMeetingId?: string;
150
160
  };
151
161
 
162
+ export const LOCUS_SYNC_LATENCY_EVENT_NAMES = [
163
+ 'internal.client.locus.sync.start',
164
+ 'internal.client.locus.hashtree.request',
165
+ 'internal.client.locus.hashtree.response',
166
+ 'internal.client.locus.sync.request',
167
+ 'internal.client.locus.sync.response',
168
+ 'internal.client.locus.sync.message.received',
169
+ ] as const;
170
+
171
+ export type LocusSyncLatencyEventName = (typeof LOCUS_SYNC_LATENCY_EVENT_NAMES)[number];
172
+
152
173
  export type InternalEvent = {
153
174
  name:
154
175
  | 'internal.client.meetinginfo.request'
@@ -156,14 +177,14 @@ export type InternalEvent = {
156
177
  | 'internal.register.device.request'
157
178
  | 'internal.register.device.response'
158
179
  | 'internal.reset.join.latencies'
159
- | 'internal.client.meeting.click.joinbutton'
160
180
  | 'internal.host.meeting.participant.admitted'
161
181
  | 'internal.client.meeting.interstitial-window.showed'
162
182
  | 'internal.client.interstitial-window.click.joinbutton'
163
183
  | 'internal.client.add-media.turn-discovery.start'
164
184
  | 'internal.client.add-media.turn-discovery.end'
165
185
  | 'internal.client.share.initiated'
166
- | 'internal.client.share.stopped';
186
+ | 'internal.client.share.stopped'
187
+ | LocusSyncLatencyEventName;
167
188
 
168
189
  payload?: never;
169
190
  options?: never;
@@ -251,10 +272,10 @@ export type ClientType = NonNullable<RawEvent['origin']['clientInfo']>['clientTy
251
272
  export type SubClientType = NonNullable<RawEvent['origin']['clientInfo']>['subClientType'];
252
273
  export type NetworkType = NonNullable<RawEvent['origin']>['networkType'];
253
274
 
254
- export type ClientSubServiceType = ClientEvent['payload']['webexSubServiceType'];
275
+ export type ClientSubServiceType = NonNullable<ClientEvent['payload']>['webexSubServiceType'];
255
276
  export type ClientEventPayload = RecursivePartial<ClientEvent['payload']>;
256
- export type ClientEventLeaveReason = ClientEvent['payload']['leaveReason'];
257
- export type ClientEventPayloadError = ClientEvent['payload']['errors'];
277
+ export type ClientEventLeaveReason = NonNullable<ClientEvent['payload']>['leaveReason'];
278
+ export type ClientEventPayloadError = NonNullable<ClientEvent['payload']>['errors'];
258
279
 
259
280
  export type ClientFeatureEventPayload = RecursivePartial<FeatureEvent['payload']>;
260
281
 
@@ -319,12 +340,14 @@ export type PreComputedLatencies =
319
340
  | 'internal.get.cluster.time'
320
341
  | 'internal.click.to.interstitial'
321
342
  | 'internal.click.to.interstitial.with.user.delay'
343
+ | 'internal.click.to.interstitial.for.client.jmt'
322
344
  | 'internal.refresh.captcha.time'
323
345
  | 'internal.exchange.ci.token.time'
324
346
  | 'internal.get.u2c.time'
325
347
  | 'internal.call.init.join.req'
326
348
  | 'internal.other.app.api.time'
327
- | 'internal.api.fetch.intelligence.models';
349
+ | 'internal.api.fetch.intelligence.models'
350
+ | 'internal.client.locus.sync.random.backoff';
328
351
 
329
352
  export interface IdType {
330
353
  meetingId?: string;