@webex/internal-plugin-metrics 3.7.0 → 3.8.0-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/business-metrics.js +74 -100
- package/dist/business-metrics.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js +24 -15
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.js +76 -10
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
- package/dist/call-diagnostic/config.js +19 -12
- package/dist/call-diagnostic/config.js.map +1 -1
- package/dist/generic-metrics.js +2 -2
- package/dist/generic-metrics.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metrics.js +1 -1
- package/dist/metrics.types.js.map +1 -1
- package/dist/new-metrics.js +28 -5
- package/dist/new-metrics.js.map +1 -1
- package/dist/types/business-metrics.d.ts +10 -28
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +14 -1
- package/dist/types/call-diagnostic/config.d.ts +2 -0
- package/dist/types/generic-metrics.d.ts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/metrics.types.d.ts +17 -1
- package/dist/types/new-metrics.d.ts +15 -3
- package/package.json +12 -12
- package/src/business-metrics.ts +66 -76
- package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +36 -14
- package/src/call-diagnostic/call-diagnostic-metrics.ts +80 -3
- package/src/call-diagnostic/config.ts +8 -0
- package/src/generic-metrics.ts +2 -2
- package/src/index.ts +2 -0
- package/src/metrics.types.ts +21 -1
- package/src/new-metrics.ts +32 -4
- package/test/unit/spec/business/business-metrics.ts +2 -2
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +85 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +674 -32
- package/test/unit/spec/new-metrics.ts +23 -0
- package/dist/behavioral/behavioral-metrics.js +0 -199
- package/dist/behavioral/behavioral-metrics.js.map +0 -1
- package/dist/behavioral/config.js +0 -11
- package/dist/behavioral/config.js.map +0 -1
- package/dist/types/behavioral/behavioral-metrics.d.ts +0 -63
- package/dist/types/behavioral/config.d.ts +0 -1
|
@@ -1,51 +1,33 @@
|
|
|
1
1
|
import GenericMetrics from './generic-metrics';
|
|
2
2
|
import { EventPayload, Table } from './metrics.types';
|
|
3
3
|
/**
|
|
4
|
-
* @description Util class to handle
|
|
4
|
+
* @description Util class to handle Business Metrics
|
|
5
5
|
* @export
|
|
6
6
|
* @class BusinessMetrics
|
|
7
7
|
*/
|
|
8
8
|
export default class BusinessMetrics extends GenericMetrics {
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
* so we have to shim this layer specifically for this
|
|
12
|
-
* https://confluence-eng-gpk2.cisco.com/conf/display/WAP/Table+wbxapp_callend_metrics
|
|
13
|
-
* @param {EventPayload} payload payload of the metric
|
|
14
|
-
* @returns {Promise<any>}
|
|
15
|
-
*/
|
|
16
|
-
private submitCallEndEvent;
|
|
17
|
-
/**
|
|
18
|
-
* Submit a buisness metric to our metrics endpoint, going to the default business_ucf table
|
|
19
|
-
* all event payload keys are converted into a hex string value
|
|
20
|
-
* unfortunately, the pinot team does not allow changes to the schema of business_metrics
|
|
21
|
-
* so we have to shim this layer specifically for this
|
|
22
|
-
* https://confluence-eng-gpk2.cisco.com/conf/display/WAP/Table%3A+business_metrics
|
|
23
|
-
* @param {string} name of the metric
|
|
24
|
-
* @param {EventPayload} payload payload of the metric
|
|
25
|
-
* @returns {Promise<any>}
|
|
26
|
-
*/
|
|
27
|
-
private submitBusinessMetricsEvent;
|
|
28
|
-
/**
|
|
29
|
-
* Submit a buisness metric to our metrics endpoint, going to the default business_ucf table
|
|
30
|
-
* all event payload keys are converted into a hex string value
|
|
31
|
-
* https://confluence-eng-gpk2.cisco.com/conf/display/WAP/Business+metrics++-%3E+ROMA
|
|
10
|
+
* Build the metric event to submit.
|
|
32
11
|
* @param {string} name of the metric
|
|
33
|
-
* @param {EventPayload} user payload of the metric
|
|
34
|
-
* @
|
|
12
|
+
* @param {EventPayload} payload user payload of the metric
|
|
13
|
+
* @param {EventPayload} metadata to include outside of eventPayload.value
|
|
14
|
+
* @returns {MetricEvent} The constructed metric event
|
|
35
15
|
*/
|
|
36
|
-
private
|
|
16
|
+
private buildEvent;
|
|
37
17
|
/**
|
|
38
|
-
* Submit a
|
|
18
|
+
* Submit a business metric to our metrics endpoint.
|
|
39
19
|
* routes to the correct table with the correct schema payload by table
|
|
40
20
|
* https://confluence-eng-gpk2.cisco.com/conf/display/WAP/Business+metrics++-%3E+ROMA
|
|
41
21
|
* @param {string} name of the metric, ignored if going to wbxapp_callend_metrics
|
|
42
22
|
* @param {EventPayload} payload user payload of the metric
|
|
43
23
|
* @param {Table} table optional - to submit the metric to and adapt the sent schema
|
|
24
|
+
* @param {EventPayload} metadata optional - to include outside of eventPayload.value
|
|
44
25
|
* @returns {Promise<any>}
|
|
45
26
|
*/
|
|
46
|
-
submitBusinessEvent({ name, payload, table, }: {
|
|
27
|
+
submitBusinessEvent({ name, payload, table, metadata, }: {
|
|
47
28
|
name: string;
|
|
48
29
|
payload: EventPayload;
|
|
49
30
|
table?: Table;
|
|
31
|
+
metadata?: EventPayload;
|
|
50
32
|
}): Promise<void>;
|
|
51
33
|
}
|
|
@@ -29,6 +29,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
29
29
|
private logger;
|
|
30
30
|
private hasLoggedBrowserSerial;
|
|
31
31
|
private device;
|
|
32
|
+
private delayedClientEvents;
|
|
32
33
|
validator: (options: {
|
|
33
34
|
type: 'mqe' | 'ce';
|
|
34
35
|
event: Event;
|
|
@@ -196,6 +197,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
196
197
|
provisionalCorrelationId?: string;
|
|
197
198
|
roomId?: string;
|
|
198
199
|
sessionCorrelationId?: string;
|
|
200
|
+
sharedMediaId?: string;
|
|
199
201
|
sipCallId?: string;
|
|
200
202
|
sipSessionId?: {
|
|
201
203
|
local?: string;
|
|
@@ -223,6 +225,8 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
223
225
|
webexSiteUuid?: string;
|
|
224
226
|
webexUserId?: number;
|
|
225
227
|
webexWebDomain?: string;
|
|
228
|
+
recordingId?: string;
|
|
229
|
+
clientCorrelationId?: string;
|
|
226
230
|
correlationId: string;
|
|
227
231
|
additionalProperties?: false;
|
|
228
232
|
} | {
|
|
@@ -276,6 +280,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
276
280
|
provisionalCorrelationId?: string;
|
|
277
281
|
roomId?: string;
|
|
278
282
|
sessionCorrelationId?: string;
|
|
283
|
+
sharedMediaId?: string;
|
|
279
284
|
sipCallId?: string;
|
|
280
285
|
sipSessionId?: {
|
|
281
286
|
local?: string;
|
|
@@ -303,6 +308,8 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
303
308
|
webexSiteUuid?: string;
|
|
304
309
|
webexUserId?: number;
|
|
305
310
|
webexWebDomain?: string;
|
|
311
|
+
recordingId?: string;
|
|
312
|
+
clientCorrelationId?: string;
|
|
306
313
|
correlationId: string;
|
|
307
314
|
additionalProperties?: false;
|
|
308
315
|
};
|
|
@@ -401,13 +408,19 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
401
408
|
* @param arg.event - event key
|
|
402
409
|
* @param arg.payload - additional payload to be merged with default payload
|
|
403
410
|
* @param arg.options - payload
|
|
411
|
+
* @param arg.delaySubmitEvent - a boolean value indicating whether to delay the submission of client events.
|
|
404
412
|
* @throws
|
|
405
413
|
*/
|
|
406
|
-
submitClientEvent({ name, payload, options, }: {
|
|
414
|
+
submitClientEvent({ name, payload, options, delaySubmitEvent, }: {
|
|
407
415
|
name: ClientEvent['name'];
|
|
408
416
|
payload?: ClientEventPayload;
|
|
409
417
|
options?: SubmitClientEventOptions;
|
|
418
|
+
delaySubmitEvent?: boolean;
|
|
410
419
|
}): Promise<any>;
|
|
420
|
+
/**
|
|
421
|
+
* Submit Delayed Client Event CA events. Clears delayedClientEvents array after submission.
|
|
422
|
+
*/
|
|
423
|
+
submitDelayedClientEvents(): Promise<any[]> | Promise<void>;
|
|
411
424
|
/**
|
|
412
425
|
* Prepare the event and send the request to metrics-a service.
|
|
413
426
|
* @param event
|
|
@@ -11,6 +11,7 @@ export declare const DTLS_HANDSHAKE_FAILED_CLIENT_CODE = 2008;
|
|
|
11
11
|
export declare const ICE_FAILED_WITH_TURN_TLS_CLIENT_CODE = 2010;
|
|
12
12
|
export declare const ICE_FAILED_WITHOUT_TURN_TLS_CLIENT_CODE = 2009;
|
|
13
13
|
export declare const ICE_AND_REACHABILITY_FAILED_CLIENT_CODE = 2011;
|
|
14
|
+
export declare const MULTISTREAM_NOT_AVAILABLE_CLIENT_CODE = 2012;
|
|
14
15
|
export declare const WBX_APP_API_URL = "wbxappapi";
|
|
15
16
|
export declare const WEBEX_SUB_SERVICE_TYPES: Record<string, ClientSubServiceType>;
|
|
16
17
|
export declare const BROWSER_MEDIA_ERROR_NAME_TO_CLIENT_ERROR_CODES_MAP: {
|
|
@@ -94,6 +95,7 @@ export declare const ERROR_DESCRIPTIONS: {
|
|
|
94
95
|
ICE_FAILED_WITHOUT_TURN_TLS: string;
|
|
95
96
|
ICE_FAILED_WITH_TURN_TLS: string;
|
|
96
97
|
ICE_AND_REACHABILITY_FAILED: string;
|
|
98
|
+
MULTISTREAM_NOT_AVAILABLE: string;
|
|
97
99
|
SDP_OFFER_CREATION_ERROR: string;
|
|
98
100
|
SDP_OFFER_CREATION_ERROR_MISSING_CODEC: string;
|
|
99
101
|
WDM_RESTRICTED_REGION: string;
|
|
@@ -17,7 +17,7 @@ export default abstract class GenericMetrics extends StatelessWebexPlugin {
|
|
|
17
17
|
*/
|
|
18
18
|
constructor(...args: any[]);
|
|
19
19
|
/**
|
|
20
|
-
* Submit a
|
|
20
|
+
* Submit a business metric to our metrics endpoint.
|
|
21
21
|
* @param {string} kind of metric for logging
|
|
22
22
|
* @param {string} name of the metric
|
|
23
23
|
* @param {object} event
|
|
@@ -44,7 +44,7 @@ export default abstract class GenericMetrics extends StatelessWebexPlugin {
|
|
|
44
44
|
*/
|
|
45
45
|
protected getBrowserDetails(): object;
|
|
46
46
|
/**
|
|
47
|
-
* Returns true once we have the deviceId we need to submit behavioral/operational/
|
|
47
|
+
* Returns true once we have the deviceId we need to submit behavioral/operational/business events
|
|
48
48
|
* @returns {boolean}
|
|
49
49
|
*/
|
|
50
50
|
isReadyToSubmitEvents(): boolean;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import config from './config';
|
|
5
5
|
import NewMetrics from './new-metrics';
|
|
6
6
|
import * as Utils from './utils';
|
|
7
|
-
import { ClientEvent, ClientEventLeaveReason, SubmitBehavioralEvent, SubmitClientEvent, SubmitInternalEvent, SubmitOperationalEvent, SubmitMQE, PreComputedLatencies } from './metrics.types';
|
|
7
|
+
import { ClientEvent, ClientEventLeaveReason, SubmitBehavioralEvent, SubmitClientEvent, SubmitInternalEvent, SubmitOperationalEvent, SubmitBusinessEvent, SubmitMQE, PreComputedLatencies } from './metrics.types';
|
|
8
8
|
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';
|
|
@@ -15,4 +15,4 @@ import BusinessMetrics from './business-metrics';
|
|
|
15
15
|
import RtcMetrics from './rtcMetrics';
|
|
16
16
|
export { default, getOSNameInternal } from './metrics';
|
|
17
17
|
export { config, CALL_DIAGNOSTIC_CONFIG, NewMetrics, Utils, CallDiagnosticUtils, CallDiagnosticLatencies, CallDiagnosticMetrics, BehavioralMetrics, OperationalMetrics, BusinessMetrics, RtcMetrics, };
|
|
18
|
-
export type { ClientEvent, ClientEventLeaveReason, SubmitBehavioralEvent, SubmitClientEvent, SubmitInternalEvent, SubmitMQE, SubmitOperationalEvent, PreComputedLatencies, };
|
|
18
|
+
export type { ClientEvent, ClientEventLeaveReason, SubmitBehavioralEvent, SubmitClientEvent, SubmitInternalEvent, SubmitMQE, SubmitOperationalEvent, SubmitBusinessEvent, PreComputedLatencies, };
|
|
@@ -6,11 +6,14 @@ export type ClientEventError = NonNullable<RawClientEvent['errors']>[0];
|
|
|
6
6
|
export type EnvironmentType = NonNullable<RawEvent['origin']['environment']>;
|
|
7
7
|
export type NewEnvironmentType = NonNullable<RawEvent['origin']['newEnvironment']>;
|
|
8
8
|
export type ClientLaunchMethodType = NonNullable<RawEvent['origin']['clientInfo']>['clientLaunchMethod'];
|
|
9
|
+
export type ClientUserNameInput = NonNullable<RawClientEvent['userNameInput']>;
|
|
10
|
+
export type ClientEmailInput = NonNullable<RawClientEvent['emailInput']>;
|
|
9
11
|
export type BrowserLaunchMethodType = NonNullable<RawEvent['origin']['clientInfo']>['browserLaunchMethod'];
|
|
10
|
-
export type MetricEventProduct = 'webex' | 'wxcc_desktop';
|
|
12
|
+
export type MetricEventProduct = 'webex' | 'wxcc_desktop' | 'wxcc_crm' | 'wxcc_sdk';
|
|
11
13
|
export type MetricEventAgent = 'user' | 'browser' | 'system' | 'sdk' | 'redux' | 'service' | 'api';
|
|
12
14
|
export type MetricEventVerb = 'abort' | 'accept' | 'activate' | 'apply' | 'answer' | 'authorize' | 'build' | 'cancel' | 'change' | 'click' | 'close' | 'complete' | 'connect' | 'create' | 'deactivate' | 'decrypt' | 'delete' | 'deliver' | 'destroy' | 'disable' | 'disconnect' | 'dismiss' | 'display' | 'download' | 'edit' | 'enable' | 'encrypt' | 'end' | 'expire' | 'fail' | 'fetch' | 'fire' | 'generate' | 'get' | 'hide' | 'hover' | 'ignore' | 'initialize' | 'initiate' | 'invalidate' | 'join' | 'list' | 'load' | 'login' | 'logout' | 'notify' | 'offer' | 'open' | 'press' | 'receive' | 'refer' | 'refresh' | 'register' | 'release' | 'reload' | 'reject' | 'request' | 'reset' | 'resize' | 'respond' | 'retry' | 'revoke' | 'save' | 'search' | 'select' | 'send' | 'set' | 'sign' | 'start' | 'submit' | 'switch' | 'sync' | 'toggle' | 'transfer' | 'unregister' | 'update' | 'upload' | 'use' | 'validate' | 'view' | 'visit' | 'wait' | 'warn' | 'exit';
|
|
13
15
|
export type MetricEventJoinFlowVersion = 'Other' | 'NewFTE';
|
|
16
|
+
export type MetricEventMeetingJoinPhase = 'pre-join' | 'join' | 'in-meeting';
|
|
14
17
|
export type SubmitClientEventOptions = {
|
|
15
18
|
meetingId?: string;
|
|
16
19
|
mediaConnections?: any[];
|
|
@@ -25,6 +28,10 @@ export type SubmitClientEventOptions = {
|
|
|
25
28
|
webexConferenceIdStr?: string;
|
|
26
29
|
globalMeetingId?: string;
|
|
27
30
|
joinFlowVersion?: MetricEventJoinFlowVersion;
|
|
31
|
+
meetingJoinPhase?: MetricEventMeetingJoinPhase;
|
|
32
|
+
triggeredTime?: string;
|
|
33
|
+
emailInput?: ClientEmailInput;
|
|
34
|
+
userNameInput?: ClientUserNameInput;
|
|
28
35
|
};
|
|
29
36
|
export type SubmitMQEOptions = {
|
|
30
37
|
meetingId: string;
|
|
@@ -129,6 +136,10 @@ export type SubmitOperationalEvent = (args: {
|
|
|
129
136
|
name: OperationalEvent['metricName'];
|
|
130
137
|
payload: EventPayload;
|
|
131
138
|
}) => void;
|
|
139
|
+
export type SubmitBusinessEvent = (args: {
|
|
140
|
+
name: OperationalEvent['metricName'];
|
|
141
|
+
payload: EventPayload;
|
|
142
|
+
}) => void;
|
|
132
143
|
export type SubmitMQE = (args: {
|
|
133
144
|
name: MediaQualityEvent['name'];
|
|
134
145
|
payload: SubmitMQEPayload;
|
|
@@ -154,4 +165,9 @@ export interface IMetricsAttributes {
|
|
|
154
165
|
meetingId?: string;
|
|
155
166
|
callId?: string;
|
|
156
167
|
}
|
|
168
|
+
export interface DelayedClientEvent {
|
|
169
|
+
name: ClientEvent['name'];
|
|
170
|
+
payload?: RecursivePartial<ClientEvent['payload']>;
|
|
171
|
+
options?: SubmitClientEventOptions;
|
|
172
|
+
}
|
|
157
173
|
export {};
|
|
@@ -18,6 +18,10 @@ declare class Metrics extends WebexPlugin {
|
|
|
18
18
|
operationalMetrics: OperationalMetrics;
|
|
19
19
|
businessMetrics: BusinessMetrics;
|
|
20
20
|
isReady: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Whether or not to delay the submission of client events.
|
|
23
|
+
*/
|
|
24
|
+
delaySubmitClientEvents: boolean;
|
|
21
25
|
/**
|
|
22
26
|
* Constructor
|
|
23
27
|
* @param args
|
|
@@ -60,7 +64,7 @@ declare class Metrics extends WebexPlugin {
|
|
|
60
64
|
*/
|
|
61
65
|
isReadyToSubmitOperationalEvents(): boolean;
|
|
62
66
|
/**
|
|
63
|
-
* @returns true once we have the deviceId we need to submit
|
|
67
|
+
* @returns true once we have the deviceId we need to submit business events
|
|
64
68
|
*/
|
|
65
69
|
isReadyToSubmitBusinessEvents(): boolean;
|
|
66
70
|
/**
|
|
@@ -83,13 +87,14 @@ declare class Metrics extends WebexPlugin {
|
|
|
83
87
|
payload?: EventPayload;
|
|
84
88
|
}): void | Promise<void>;
|
|
85
89
|
/**
|
|
86
|
-
*
|
|
90
|
+
* Business event
|
|
87
91
|
* @param args
|
|
88
92
|
*/
|
|
89
|
-
submitBusinessEvent({ name, payload, table, }: {
|
|
93
|
+
submitBusinessEvent({ name, payload, table, metadata, }: {
|
|
90
94
|
name: string;
|
|
91
95
|
payload: EventPayload;
|
|
92
96
|
table?: Table;
|
|
97
|
+
metadata?: EventPayload;
|
|
93
98
|
}): Promise<void>;
|
|
94
99
|
/**
|
|
95
100
|
* Call Analyzer: Media Quality Event
|
|
@@ -169,5 +174,12 @@ declare class Metrics extends WebexPlugin {
|
|
|
169
174
|
* @returns {boolean}
|
|
170
175
|
*/
|
|
171
176
|
isServiceErrorExpected(serviceErrorCode: number): boolean;
|
|
177
|
+
/**
|
|
178
|
+
* Sets the value of delaySubmitClientEvents. If set to true, client events will be delayed until submitDelayedClientEvents is called. If
|
|
179
|
+
* set to false, delayed client events will be submitted.
|
|
180
|
+
*
|
|
181
|
+
* @param {boolean} shouldDelay - A boolean value indicating whether to delay the submission of client events.
|
|
182
|
+
*/
|
|
183
|
+
setDelaySubmitClientEvents(shouldDelay: boolean): Promise<any[]> | Promise<void>;
|
|
172
184
|
}
|
|
173
185
|
export default Metrics;
|
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.
|
|
30
|
-
"@webex/test-helper-mocha": "3.
|
|
31
|
-
"@webex/test-helper-mock-webex": "3.
|
|
32
|
-
"@webex/test-helper-test-users": "3.
|
|
29
|
+
"@webex/test-helper-chai": "3.8.0-next.10",
|
|
30
|
+
"@webex/test-helper-mocha": "3.8.0-next.10",
|
|
31
|
+
"@webex/test-helper-mock-webex": "3.8.0-next.10",
|
|
32
|
+
"@webex/test-helper-test-users": "3.8.0-next.10",
|
|
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.
|
|
39
|
-
"@webex/common-timers": "3.
|
|
40
|
-
"@webex/event-dictionary-ts": "^1.0.
|
|
41
|
-
"@webex/internal-plugin-metrics": "3.
|
|
42
|
-
"@webex/test-helper-chai": "3.
|
|
43
|
-
"@webex/test-helper-mock-webex": "3.
|
|
44
|
-
"@webex/webex-core": "3.
|
|
38
|
+
"@webex/common": "3.8.0-next.10",
|
|
39
|
+
"@webex/common-timers": "3.8.0-next.10",
|
|
40
|
+
"@webex/event-dictionary-ts": "^1.0.1688",
|
|
41
|
+
"@webex/internal-plugin-metrics": "3.8.0-next.10",
|
|
42
|
+
"@webex/test-helper-chai": "3.8.0-next.10",
|
|
43
|
+
"@webex/test-helper-mock-webex": "3.8.0-next.10",
|
|
44
|
+
"@webex/webex-core": "3.8.0-next.10",
|
|
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.
|
|
57
|
+
"version": "3.8.0-next.10"
|
|
58
58
|
}
|
package/src/business-metrics.ts
CHANGED
|
@@ -2,121 +2,111 @@ import GenericMetrics from './generic-metrics';
|
|
|
2
2
|
import {EventPayload, Table} from './metrics.types';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* @description Util class to handle
|
|
5
|
+
* @description Util class to handle Business Metrics
|
|
6
6
|
* @export
|
|
7
7
|
* @class BusinessMetrics
|
|
8
8
|
*/
|
|
9
9
|
export default class BusinessMetrics extends GenericMetrics {
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
* so we have to shim this layer specifically for this
|
|
13
|
-
* https://confluence-eng-gpk2.cisco.com/conf/display/WAP/Table+wbxapp_callend_metrics
|
|
14
|
-
* @param {EventPayload} payload payload of the metric
|
|
15
|
-
* @returns {Promise<any>}
|
|
16
|
-
*/
|
|
17
|
-
private submitCallEndEvent({payload}: {payload: EventPayload}) {
|
|
18
|
-
const event = {
|
|
19
|
-
type: ['business'],
|
|
20
|
-
eventPayload: {
|
|
21
|
-
key: 'callEnd',
|
|
22
|
-
client_timestamp: new Date().toISOString(),
|
|
23
|
-
appType: 'Web Client',
|
|
24
|
-
value: {
|
|
25
|
-
...payload,
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
return this.submitEvent({
|
|
31
|
-
kind: 'buisness-events:wbxapp_callend_metrics -> ',
|
|
32
|
-
name: 'wbxapp_callend_metrics',
|
|
33
|
-
event,
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Submit a buisness metric to our metrics endpoint, going to the default business_ucf table
|
|
39
|
-
* all event payload keys are converted into a hex string value
|
|
40
|
-
* unfortunately, the pinot team does not allow changes to the schema of business_metrics
|
|
41
|
-
* so we have to shim this layer specifically for this
|
|
42
|
-
* https://confluence-eng-gpk2.cisco.com/conf/display/WAP/Table%3A+business_metrics
|
|
11
|
+
* Build the metric event to submit.
|
|
43
12
|
* @param {string} name of the metric
|
|
44
|
-
* @param {EventPayload} payload payload of the metric
|
|
45
|
-
* @
|
|
46
|
-
|
|
47
|
-
private submitBusinessMetricsEvent({name, payload}: {name: string; payload: EventPayload}) {
|
|
48
|
-
const event = {
|
|
49
|
-
type: ['business'],
|
|
50
|
-
eventPayload: {
|
|
51
|
-
key: name,
|
|
52
|
-
client_timestamp: new Date().toISOString(),
|
|
53
|
-
appType: 'Web Client',
|
|
54
|
-
value: {
|
|
55
|
-
...this.getContext(),
|
|
56
|
-
...this.getBrowserDetails(),
|
|
57
|
-
...payload,
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
return this.submitEvent({kind: 'buisness-events:business_metrics -> ', name, event});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Submit a buisness metric to our metrics endpoint, going to the default business_ucf table
|
|
67
|
-
* all event payload keys are converted into a hex string value
|
|
68
|
-
* https://confluence-eng-gpk2.cisco.com/conf/display/WAP/Business+metrics++-%3E+ROMA
|
|
69
|
-
* @param {string} name of the metric
|
|
70
|
-
* @param {EventPayload} user payload of the metric
|
|
71
|
-
* @returns {Promise<any>}
|
|
13
|
+
* @param {EventPayload} payload user payload of the metric
|
|
14
|
+
* @param {EventPayload} metadata to include outside of eventPayload.value
|
|
15
|
+
* @returns {MetricEvent} The constructed metric event
|
|
72
16
|
*/
|
|
73
|
-
private
|
|
74
|
-
|
|
17
|
+
private buildEvent({name, payload, metadata}: {name: string; payload: object; metadata: object}) {
|
|
18
|
+
return {
|
|
75
19
|
type: ['business'],
|
|
76
20
|
eventPayload: {
|
|
77
21
|
key: name,
|
|
78
|
-
appType: 'Web Client',
|
|
79
22
|
client_timestamp: new Date().toISOString(),
|
|
80
|
-
|
|
81
|
-
browserDetails: this.getBrowserDetails(),
|
|
23
|
+
...metadata,
|
|
82
24
|
value: payload,
|
|
83
25
|
},
|
|
84
26
|
};
|
|
85
|
-
|
|
86
|
-
return this.submitEvent({kind: 'buisness-events:default -> ', name, event});
|
|
87
27
|
}
|
|
88
28
|
|
|
89
29
|
/**
|
|
90
|
-
* Submit a
|
|
30
|
+
* Submit a business metric to our metrics endpoint.
|
|
91
31
|
* routes to the correct table with the correct schema payload by table
|
|
92
32
|
* https://confluence-eng-gpk2.cisco.com/conf/display/WAP/Business+metrics++-%3E+ROMA
|
|
93
33
|
* @param {string} name of the metric, ignored if going to wbxapp_callend_metrics
|
|
94
34
|
* @param {EventPayload} payload user payload of the metric
|
|
95
35
|
* @param {Table} table optional - to submit the metric to and adapt the sent schema
|
|
36
|
+
* @param {EventPayload} metadata optional - to include outside of eventPayload.value
|
|
96
37
|
* @returns {Promise<any>}
|
|
97
38
|
*/
|
|
98
39
|
public submitBusinessEvent({
|
|
99
40
|
name,
|
|
100
41
|
payload,
|
|
101
42
|
table,
|
|
43
|
+
metadata,
|
|
102
44
|
}: {
|
|
103
45
|
name: string;
|
|
104
46
|
payload: EventPayload;
|
|
105
47
|
table?: Table;
|
|
48
|
+
metadata?: EventPayload;
|
|
106
49
|
}): Promise<void> {
|
|
107
50
|
if (!table) {
|
|
108
51
|
table = 'default';
|
|
109
52
|
}
|
|
53
|
+
if (!metadata) {
|
|
54
|
+
metadata = {};
|
|
55
|
+
}
|
|
56
|
+
if (!metadata.appType) {
|
|
57
|
+
metadata.appType = 'Web Client';
|
|
58
|
+
}
|
|
110
59
|
switch (table) {
|
|
111
|
-
case 'wbxapp_callend_metrics':
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
60
|
+
case 'wbxapp_callend_metrics': {
|
|
61
|
+
// https://confluence-eng-gpk2.cisco.com/conf/display/WAP/Table+wbxapp_callend_metrics
|
|
62
|
+
const callEndEvent = this.buildEvent({name: 'callEnd', payload, metadata});
|
|
63
|
+
|
|
64
|
+
return this.submitEvent({
|
|
65
|
+
kind: 'business-events:wbxapp_callend_metrics -> ',
|
|
66
|
+
name: 'wbxapp_callend_metrics',
|
|
67
|
+
event: callEndEvent,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
case 'business_metrics': {
|
|
72
|
+
// all event payload keys are converted into a hex string value
|
|
73
|
+
// unfortunately, the pinot team does not allow changes to the schema of business_metrics
|
|
74
|
+
// so we have to shim this layer specifically for this
|
|
75
|
+
// https://confluence-eng-gpk2.cisco.com/conf/display/WAP/Table%3A+business_metrics
|
|
76
|
+
const businessEvent = this.buildEvent({
|
|
77
|
+
name,
|
|
78
|
+
payload: {
|
|
79
|
+
...this.getContext(),
|
|
80
|
+
...this.getBrowserDetails(),
|
|
81
|
+
...payload,
|
|
82
|
+
},
|
|
83
|
+
metadata,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return this.submitEvent({
|
|
87
|
+
kind: 'business-events:business_metrics -> ',
|
|
88
|
+
name,
|
|
89
|
+
event: businessEvent,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
115
93
|
case 'business_ucf':
|
|
116
|
-
return this.submitDefaultEvent({name, payload});
|
|
117
94
|
case 'default':
|
|
118
|
-
default:
|
|
119
|
-
|
|
95
|
+
default: {
|
|
96
|
+
// all event payload keys are converted into a hex string value
|
|
97
|
+
// https://confluence-eng-gpk2.cisco.com/conf/display/WAP/Business+metrics++-%3E+ROMA
|
|
98
|
+
const defaultEvent = this.buildEvent({
|
|
99
|
+
name,
|
|
100
|
+
payload,
|
|
101
|
+
metadata: {
|
|
102
|
+
context: this.getContext(),
|
|
103
|
+
browserDetails: this.getBrowserDetails(),
|
|
104
|
+
...metadata,
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
return this.submitEvent({kind: 'business-events:default -> ', name, event: defaultEvent});
|
|
109
|
+
}
|
|
120
110
|
}
|
|
121
111
|
}
|
|
122
112
|
}
|
|
@@ -83,11 +83,16 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
83
83
|
key === 'client.media.rx.start' ||
|
|
84
84
|
key === 'client.media.tx.start' ||
|
|
85
85
|
key === 'internal.client.meetinginfo.request' ||
|
|
86
|
-
key === 'internal.client.meetinginfo.response'
|
|
86
|
+
key === 'internal.client.meetinginfo.response' ||
|
|
87
|
+
key === 'client.media-engine.remote-sdp-received'
|
|
87
88
|
) {
|
|
88
89
|
this.saveFirstTimestampOnly(key, value);
|
|
89
90
|
} else {
|
|
90
91
|
this.latencyTimestamps.set(key, value);
|
|
92
|
+
// new offer/answer so reset the remote SDP timestamp
|
|
93
|
+
if (key === 'client.media-engine.local-sdp-generated') {
|
|
94
|
+
this.latencyTimestamps.delete('client.media-engine.remote-sdp-received');
|
|
95
|
+
}
|
|
91
96
|
}
|
|
92
97
|
}
|
|
93
98
|
|
|
@@ -146,7 +151,8 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
146
151
|
public getDiffBetweenTimestamps(a: MetricEventNames, b: MetricEventNames) {
|
|
147
152
|
const start = this.latencyTimestamps.get(a);
|
|
148
153
|
const end = this.latencyTimestamps.get(b);
|
|
149
|
-
|
|
154
|
+
|
|
155
|
+
if (typeof start === 'number' && typeof end === 'number') {
|
|
150
156
|
return end - start;
|
|
151
157
|
}
|
|
152
158
|
|
|
@@ -188,7 +194,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
188
194
|
public getU2CTime() {
|
|
189
195
|
const u2cLatency = this.precomputedLatencies.get('internal.get.u2c.time');
|
|
190
196
|
|
|
191
|
-
return u2cLatency ? Math.floor(u2cLatency) : undefined;
|
|
197
|
+
return typeof u2cLatency === 'number' ? Math.floor(u2cLatency) : undefined;
|
|
192
198
|
}
|
|
193
199
|
|
|
194
200
|
/**
|
|
@@ -291,7 +297,9 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
291
297
|
* @returns - latency
|
|
292
298
|
*/
|
|
293
299
|
public getPageJMT() {
|
|
294
|
-
|
|
300
|
+
const latency = this.precomputedLatencies.get('internal.client.pageJMT');
|
|
301
|
+
|
|
302
|
+
return typeof latency === 'number' ? latency : undefined;
|
|
295
303
|
}
|
|
296
304
|
|
|
297
305
|
/**
|
|
@@ -299,7 +307,9 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
299
307
|
* @returns - latency
|
|
300
308
|
*/
|
|
301
309
|
public getDownloadTimeJMT() {
|
|
302
|
-
|
|
310
|
+
const latency = this.precomputedLatencies.get('internal.download.time');
|
|
311
|
+
|
|
312
|
+
return typeof latency === 'number' ? latency : undefined;
|
|
303
313
|
}
|
|
304
314
|
|
|
305
315
|
/**
|
|
@@ -315,8 +325,15 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
315
325
|
);
|
|
316
326
|
}
|
|
317
327
|
|
|
318
|
-
|
|
319
|
-
|
|
328
|
+
const clickToInterstitialLatency = this.precomputedLatencies.get(
|
|
329
|
+
'internal.click.to.interstitial'
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
if (typeof clickToInterstitialLatency === 'number') {
|
|
333
|
+
return clickToInterstitialLatency;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return undefined;
|
|
320
337
|
}
|
|
321
338
|
|
|
322
339
|
/**
|
|
@@ -353,7 +370,8 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
353
370
|
// get the first timestamp
|
|
354
371
|
const connectedMedia = this.latencyTimestamps.get('client.ice.end');
|
|
355
372
|
|
|
356
|
-
const
|
|
373
|
+
const lobbyTimeLatency = this.getStayLobbyTime();
|
|
374
|
+
const lobbyTime = typeof lobbyTimeLatency === 'number' ? lobbyTimeLatency : 0;
|
|
357
375
|
|
|
358
376
|
if (interstitialJoinClickTimestamp && connectedMedia) {
|
|
359
377
|
return connectedMedia - interstitialJoinClickTimestamp - lobbyTime;
|
|
@@ -370,7 +388,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
370
388
|
const clickToInterstitial = this.getClickToInterstitial();
|
|
371
389
|
const interstitialToJoinOk = this.getInterstitialToJoinOK();
|
|
372
390
|
|
|
373
|
-
if (clickToInterstitial && interstitialToJoinOk) {
|
|
391
|
+
if (typeof clickToInterstitial === 'number' && typeof interstitialToJoinOk === 'number') {
|
|
374
392
|
return clickToInterstitial + interstitialToJoinOk;
|
|
375
393
|
}
|
|
376
394
|
|
|
@@ -422,7 +440,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
422
440
|
const interstitialToJoinOk = this.getInterstitialToJoinOK();
|
|
423
441
|
const joinConfJMT = this.getJoinConfJMT();
|
|
424
442
|
|
|
425
|
-
if (interstitialToJoinOk && joinConfJMT) {
|
|
443
|
+
if (typeof interstitialToJoinOk === 'number' && typeof joinConfJMT === 'number') {
|
|
426
444
|
return interstitialToJoinOk - joinConfJMT;
|
|
427
445
|
}
|
|
428
446
|
|
|
@@ -449,7 +467,9 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
449
467
|
public getReachabilityClustersReqResp() {
|
|
450
468
|
const reachablityClusterReqResp = this.precomputedLatencies.get('internal.get.cluster.time');
|
|
451
469
|
|
|
452
|
-
return
|
|
470
|
+
return typeof reachablityClusterReqResp === 'number'
|
|
471
|
+
? Math.floor(reachablityClusterReqResp)
|
|
472
|
+
: undefined;
|
|
453
473
|
}
|
|
454
474
|
|
|
455
475
|
/**
|
|
@@ -472,7 +492,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
472
492
|
public getExchangeCITokenJMT() {
|
|
473
493
|
const exchangeCITokenJMT = this.precomputedLatencies.get('internal.exchange.ci.token.time');
|
|
474
494
|
|
|
475
|
-
return exchangeCITokenJMT ? Math.floor(exchangeCITokenJMT) : undefined;
|
|
495
|
+
return typeof exchangeCITokenJMT === 'number' ? Math.floor(exchangeCITokenJMT) : undefined;
|
|
476
496
|
}
|
|
477
497
|
|
|
478
498
|
/**
|
|
@@ -481,7 +501,9 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
481
501
|
public getRefreshCaptchaReqResp() {
|
|
482
502
|
const refreshCaptchaReqResp = this.precomputedLatencies.get('internal.refresh.captcha.time');
|
|
483
503
|
|
|
484
|
-
return
|
|
504
|
+
return typeof refreshCaptchaReqResp === 'number'
|
|
505
|
+
? Math.floor(refreshCaptchaReqResp)
|
|
506
|
+
: undefined;
|
|
485
507
|
}
|
|
486
508
|
|
|
487
509
|
/**
|
|
@@ -493,7 +515,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
493
515
|
'internal.api.fetch.intelligence.models'
|
|
494
516
|
);
|
|
495
517
|
|
|
496
|
-
return downloadIntelligenceModelsReqResp
|
|
518
|
+
return typeof downloadIntelligenceModelsReqResp === 'number'
|
|
497
519
|
? Math.floor(downloadIntelligenceModelsReqResp)
|
|
498
520
|
: undefined;
|
|
499
521
|
}
|