@webex/internal-plugin-metrics 3.3.1 → 3.4.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.
- package/dist/behavioral-metrics.js +63 -0
- package/dist/behavioral-metrics.js.map +1 -0
- package/dist/business-metrics.js +62 -0
- package/dist/business-metrics.js.map +1 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.js +3 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js +14 -11
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
- package/dist/call-diagnostic/config.js +19 -13
- package/dist/call-diagnostic/config.js.map +1 -1
- package/dist/generic-metrics.js +184 -0
- package/dist/generic-metrics.js.map +1 -0
- package/dist/index.js +21 -0
- 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 +116 -23
- package/dist/new-metrics.js.map +1 -1
- package/dist/operational-metrics.js +56 -0
- package/dist/operational-metrics.js.map +1 -0
- package/dist/types/behavioral-metrics.d.ts +25 -0
- package/dist/types/business-metrics.d.ts +19 -0
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +2 -2
- package/dist/types/call-diagnostic/call-diagnostic-metrics.util.d.ts +3 -2
- package/dist/types/call-diagnostic/config.d.ts +2 -0
- package/dist/types/generic-metrics.d.ts +63 -0
- package/dist/types/index.d.ts +4 -1
- package/dist/types/metrics.types.d.ts +47 -15
- package/dist/types/new-metrics.d.ts +39 -11
- package/dist/types/operational-metrics.d.ts +19 -0
- package/package.json +11 -11
- package/src/behavioral-metrics.ts +40 -0
- package/src/business-metrics.ts +30 -0
- package/src/call-diagnostic/call-diagnostic-metrics.ts +3 -0
- package/src/call-diagnostic/call-diagnostic-metrics.util.ts +16 -17
- package/src/call-diagnostic/config.ts +9 -2
- package/src/generic-metrics.ts +146 -0
- package/src/index.ts +6 -0
- package/src/metrics.types.ts +82 -18
- package/src/new-metrics.ts +95 -18
- package/src/operational-metrics.ts +24 -0
- package/test/unit/spec/behavioral/behavioral-metrics.ts +205 -0
- package/test/unit/spec/business/business-metrics.ts +120 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts +48 -52
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +1 -1
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +9 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.util.ts +41 -22
- package/test/unit/spec/operational/operational-metrics.ts +115 -0
- package/test/unit/spec/prelogin-metrics-batcher.ts +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _Reflect$construct = require("@babel/runtime-corejs2/core-js/reflect/construct");
|
|
4
|
+
var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
|
|
5
|
+
var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
|
|
6
|
+
_Object$defineProperty(exports, "__esModule", {
|
|
7
|
+
value: true
|
|
8
|
+
});
|
|
9
|
+
exports.default = void 0;
|
|
10
|
+
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
|
|
11
|
+
var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
|
|
12
|
+
var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/inherits"));
|
|
13
|
+
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/possibleConstructorReturn"));
|
|
14
|
+
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/getPrototypeOf"));
|
|
15
|
+
var _genericMetrics = _interopRequireDefault(require("./generic-metrics"));
|
|
16
|
+
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = _Reflect$construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
|
|
17
|
+
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !_Reflect$construct) return false; if (_Reflect$construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
18
|
+
/**
|
|
19
|
+
* @description Util class to handle Operational Metrics
|
|
20
|
+
* @export
|
|
21
|
+
* @class OperationalMetrics
|
|
22
|
+
*/
|
|
23
|
+
var OperationalMetrics = exports.default = /*#__PURE__*/function (_GenericMetrics) {
|
|
24
|
+
(0, _inherits2.default)(OperationalMetrics, _GenericMetrics);
|
|
25
|
+
var _super = _createSuper(OperationalMetrics);
|
|
26
|
+
function OperationalMetrics() {
|
|
27
|
+
(0, _classCallCheck2.default)(this, OperationalMetrics);
|
|
28
|
+
return _super.apply(this, arguments);
|
|
29
|
+
}
|
|
30
|
+
(0, _createClass2.default)(OperationalMetrics, [{
|
|
31
|
+
key: "submitOperationalEvent",
|
|
32
|
+
value:
|
|
33
|
+
/**
|
|
34
|
+
* Submit an operational metric to our metrics endpoint.
|
|
35
|
+
* @param {string} name of the metric
|
|
36
|
+
* @param {EventPayload} user payload of the metric
|
|
37
|
+
* @returns {Promise<any>}
|
|
38
|
+
*/
|
|
39
|
+
function submitOperationalEvent(_ref) {
|
|
40
|
+
var name = _ref.name,
|
|
41
|
+
payload = _ref.payload;
|
|
42
|
+
var event = this.createTaggedEventObject({
|
|
43
|
+
type: ['operational'],
|
|
44
|
+
name: name,
|
|
45
|
+
payload: payload
|
|
46
|
+
});
|
|
47
|
+
this.submitEvent({
|
|
48
|
+
kind: 'operational-events -> ',
|
|
49
|
+
name: name,
|
|
50
|
+
event: event
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}]);
|
|
54
|
+
return OperationalMetrics;
|
|
55
|
+
}(_genericMetrics.default);
|
|
56
|
+
//# sourceMappingURL=operational-metrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_genericMetrics","_interopRequireDefault","require","_createSuper","Derived","hasNativeReflectConstruct","_isNativeReflectConstruct","_createSuperInternal","Super","_getPrototypeOf2","default","result","NewTarget","constructor","_Reflect$construct","arguments","apply","_possibleConstructorReturn2","Reflect","sham","Proxy","Boolean","prototype","valueOf","call","e","OperationalMetrics","exports","_GenericMetrics","_inherits2","_super","_classCallCheck2","_createClass2","key","value","submitOperationalEvent","_ref","name","payload","event","createTaggedEventObject","type","submitEvent","kind","GenericMetrics"],"sources":["operational-metrics.ts"],"sourcesContent":["import GenericMetrics from './generic-metrics';\nimport {EventPayload} from './metrics.types';\n\n/**\n * @description Util class to handle Operational Metrics\n * @export\n * @class OperationalMetrics\n */\nexport default class OperationalMetrics extends GenericMetrics {\n /**\n * Submit an operational metric to our metrics endpoint.\n * @param {string} name of the metric\n * @param {EventPayload} user payload of the metric\n * @returns {Promise<any>}\n */\n public submitOperationalEvent({name, payload}: {name: string; payload: EventPayload}) {\n const event = this.createTaggedEventObject({\n type: ['operational'],\n name,\n payload,\n });\n this.submitEvent({kind: 'operational-events -> ', name, event});\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAAA,IAAAA,eAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA+C,SAAAC,aAAAC,OAAA,QAAAC,yBAAA,GAAAC,yBAAA,oBAAAC,qBAAA,QAAAC,KAAA,OAAAC,gBAAA,CAAAC,OAAA,EAAAN,OAAA,GAAAO,MAAA,MAAAN,yBAAA,QAAAO,SAAA,OAAAH,gBAAA,CAAAC,OAAA,QAAAG,WAAA,EAAAF,MAAA,GAAAG,kBAAA,CAAAN,KAAA,EAAAO,SAAA,EAAAH,SAAA,YAAAD,MAAA,GAAAH,KAAA,CAAAQ,KAAA,OAAAD,SAAA,gBAAAE,2BAAA,CAAAP,OAAA,QAAAC,MAAA;AAAA,SAAAL,0BAAA,eAAAY,OAAA,qBAAAJ,kBAAA,oBAAAA,kBAAA,CAAAK,IAAA,2BAAAC,KAAA,oCAAAC,OAAA,CAAAC,SAAA,CAAAC,OAAA,CAAAC,IAAA,CAAAV,kBAAA,CAAAO,OAAA,8CAAAI,CAAA;AAG/C;AACA;AACA;AACA;AACA;AAJA,IAKqBC,kBAAkB,GAAAC,OAAA,CAAAjB,OAAA,0BAAAkB,eAAA;EAAA,IAAAC,UAAA,CAAAnB,OAAA,EAAAgB,kBAAA,EAAAE,eAAA;EAAA,IAAAE,MAAA,GAAA3B,YAAA,CAAAuB,kBAAA;EAAA,SAAAA,mBAAA;IAAA,IAAAK,gBAAA,CAAArB,OAAA,QAAAgB,kBAAA;IAAA,OAAAI,MAAA,CAAAd,KAAA,OAAAD,SAAA;EAAA;EAAA,IAAAiB,aAAA,CAAAtB,OAAA,EAAAgB,kBAAA;IAAAO,GAAA;IAAAC,KAAA;IACrC;AACF;AACA;AACA;AACA;AACA;IACE,SAAAC,uBAAAC,IAAA,EAAsF;MAAA,IAAvDC,IAAI,GAAAD,IAAA,CAAJC,IAAI;QAAEC,OAAO,GAAAF,IAAA,CAAPE,OAAO;MAC1C,IAAMC,KAAK,GAAG,IAAI,CAACC,uBAAuB,CAAC;QACzCC,IAAI,EAAE,CAAC,aAAa,CAAC;QACrBJ,IAAI,EAAJA,IAAI;QACJC,OAAO,EAAPA;MACF,CAAC,CAAC;MACF,IAAI,CAACI,WAAW,CAAC;QAACC,IAAI,EAAE,wBAAwB;QAAEN,IAAI,EAAJA,IAAI;QAAEE,KAAK,EAALA;MAAK,CAAC,CAAC;IACjE;EAAC;EAAA,OAAAb,kBAAA;AAAA,EAd6CkB,uBAAc"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { MetricEventProduct, MetricEventAgent, MetricEventVerb, EventPayload } from './metrics.types';
|
|
2
|
+
import GenericMetrics from './generic-metrics';
|
|
3
|
+
/**
|
|
4
|
+
* @description Util class to handle Behavioral Metrics
|
|
5
|
+
* @export
|
|
6
|
+
* @class BehavioralMetrics
|
|
7
|
+
*/
|
|
8
|
+
export default class BehavioralMetrics extends GenericMetrics {
|
|
9
|
+
/**
|
|
10
|
+
* Submit a behavioral metric to our metrics endpoint.
|
|
11
|
+
* @param {MetricEventProduct} product the product from which the metric is being submitted, e.g. 'webex' web client, 'wxcc_desktop'
|
|
12
|
+
* @param {MetricEventAgent} agent the source of the action for this metric
|
|
13
|
+
* @param {string} target the 'thing' that this metric includes information about
|
|
14
|
+
* @param {MetricEventVerb} verb the action that this metric includes information about
|
|
15
|
+
* @param {EventPayload} payload information specific to this event. This should be flat, i.e. it should not include nested objects.
|
|
16
|
+
* @returns {Promise<any>}
|
|
17
|
+
*/
|
|
18
|
+
submitBehavioralEvent({ product, agent, target, verb, payload, }: {
|
|
19
|
+
product: MetricEventProduct;
|
|
20
|
+
agent: MetricEventAgent;
|
|
21
|
+
target: string;
|
|
22
|
+
verb: MetricEventVerb;
|
|
23
|
+
payload?: EventPayload;
|
|
24
|
+
}): void;
|
|
25
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import GenericMetrics from './generic-metrics';
|
|
2
|
+
import { EventPayload } from './metrics.types';
|
|
3
|
+
/**
|
|
4
|
+
* @description Util class to handle Buisness Metrics
|
|
5
|
+
* @export
|
|
6
|
+
* @class BusinessMetrics
|
|
7
|
+
*/
|
|
8
|
+
export default class BusinessMetrics extends GenericMetrics {
|
|
9
|
+
/**
|
|
10
|
+
* Submit a buisness metric to our metrics endpoint.
|
|
11
|
+
* @param {string} name of the metric
|
|
12
|
+
* @param {EventPayload} user payload of the metric
|
|
13
|
+
* @returns {Promise<any>}
|
|
14
|
+
*/
|
|
15
|
+
submitBusinessEvent({ name, payload }: {
|
|
16
|
+
name: string;
|
|
17
|
+
payload: EventPayload;
|
|
18
|
+
}): void;
|
|
19
|
+
}
|
|
@@ -77,7 +77,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
77
77
|
environment?: string;
|
|
78
78
|
newEnvironment?: string;
|
|
79
79
|
clientInfo?: {
|
|
80
|
-
os?: "
|
|
80
|
+
os?: "windows" | "mac" | "ios" | "android" | "chrome" | "linux" | "other" | "android-x64" | "android-arm64" | "uwp-arm64";
|
|
81
81
|
osVersion?: string;
|
|
82
82
|
localIP?: string;
|
|
83
83
|
gatewayIP?: string;
|
|
@@ -336,7 +336,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
336
336
|
*/
|
|
337
337
|
generateClientEventErrorPayload(rawError: any): {
|
|
338
338
|
fatal: boolean;
|
|
339
|
-
category: "
|
|
339
|
+
category: "other" | "signaling" | "media" | "network" | "expected";
|
|
340
340
|
errorDescription?: string;
|
|
341
341
|
errorCode?: number;
|
|
342
342
|
errorCodeStr?: string;
|
|
@@ -96,8 +96,9 @@ export declare const extractVersionMetadata: (version: string) => {
|
|
|
96
96
|
* Generates client error codes for specific ice failures
|
|
97
97
|
* that happen when trying to add media in a meeting.
|
|
98
98
|
*/
|
|
99
|
-
export declare const generateClientErrorCodeForIceFailure: ({ signalingState,
|
|
99
|
+
export declare const generateClientErrorCodeForIceFailure: ({ signalingState, iceConnected, turnServerUsed, unreachable, }: {
|
|
100
100
|
signalingState: RTCPeerConnection['signalingState'];
|
|
101
|
-
|
|
101
|
+
iceConnected: boolean;
|
|
102
102
|
turnServerUsed: boolean;
|
|
103
|
+
unreachable: boolean;
|
|
103
104
|
}) => number;
|
|
@@ -10,6 +10,7 @@ export declare const MISSING_ROAP_ANSWER_CLIENT_CODE = 2007;
|
|
|
10
10
|
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
|
+
export declare const ICE_AND_REACHABILITY_FAILED_CLIENT_CODE = 2011;
|
|
13
14
|
export declare const WBX_APP_API_URL = "wbxappapi";
|
|
14
15
|
export declare const WEBEX_SUB_SERVICE_TYPES: Record<string, ClientSubServiceType>;
|
|
15
16
|
export declare const BROWSER_MEDIA_ERROR_NAME_TO_CLIENT_ERROR_CODES_MAP: {
|
|
@@ -92,6 +93,7 @@ export declare const ERROR_DESCRIPTIONS: {
|
|
|
92
93
|
DTLS_HANDSHAKE_FAILED: string;
|
|
93
94
|
ICE_FAILED_WITHOUT_TURN_TLS: string;
|
|
94
95
|
ICE_FAILED_WITH_TURN_TLS: string;
|
|
96
|
+
ICE_AND_REACHABILITY_FAILED: string;
|
|
95
97
|
SDP_OFFER_CREATION_ERROR: string;
|
|
96
98
|
SDP_OFFER_CREATION_ERROR_MISSING_CODEC: string;
|
|
97
99
|
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { StatelessWebexPlugin } from '@webex/webex-core';
|
|
2
|
+
import { DeviceContext, TaggedEvent, EventPayload, MetricType } from './metrics.types';
|
|
3
|
+
/**
|
|
4
|
+
* @description top-level abstract class to handle Metrics and common routines.
|
|
5
|
+
* @export
|
|
6
|
+
* @class GenericMetrics
|
|
7
|
+
*/
|
|
8
|
+
export default abstract class GenericMetrics extends StatelessWebexPlugin {
|
|
9
|
+
private clientMetricsBatcher;
|
|
10
|
+
private logger;
|
|
11
|
+
private device;
|
|
12
|
+
private version;
|
|
13
|
+
private deviceId;
|
|
14
|
+
/**
|
|
15
|
+
* Constructor
|
|
16
|
+
* @param {any[]} args
|
|
17
|
+
*/
|
|
18
|
+
constructor(...args: any[]);
|
|
19
|
+
/**
|
|
20
|
+
* Submit a buisness metric to our metrics endpoint.
|
|
21
|
+
* @param {string} kind of metric for logging
|
|
22
|
+
* @param {string} name of the metric
|
|
23
|
+
* @param {object} event
|
|
24
|
+
* @returns {Promise<any>}
|
|
25
|
+
*/
|
|
26
|
+
protected submitEvent({ kind, name, event }: {
|
|
27
|
+
kind: string;
|
|
28
|
+
name: string;
|
|
29
|
+
event: object;
|
|
30
|
+
}): any;
|
|
31
|
+
/**
|
|
32
|
+
* Returns the deviceId from our registration with WDM.
|
|
33
|
+
* @returns {string} deviceId or empty string
|
|
34
|
+
*/
|
|
35
|
+
protected getDeviceId(): string;
|
|
36
|
+
/**
|
|
37
|
+
* Returns the context object to be submitted with all metrics.
|
|
38
|
+
* @returns {DeviceContext}
|
|
39
|
+
*/
|
|
40
|
+
protected getContext(): DeviceContext;
|
|
41
|
+
/**
|
|
42
|
+
* Returns the browser details to be included with all metrics.
|
|
43
|
+
* @returns {object}
|
|
44
|
+
*/
|
|
45
|
+
protected getBrowserDetails(): object;
|
|
46
|
+
/**
|
|
47
|
+
* Returns true once we have the deviceId we need to submit behavioral/operational/buisness events
|
|
48
|
+
* @returns {boolean}
|
|
49
|
+
*/
|
|
50
|
+
isReadyToSubmitEvents(): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Creates the object to send to our metrics endpoint for a tagged event (i.e. behavoral or operational)
|
|
53
|
+
* @param {[MetricType]} list of event type (i.e. ['behavioral'], ['operational', 'behavioral'])
|
|
54
|
+
* @param {string} metric name
|
|
55
|
+
* @param {EventPayload} user payload
|
|
56
|
+
* @returns {EventPayload}
|
|
57
|
+
*/
|
|
58
|
+
protected createTaggedEventObject({ type, name, payload, }: {
|
|
59
|
+
type: [MetricType];
|
|
60
|
+
name: string;
|
|
61
|
+
payload: EventPayload;
|
|
62
|
+
}): TaggedEvent;
|
|
63
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -9,6 +9,9 @@ import * as CALL_DIAGNOSTIC_CONFIG from './call-diagnostic/config';
|
|
|
9
9
|
import * as CallDiagnosticUtils from './call-diagnostic/call-diagnostic-metrics.util';
|
|
10
10
|
import CallDiagnosticMetrics from './call-diagnostic/call-diagnostic-metrics';
|
|
11
11
|
import CallDiagnosticLatencies from './call-diagnostic/call-diagnostic-metrics-latencies';
|
|
12
|
+
import BehavioralMetrics from './behavioral-metrics';
|
|
13
|
+
import OperationalMetrics from './operational-metrics';
|
|
14
|
+
import BusinessMetrics from './business-metrics';
|
|
12
15
|
export { default, getOSNameInternal } from './metrics';
|
|
13
|
-
export { config, CALL_DIAGNOSTIC_CONFIG, NewMetrics, Utils, CallDiagnosticUtils, CallDiagnosticLatencies, CallDiagnosticMetrics, };
|
|
16
|
+
export { config, CALL_DIAGNOSTIC_CONFIG, NewMetrics, Utils, CallDiagnosticUtils, CallDiagnosticLatencies, CallDiagnosticMetrics, BehavioralMetrics, OperationalMetrics, BusinessMetrics, };
|
|
14
17
|
export type { ClientEvent, ClientEventLeaveReason, SubmitBehavioralEvent, SubmitClientEvent, SubmitInternalEvent, SubmitMQE, SubmitOperationalEvent, PreComputedLatencies, };
|
|
@@ -7,6 +7,9 @@ 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
9
|
export type BrowserLaunchMethodType = NonNullable<RawEvent['origin']['clientInfo']>['browserLaunchMethod'];
|
|
10
|
+
export type MetricEventProduct = 'webex' | 'wxcc_desktop';
|
|
11
|
+
export type MetricEventAgent = 'user' | 'browser' | 'system' | 'sdk' | 'redux' | 'service';
|
|
12
|
+
export type MetricEventVerb = 'create' | 'get' | 'fetch' | 'update' | 'list' | 'delete' | 'select' | 'view' | 'set' | 'toggle' | 'load' | 'reload' | 'click' | 'hover' | 'register' | 'unregister' | 'enable' | 'disable' | 'use' | 'complete' | 'submit' | 'apply' | 'cancel' | 'abort' | 'sync' | 'login' | 'logout' | 'answer' | 'activate' | 'deactivate';
|
|
10
13
|
export type SubmitClientEventOptions = {
|
|
11
14
|
meetingId?: string;
|
|
12
15
|
mediaConnections?: any[];
|
|
@@ -37,16 +40,43 @@ export interface ClientEvent {
|
|
|
37
40
|
payload?: RawClientEvent;
|
|
38
41
|
options?: SubmitClientEventOptions;
|
|
39
42
|
}
|
|
40
|
-
export interface
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
export interface DeviceContext {
|
|
44
|
+
app: {
|
|
45
|
+
version: string;
|
|
46
|
+
};
|
|
47
|
+
device: {
|
|
48
|
+
id: string;
|
|
49
|
+
};
|
|
50
|
+
locale: string;
|
|
51
|
+
os: {
|
|
52
|
+
name: string;
|
|
53
|
+
version: string;
|
|
54
|
+
};
|
|
44
55
|
}
|
|
45
|
-
export
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
56
|
+
export type MetricType = 'behavioral' | 'operational' | 'business';
|
|
57
|
+
type InternalEventPayload = string | number | boolean;
|
|
58
|
+
export type EventPayload = Record<string, InternalEventPayload>;
|
|
59
|
+
export type BehavioralEventPayload = EventPayload;
|
|
60
|
+
export interface BusinessEventPayload {
|
|
61
|
+
metricName: string;
|
|
62
|
+
timestamp: number;
|
|
63
|
+
context: DeviceContext;
|
|
64
|
+
browserDetails: EventPayload;
|
|
65
|
+
value: EventPayload;
|
|
49
66
|
}
|
|
67
|
+
export interface BusinessEvent {
|
|
68
|
+
type: string[];
|
|
69
|
+
eventPayload: BusinessEventPayload;
|
|
70
|
+
}
|
|
71
|
+
export interface TaggedEvent {
|
|
72
|
+
context: DeviceContext;
|
|
73
|
+
metricName: string;
|
|
74
|
+
tags: EventPayload;
|
|
75
|
+
timestamp: number;
|
|
76
|
+
type: [MetricType];
|
|
77
|
+
}
|
|
78
|
+
export type BehavioralEvent = TaggedEvent;
|
|
79
|
+
export type OperationalEvent = TaggedEvent;
|
|
50
80
|
export interface FeatureEvent {
|
|
51
81
|
name: never;
|
|
52
82
|
payload?: never;
|
|
@@ -60,7 +90,7 @@ export interface MediaQualityEvent {
|
|
|
60
90
|
export type RecursivePartial<T> = {
|
|
61
91
|
[P in keyof T]?: T[P] extends (infer U)[] ? RecursivePartial<U>[] : T[P] extends object ? RecursivePartial<T[P]> : T[P];
|
|
62
92
|
};
|
|
63
|
-
export type MetricEventNames = InternalEvent['name'] | ClientEvent['name'] | BehavioralEvent['
|
|
93
|
+
export type MetricEventNames = InternalEvent['name'] | ClientEvent['name'] | BehavioralEvent['metricName'] | OperationalEvent['metricName'] | BusinessEvent['eventPayload']['metricName'] | FeatureEvent['name'] | MediaQualityEvent['name'];
|
|
64
94
|
export type ClientInfo = NonNullable<RawEvent['origin']['clientInfo']>;
|
|
65
95
|
export type ClientType = NonNullable<RawEvent['origin']['clientInfo']>['clientType'];
|
|
66
96
|
export type SubClientType = NonNullable<RawEvent['origin']['clientInfo']>['subClientType'];
|
|
@@ -80,9 +110,11 @@ export type SubmitInternalEvent = (args: {
|
|
|
80
110
|
options?: any;
|
|
81
111
|
}) => void;
|
|
82
112
|
export type SubmitBehavioralEvent = (args: {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
113
|
+
product: MetricEventProduct;
|
|
114
|
+
agent: MetricEventAgent;
|
|
115
|
+
target: string;
|
|
116
|
+
verb: MetricEventVerb;
|
|
117
|
+
payload?: EventPayload;
|
|
86
118
|
}) => void;
|
|
87
119
|
export type SubmitClientEvent = (args: {
|
|
88
120
|
name: ClientEvent['name'];
|
|
@@ -90,9 +122,8 @@ export type SubmitClientEvent = (args: {
|
|
|
90
122
|
options?: SubmitClientEventOptions;
|
|
91
123
|
}) => Promise<any>;
|
|
92
124
|
export type SubmitOperationalEvent = (args: {
|
|
93
|
-
name: OperationalEvent['
|
|
94
|
-
payload
|
|
95
|
-
options?: any;
|
|
125
|
+
name: OperationalEvent['metricName'];
|
|
126
|
+
payload: EventPayload;
|
|
96
127
|
}) => void;
|
|
97
128
|
export type SubmitMQE = (args: {
|
|
98
129
|
name: MediaQualityEvent['name'];
|
|
@@ -105,3 +136,4 @@ export type BuildClientEventFetchRequestOptions = (args: {
|
|
|
105
136
|
options?: SubmitClientEventOptions;
|
|
106
137
|
}) => Promise<any>;
|
|
107
138
|
export type PreComputedLatencies = 'internal.client.pageJMT' | 'internal.download.time' | 'internal.get.cluster.time' | 'internal.click.to.interstitial' | 'internal.refresh.captcha.time' | 'internal.exchange.ci.token.time' | 'internal.get.u2c.time' | 'internal.call.init.join.req' | 'internal.other.app.api.time' | 'internal.api.fetch.intelligence.models';
|
|
139
|
+
export {};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { WebexPlugin } from '@webex/webex-core';
|
|
2
2
|
import CallDiagnosticMetrics from './call-diagnostic/call-diagnostic-metrics';
|
|
3
|
-
import
|
|
3
|
+
import BehavioralMetrics from './behavioral-metrics';
|
|
4
|
+
import OperationalMetrics from './operational-metrics';
|
|
5
|
+
import BusinessMetrics from './business-metrics';
|
|
6
|
+
import { RecursivePartial, MetricEventProduct, MetricEventAgent, MetricEventVerb, ClientEvent, FeatureEvent, EventPayload, MediaQualityEvent, InternalEvent, SubmitClientEventOptions } from './metrics.types';
|
|
4
7
|
import CallDiagnosticLatencies from './call-diagnostic/call-diagnostic-metrics-latencies';
|
|
5
8
|
/**
|
|
6
9
|
* Metrics plugin to centralize all types of metrics.
|
|
@@ -10,6 +13,10 @@ declare class Metrics extends WebexPlugin {
|
|
|
10
13
|
static instance: Metrics;
|
|
11
14
|
callDiagnosticLatencies: CallDiagnosticLatencies;
|
|
12
15
|
callDiagnosticMetrics: CallDiagnosticMetrics;
|
|
16
|
+
behavioralMetrics: BehavioralMetrics;
|
|
17
|
+
operationalMetrics: OperationalMetrics;
|
|
18
|
+
businessMetrics: BusinessMetrics;
|
|
19
|
+
isReady: boolean;
|
|
13
20
|
/**
|
|
14
21
|
* Constructor
|
|
15
22
|
* @param args
|
|
@@ -31,24 +38,45 @@ declare class Metrics extends WebexPlugin {
|
|
|
31
38
|
payload?: RecursivePartial<InternalEvent['payload']>;
|
|
32
39
|
options?: any;
|
|
33
40
|
}): void;
|
|
41
|
+
/**
|
|
42
|
+
* @returns true once we have the deviceId we need to submit behavioral events to Amplitude
|
|
43
|
+
*/
|
|
44
|
+
isReadyToSubmitBehavioralEvents(): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* @returns true once we have the deviceId we need to submit operational events
|
|
47
|
+
*/
|
|
48
|
+
isReadyToSubmitOperationalEvents(): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* @returns true once we have the deviceId we need to submit buisness events
|
|
51
|
+
*/
|
|
52
|
+
isReadyToSubmitBusinessEvents(): boolean;
|
|
34
53
|
/**
|
|
35
54
|
* Behavioral event
|
|
36
55
|
* @param args
|
|
37
56
|
*/
|
|
38
|
-
submitBehavioralEvent({
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
57
|
+
submitBehavioralEvent({ product, agent, target, verb, payload, }: {
|
|
58
|
+
product: MetricEventProduct;
|
|
59
|
+
agent: MetricEventAgent;
|
|
60
|
+
target: string;
|
|
61
|
+
verb: MetricEventVerb;
|
|
62
|
+
payload?: EventPayload;
|
|
63
|
+
}): void | Promise<void>;
|
|
43
64
|
/**
|
|
44
65
|
* Operational event
|
|
45
66
|
* @param args
|
|
46
67
|
*/
|
|
47
|
-
submitOperationalEvent({ name, payload
|
|
48
|
-
name:
|
|
49
|
-
payload?:
|
|
50
|
-
|
|
51
|
-
|
|
68
|
+
submitOperationalEvent({ name, payload }: {
|
|
69
|
+
name: string;
|
|
70
|
+
payload?: EventPayload;
|
|
71
|
+
}): void | Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Buisness event
|
|
74
|
+
* @param args
|
|
75
|
+
*/
|
|
76
|
+
submitBusinessEvent({ name, payload }: {
|
|
77
|
+
name: string;
|
|
78
|
+
payload: EventPayload;
|
|
79
|
+
}): void | Promise<void>;
|
|
52
80
|
/**
|
|
53
81
|
* Call Analyzer: Media Quality Event
|
|
54
82
|
* @param args
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import GenericMetrics from './generic-metrics';
|
|
2
|
+
import { EventPayload } from './metrics.types';
|
|
3
|
+
/**
|
|
4
|
+
* @description Util class to handle Operational Metrics
|
|
5
|
+
* @export
|
|
6
|
+
* @class OperationalMetrics
|
|
7
|
+
*/
|
|
8
|
+
export default class OperationalMetrics extends GenericMetrics {
|
|
9
|
+
/**
|
|
10
|
+
* Submit an operational metric to our metrics endpoint.
|
|
11
|
+
* @param {string} name of the metric
|
|
12
|
+
* @param {EventPayload} user payload of the metric
|
|
13
|
+
* @returns {Promise<any>}
|
|
14
|
+
*/
|
|
15
|
+
submitOperationalEvent({ name, payload }: {
|
|
16
|
+
name: string;
|
|
17
|
+
payload: EventPayload;
|
|
18
|
+
}): void;
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -26,22 +26,22 @@
|
|
|
26
26
|
"@webex/eslint-config-legacy": "0.0.0",
|
|
27
27
|
"@webex/jest-config-legacy": "0.0.0",
|
|
28
28
|
"@webex/legacy-tools": "0.0.0",
|
|
29
|
-
"@webex/test-helper-chai": "3.
|
|
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.4.0-next.2",
|
|
30
|
+
"@webex/test-helper-mocha": "3.4.0-next.2",
|
|
31
|
+
"@webex/test-helper-mock-webex": "3.4.0-next.2",
|
|
32
|
+
"@webex/test-helper-test-users": "3.4.0-next.2",
|
|
33
33
|
"eslint": "^8.24.0",
|
|
34
34
|
"prettier": "^2.7.1",
|
|
35
35
|
"sinon": "^9.2.4"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@webex/common": "3.
|
|
39
|
-
"@webex/common-timers": "3.
|
|
38
|
+
"@webex/common": "3.4.0-next.2",
|
|
39
|
+
"@webex/common-timers": "3.4.0-next.2",
|
|
40
40
|
"@webex/event-dictionary-ts": "^1.0.1406",
|
|
41
|
-
"@webex/internal-plugin-metrics": "3.
|
|
42
|
-
"@webex/test-helper-chai": "3.
|
|
43
|
-
"@webex/test-helper-mock-webex": "3.
|
|
44
|
-
"@webex/webex-core": "3.
|
|
41
|
+
"@webex/internal-plugin-metrics": "3.4.0-next.2",
|
|
42
|
+
"@webex/test-helper-chai": "3.4.0-next.2",
|
|
43
|
+
"@webex/test-helper-mock-webex": "3.4.0-next.2",
|
|
44
|
+
"@webex/webex-core": "3.4.0-next.2",
|
|
45
45
|
"ip-anonymize": "^0.1.0",
|
|
46
46
|
"lodash": "^4.17.21",
|
|
47
47
|
"uuid": "^3.3.2"
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"test:style": "eslint ./src/**/*.*",
|
|
55
55
|
"test:unit": "webex-legacy-tools test --unit --runner mocha"
|
|
56
56
|
},
|
|
57
|
-
"version": "3.
|
|
57
|
+
"version": "3.4.0-next.2"
|
|
58
58
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {MetricEventProduct, MetricEventAgent, MetricEventVerb, EventPayload} from './metrics.types';
|
|
2
|
+
import GenericMetrics from './generic-metrics';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @description Util class to handle Behavioral Metrics
|
|
6
|
+
* @export
|
|
7
|
+
* @class BehavioralMetrics
|
|
8
|
+
*/
|
|
9
|
+
export default class BehavioralMetrics extends GenericMetrics {
|
|
10
|
+
/**
|
|
11
|
+
* Submit a behavioral metric to our metrics endpoint.
|
|
12
|
+
* @param {MetricEventProduct} product the product from which the metric is being submitted, e.g. 'webex' web client, 'wxcc_desktop'
|
|
13
|
+
* @param {MetricEventAgent} agent the source of the action for this metric
|
|
14
|
+
* @param {string} target the 'thing' that this metric includes information about
|
|
15
|
+
* @param {MetricEventVerb} verb the action that this metric includes information about
|
|
16
|
+
* @param {EventPayload} payload information specific to this event. This should be flat, i.e. it should not include nested objects.
|
|
17
|
+
* @returns {Promise<any>}
|
|
18
|
+
*/
|
|
19
|
+
public submitBehavioralEvent({
|
|
20
|
+
product,
|
|
21
|
+
agent,
|
|
22
|
+
target,
|
|
23
|
+
verb,
|
|
24
|
+
payload,
|
|
25
|
+
}: {
|
|
26
|
+
product: MetricEventProduct;
|
|
27
|
+
agent: MetricEventAgent;
|
|
28
|
+
target: string;
|
|
29
|
+
verb: MetricEventVerb;
|
|
30
|
+
payload?: EventPayload;
|
|
31
|
+
}) {
|
|
32
|
+
const name = `${product}.${agent}.${target}.${verb}`;
|
|
33
|
+
const event = this.createTaggedEventObject({
|
|
34
|
+
type: ['behavioral'],
|
|
35
|
+
name,
|
|
36
|
+
payload,
|
|
37
|
+
});
|
|
38
|
+
this.submitEvent({kind: 'behavioral-events -> ', name, event});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import GenericMetrics from './generic-metrics';
|
|
2
|
+
import {EventPayload} from './metrics.types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @description Util class to handle Buisness Metrics
|
|
6
|
+
* @export
|
|
7
|
+
* @class BusinessMetrics
|
|
8
|
+
*/
|
|
9
|
+
export default class BusinessMetrics extends GenericMetrics {
|
|
10
|
+
/**
|
|
11
|
+
* Submit a buisness metric to our metrics endpoint.
|
|
12
|
+
* @param {string} name of the metric
|
|
13
|
+
* @param {EventPayload} user payload of the metric
|
|
14
|
+
* @returns {Promise<any>}
|
|
15
|
+
*/
|
|
16
|
+
public submitBusinessEvent({name, payload}: {name: string; payload: EventPayload}) {
|
|
17
|
+
const event = {
|
|
18
|
+
type: ['business'],
|
|
19
|
+
eventPayload: {
|
|
20
|
+
metricName: name,
|
|
21
|
+
timestamp: Date.now(),
|
|
22
|
+
context: this.getContext(),
|
|
23
|
+
browserDetails: this.getBrowserDetails(),
|
|
24
|
+
value: payload,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
this.submitEvent({kind: 'buisness-events -> ', name, event});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -455,6 +455,9 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
455
455
|
},
|
|
456
456
|
intervals: payload.intervals,
|
|
457
457
|
callingServiceType: 'LOCUS',
|
|
458
|
+
meetingJoinInfo: {
|
|
459
|
+
clientSignallingProtocol: 'WebRTC',
|
|
460
|
+
},
|
|
458
461
|
sourceMetadata: {
|
|
459
462
|
applicationSoftwareType: CLIENT_NAME,
|
|
460
463
|
// @ts-ignore
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
MISSING_ROAP_ANSWER_CLIENT_CODE,
|
|
22
22
|
WBX_APP_API_URL,
|
|
23
23
|
ERROR_DESCRIPTIONS,
|
|
24
|
+
ICE_AND_REACHABILITY_FAILED_CLIENT_CODE,
|
|
24
25
|
} from './config';
|
|
25
26
|
|
|
26
27
|
const {getOSName, getOSVersion, getBrowserName, getBrowserVersion} = BrowserDetection();
|
|
@@ -225,7 +226,7 @@ export const getBuildType = (
|
|
|
225
226
|
*/
|
|
226
227
|
export const prepareDiagnosticMetricItem = (webex: any, item: any) => {
|
|
227
228
|
const origin: Partial<Event['origin']> = {
|
|
228
|
-
buildType:
|
|
229
|
+
buildType: getBuildType(
|
|
229
230
|
item.eventPayload?.event?.eventData?.webClientDomain,
|
|
230
231
|
item.eventPayload?.event?.eventData?.markAsTestEvent
|
|
231
232
|
),
|
|
@@ -284,6 +285,8 @@ export const prepareDiagnosticMetricItem = (webex: any, item: any) => {
|
|
|
284
285
|
|
|
285
286
|
case 'client.media.rx.start':
|
|
286
287
|
joinTimes.localSDPGenRemoteSDPRecv = cdl.getLocalSDPGenRemoteSDPRecv();
|
|
288
|
+
audioSetupDelay.joinRespRxStart = cdl.getAudioJoinRespRxStart();
|
|
289
|
+
videoSetupDelay.joinRespRxStart = cdl.getVideoJoinRespRxStart();
|
|
287
290
|
break;
|
|
288
291
|
|
|
289
292
|
case 'client.media-engine.ready':
|
|
@@ -293,10 +296,8 @@ export const prepareDiagnosticMetricItem = (webex: any, item: any) => {
|
|
|
293
296
|
joinTimes.stayLobbyTime = cdl.getStayLobbyTime();
|
|
294
297
|
break;
|
|
295
298
|
|
|
296
|
-
case 'client.
|
|
297
|
-
audioSetupDelay.joinRespRxStart = cdl.getAudioJoinRespRxStart();
|
|
299
|
+
case 'client.media.tx.start':
|
|
298
300
|
audioSetupDelay.joinRespTxStart = cdl.getAudioJoinRespTxStart();
|
|
299
|
-
videoSetupDelay.joinRespRxStart = cdl.getVideoJoinRespRxStart();
|
|
300
301
|
videoSetupDelay.joinRespTxStart = cdl.getVideoJoinRespTxStart();
|
|
301
302
|
}
|
|
302
303
|
|
|
@@ -314,7 +315,6 @@ export const prepareDiagnosticMetricItem = (webex: any, item: any) => {
|
|
|
314
315
|
|
|
315
316
|
item.eventPayload.origin = Object.assign(origin, item.eventPayload.origin);
|
|
316
317
|
|
|
317
|
-
// @ts-ignore
|
|
318
318
|
webex.logger.log(
|
|
319
319
|
`CallDiagnosticLatencies,prepareDiagnosticMetricItem: ${JSON.stringify({
|
|
320
320
|
latencies: Object.fromEntries(cdl.latencyTimestamps),
|
|
@@ -370,12 +370,14 @@ export const extractVersionMetadata = (version: string) => {
|
|
|
370
370
|
*/
|
|
371
371
|
export const generateClientErrorCodeForIceFailure = ({
|
|
372
372
|
signalingState,
|
|
373
|
-
|
|
373
|
+
iceConnected,
|
|
374
374
|
turnServerUsed,
|
|
375
|
+
unreachable,
|
|
375
376
|
}: {
|
|
376
377
|
signalingState: RTCPeerConnection['signalingState'];
|
|
377
|
-
|
|
378
|
+
iceConnected: boolean;
|
|
378
379
|
turnServerUsed: boolean;
|
|
380
|
+
unreachable: boolean;
|
|
379
381
|
}) => {
|
|
380
382
|
let errorCode = ICE_FAILURE_CLIENT_CODE; // default;
|
|
381
383
|
|
|
@@ -383,20 +385,17 @@ export const generateClientErrorCodeForIceFailure = ({
|
|
|
383
385
|
errorCode = MISSING_ROAP_ANSWER_CLIENT_CODE;
|
|
384
386
|
}
|
|
385
387
|
|
|
386
|
-
if (
|
|
387
|
-
signalingState === 'stable' &&
|
|
388
|
-
(iceConnectionState === 'connected' || iceConnectionState === 'disconnected')
|
|
389
|
-
) {
|
|
388
|
+
if (signalingState === 'stable' && iceConnected) {
|
|
390
389
|
errorCode = DTLS_HANDSHAKE_FAILED_CLIENT_CODE;
|
|
391
390
|
}
|
|
392
391
|
|
|
393
|
-
if (
|
|
394
|
-
signalingState !== 'have-local-offer' &&
|
|
395
|
-
iceConnectionState !== 'connected' &&
|
|
396
|
-
iceConnectionState !== 'disconnected'
|
|
397
|
-
) {
|
|
392
|
+
if (signalingState !== 'have-local-offer' && !iceConnected) {
|
|
398
393
|
if (turnServerUsed) {
|
|
399
|
-
|
|
394
|
+
if (unreachable) {
|
|
395
|
+
errorCode = ICE_AND_REACHABILITY_FAILED_CLIENT_CODE;
|
|
396
|
+
} else {
|
|
397
|
+
errorCode = ICE_FAILED_WITH_TURN_TLS_CLIENT_CODE;
|
|
398
|
+
}
|
|
400
399
|
} else {
|
|
401
400
|
errorCode = ICE_FAILED_WITHOUT_TURN_TLS_CLIENT_CODE;
|
|
402
401
|
}
|