@webex/internal-plugin-metrics 3.9.0-webinar5k.1 → 3.10.0-multi-llms.1
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/call-diagnostic/call-diagnostic-metrics-latencies.js +58 -28
- package/dist/call-diagnostic/call-diagnostic-metrics-latencies.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.js +165 -28
- package/dist/call-diagnostic/call-diagnostic-metrics.js.map +1 -1
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js +15 -0
- package/dist/call-diagnostic/call-diagnostic-metrics.util.js.map +1 -1
- package/dist/metrics.js +1 -1
- package/dist/metrics.types.js.map +1 -1
- package/dist/types/call-diagnostic/call-diagnostic-metrics-latencies.d.ts +9 -1
- package/dist/types/call-diagnostic/call-diagnostic-metrics.d.ts +35 -3
- package/dist/types/metrics.types.d.ts +2 -1
- package/package.json +12 -13
- package/src/call-diagnostic/call-diagnostic-metrics-latencies.ts +68 -28
- package/src/call-diagnostic/call-diagnostic-metrics.ts +154 -2
- package/src/call-diagnostic/call-diagnostic-metrics.util.ts +14 -0
- package/src/metrics.types.ts +4 -1
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics-latencies.ts +287 -0
- package/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts +440 -2
- package/test/unit/spec/prelogin-metrics-batcher.ts +71 -3
package/dist/metrics.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["metrics.types.ts"],"sourcesContent":["import {\n ClientEvent as RawClientEvent,\n Event as RawEvent,\n MediaQualityEvent as RawMediaQualityEvent,\n FeatureEvent as RawFeatureEvent,\n} from '@webex/event-dictionary-ts';\n\nexport type Event = Omit<RawEvent, 'event'> & {\n event: RawClientEvent | RawMediaQualityEvent | RawFeatureEvent;\n};\n\nexport type ClientEventError = NonNullable<RawClientEvent['errors']>[0];\n\nexport type EnvironmentType = NonNullable<RawEvent['origin']['environment']>;\n\nexport type NewEnvironmentType = NonNullable<RawEvent['origin']['newEnvironment']>;\n\nexport type ClientLaunchMethodType = NonNullable<\n RawEvent['origin']['clientInfo']\n>['clientLaunchMethod'];\n\nexport type ClientUserNameInput = NonNullable<RawClientEvent['userNameInput']>;\n\nexport type ClientEmailInput = NonNullable<RawClientEvent['emailInput']>;\n\nexport type BrowserLaunchMethodType = NonNullable<\n RawEvent['origin']['clientInfo']\n>['browserLaunchMethod'];\n\nexport type MetricEventProduct = 'webex' | 'wxcc_desktop' | 'wxcc_crm' | 'wxcc_sdk';\n\nexport type MetricEventAgent = 'user' | 'browser' | 'system' | 'sdk' | 'redux' | 'service' | 'api';\n\nexport type MetricEventVerb =\n | 'abort'\n | 'accept'\n | 'activate'\n | 'apply'\n | 'answer'\n | 'authorize'\n | 'build'\n | 'cancel'\n | 'change'\n | 'click'\n | 'close'\n | 'complete'\n | 'connect'\n | 'create'\n | 'deactivate'\n | 'decrypt'\n | 'delete'\n | 'deliver'\n | 'destroy'\n | 'disable'\n | 'disconnect'\n | 'dismiss'\n | 'display'\n | 'download'\n | 'edit'\n | 'enable'\n | 'encrypt'\n | 'end'\n | 'expire'\n | 'fail'\n | 'fetch'\n | 'fire'\n | 'generate'\n | 'get'\n | 'hide'\n | 'hover'\n | 'ignore'\n | 'initialize'\n | 'initiate'\n | 'invalidate'\n | 'join'\n | 'list'\n | 'load'\n | 'login'\n | 'logout'\n | 'notify'\n | 'offer'\n | 'open'\n | 'press'\n | 'receive'\n | 'refer'\n | 'refresh'\n | 'register'\n | 'release'\n | 'reload'\n | 'reject'\n | 'request'\n | 'reset'\n | 'resize'\n | 'respond'\n | 'retry'\n | 'revoke'\n | 'save'\n | 'search'\n | 'select'\n | 'send'\n | 'set'\n | 'sign'\n | 'start'\n | 'submit'\n | 'switch'\n | 'sync'\n | 'toggle'\n | 'transfer'\n | 'unregister'\n | 'update'\n | 'upload'\n | 'use'\n | 'validate'\n | 'view'\n | 'visit'\n | 'wait'\n | 'warn'\n | 'exit';\n\nexport type MetricEventJoinFlowVersion = 'Other' | 'NewFTE';\nexport type MetricEventMeetingJoinPhase = 'pre-join' | 'join' | 'in-meeting';\n\nexport type SubmitClientEventOptions = {\n meetingId?: string;\n mediaConnections?: any[];\n rawError?: any;\n correlationId?: string;\n sessionCorrelationId?: string;\n preLoginId?: string;\n environment?: EnvironmentType;\n newEnvironmentType?: NewEnvironmentType;\n clientLaunchMethod?: ClientLaunchMethodType;\n browserLaunchMethod?: BrowserLaunchMethodType;\n webexConferenceIdStr?: string;\n globalMeetingId?: string;\n joinFlowVersion?: MetricEventJoinFlowVersion;\n meetingJoinPhase?: MetricEventMeetingJoinPhase;\n triggeredTime?: string;\n emailInput?: ClientEmailInput;\n userNameInput?: ClientUserNameInput;\n};\n\nexport type SubmitMQEOptions = {\n meetingId: string;\n mediaConnections?: any[];\n networkType?: Event['origin']['networkType'];\n webexConferenceIdStr?: string;\n globalMeetingId?: string;\n};\n\nexport type InternalEvent = {\n name:\n | 'internal.client.meetinginfo.request'\n | 'internal.client.meetinginfo.response'\n | 'internal.register.device.request'\n | 'internal.register.device.response'\n | 'internal.reset.join.latencies'\n | 'internal.client.meeting.click.joinbutton'\n | 'internal.host.meeting.participant.admitted'\n | 'internal.client.meeting.interstitial-window.showed'\n | 'internal.client.interstitial-window.click.joinbutton'\n | 'internal.client.add-media.turn-discovery.start'\n | 'internal.client.add-media.turn-discovery.end';\n\n payload?: never;\n options?: never;\n};\n\nexport interface ClientEvent {\n name: RawClientEvent['name'];\n payload?: RawClientEvent;\n options?: SubmitClientEventOptions;\n}\n\nexport interface DeviceContext {\n app: {version: string};\n device: {id: string};\n locale: string;\n os: {\n name: string;\n version: string;\n };\n}\n\nexport type MetricType = 'behavioral' | 'operational' | 'business';\n\nexport type Table = 'wbxapp_callend_metrics' | 'business_metrics' | 'business_ucf' | 'default';\n\ntype InternalEventPayload = string | number | boolean;\nexport type EventPayload = Record<string, InternalEventPayload>;\nexport type BehavioralEventPayload = EventPayload; // for compatibilty, can be remove after wxcc-desktop did change their imports.\n\nexport interface BusinessEventPayload {\n metricName: string;\n timestamp: number;\n context: DeviceContext;\n browserDetails: EventPayload;\n value: EventPayload;\n}\n\nexport interface BusinessEvent {\n type: string[];\n eventPayload: BusinessEventPayload;\n}\n\nexport interface TaggedEvent {\n context: DeviceContext;\n metricName: string;\n tags: EventPayload;\n timestamp: number;\n type: [MetricType];\n}\n\nexport type BehavioralEvent = TaggedEvent;\nexport type OperationalEvent = TaggedEvent;\n\nexport interface FeatureEvent {\n name: RawFeatureEvent['name'];\n payload?: RawFeatureEvent;\n options?: SubmitClientEventOptions;\n}\n\nexport interface MediaQualityEvent {\n name: RawMediaQualityEvent['name'];\n payload?: RawMediaQualityEvent;\n options: SubmitMQEOptions;\n}\n\nexport type RecursivePartial<T> = {\n [P in keyof T]?: T[P] extends (infer U)[]\n ? RecursivePartial<U>[]\n : T[P] extends object\n ? RecursivePartial<T[P]>\n : T[P];\n};\n\nexport type MetricEventNames =\n | InternalEvent['name']\n | ClientEvent['name']\n | BehavioralEvent['metricName']\n | OperationalEvent['metricName']\n | BusinessEvent['eventPayload']['metricName']\n | FeatureEvent['name']\n | MediaQualityEvent['name'];\n\nexport type ClientInfo = NonNullable<RawEvent['origin']['clientInfo']>;\nexport type ClientType = NonNullable<RawEvent['origin']['clientInfo']>['clientType'];\nexport type SubClientType = NonNullable<RawEvent['origin']['clientInfo']>['subClientType'];\nexport type NetworkType = NonNullable<RawEvent['origin']>['networkType'];\n\nexport type ClientSubServiceType = ClientEvent['payload']['webexSubServiceType'];\nexport type ClientEventPayload = RecursivePartial<ClientEvent['payload']>;\nexport type ClientEventLeaveReason = ClientEvent['payload']['leaveReason'];\nexport type ClientEventPayloadError = ClientEvent['payload']['errors'];\n\nexport type ClientFeatureEventPayload = RecursivePartial<FeatureEvent['payload']>;\n\nexport type MediaQualityEventAudioSetupDelayPayload = NonNullable<\n MediaQualityEvent['payload']\n>['audioSetupDelay'];\nexport type MediaQualityEventVideoSetupDelayPayload = NonNullable<\n MediaQualityEvent['payload']\n>['videoSetupDelay'];\n\nexport type SubmitMQEPayload = RecursivePartial<MediaQualityEvent['payload']> & {\n intervals: NonNullable<MediaQualityEvent['payload']>['intervals'];\n};\n\nexport type SubmitInternalEvent = (args: {\n name: InternalEvent['name'];\n payload?: RecursivePartial<InternalEvent['payload']>;\n options?: any;\n}) => void;\n\nexport type SubmitBehavioralEvent = (args: {\n product: MetricEventProduct;\n agent: MetricEventAgent;\n target: string;\n verb: MetricEventVerb;\n payload?: EventPayload;\n}) => void;\n\nexport type SubmitClientEvent = (args: {\n name: ClientEvent['name'];\n payload?: RecursivePartial<ClientEvent['payload']>;\n options?: SubmitClientEventOptions;\n}) => Promise<any>;\n\nexport type SubmitOperationalEvent = (args: {\n name: OperationalEvent['metricName'];\n payload: EventPayload;\n}) => void;\n\nexport type SubmitBusinessEvent = (args: {\n name: OperationalEvent['metricName'];\n payload: EventPayload;\n metadata?: EventPayload;\n table?: Table;\n}) => void;\n\nexport type SubmitMQE = (args: {\n name: MediaQualityEvent['name'];\n payload: SubmitMQEPayload;\n options: any;\n}) => void;\n\nexport type BuildClientEventFetchRequestOptions = (args: {\n name: ClientEvent['name'];\n payload?: RecursivePartial<ClientEvent['payload']>;\n options?: SubmitClientEventOptions;\n}) => Promise<any>;\n\nexport type PreComputedLatencies =\n | 'internal.client.pageJMT'\n | 'internal.download.time'\n | 'internal.get.cluster.time'\n | 'internal.click.to.interstitial'\n | 'internal.click.to.interstitial.with.user.delay'\n | 'internal.refresh.captcha.time'\n | 'internal.exchange.ci.token.time'\n | 'internal.get.u2c.time'\n | 'internal.call.init.join.req'\n | 'internal.other.app.api.time'\n | 'internal.api.fetch.intelligence.models';\n\nexport interface IdType {\n meetingId?: string;\n callId?: string;\n}\n\nexport interface IMetricsAttributes {\n type: string;\n version: string;\n userId: string;\n correlationId: string;\n connectionId: string;\n data: any[];\n meetingId?: string;\n callId?: string;\n}\n\nexport interface DelayedClientEvent {\n name: ClientEvent['name'];\n payload?: RecursivePartial<ClientEvent['payload']>;\n options?: SubmitClientEventOptions;\n}\n\nexport type SubmitFeatureEvent = (args: {\n name: FeatureEvent['name'];\n payload?: RecursivePartial<FeatureEvent['payload']>;\n options?: SubmitClientEventOptions;\n}) => Promise<any>;\n\nexport interface DelayedClientFeatureEvent {\n name: FeatureEvent['name'];\n payload?: RecursivePartial<FeatureEvent['payload']>;\n options?: SubmitClientEventOptions;\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"names":[],"sources":["metrics.types.ts"],"sourcesContent":["import {\n ClientEvent as RawClientEvent,\n Event as RawEvent,\n MediaQualityEvent as RawMediaQualityEvent,\n FeatureEvent as RawFeatureEvent,\n} from '@webex/event-dictionary-ts';\n\nexport type Event = Omit<RawEvent, 'event'> & {\n event: RawClientEvent | RawMediaQualityEvent | RawFeatureEvent;\n};\n\nexport type ClientEventError = NonNullable<RawClientEvent['errors']>[0];\n\nexport type EnvironmentType = NonNullable<RawEvent['origin']['environment']>;\n\nexport type NewEnvironmentType = NonNullable<RawEvent['origin']['newEnvironment']>;\n\nexport type ClientLaunchMethodType = NonNullable<\n RawEvent['origin']['clientInfo']\n>['clientLaunchMethod'];\n\nexport type ClientUserNameInput = NonNullable<RawClientEvent['userNameInput']>;\n\nexport type ClientEmailInput = NonNullable<RawClientEvent['emailInput']>;\n\nexport type BrowserLaunchMethodType = NonNullable<\n RawEvent['origin']['clientInfo']\n>['browserLaunchMethod'];\n\nexport type MetricEventProduct = 'webex' | 'wxcc_desktop' | 'wxcc_crm' | 'wxcc_sdk';\n\nexport type MetricEventAgent = 'user' | 'browser' | 'system' | 'sdk' | 'redux' | 'service' | 'api';\n\nexport type MetricEventVerb =\n | 'abort'\n | 'accept'\n | 'activate'\n | 'apply'\n | 'answer'\n | 'authorize'\n | 'build'\n | 'cancel'\n | 'change'\n | 'click'\n | 'close'\n | 'complete'\n | 'connect'\n | 'create'\n | 'deactivate'\n | 'decrypt'\n | 'delete'\n | 'deliver'\n | 'destroy'\n | 'disable'\n | 'disconnect'\n | 'dismiss'\n | 'display'\n | 'download'\n | 'edit'\n | 'enable'\n | 'encrypt'\n | 'end'\n | 'expire'\n | 'fail'\n | 'fetch'\n | 'fire'\n | 'generate'\n | 'get'\n | 'hide'\n | 'hover'\n | 'ignore'\n | 'initialize'\n | 'initiate'\n | 'invalidate'\n | 'join'\n | 'list'\n | 'load'\n | 'login'\n | 'logout'\n | 'notify'\n | 'offer'\n | 'open'\n | 'press'\n | 'receive'\n | 'refer'\n | 'refresh'\n | 'register'\n | 'release'\n | 'reload'\n | 'reject'\n | 'request'\n | 'reset'\n | 'resize'\n | 'respond'\n | 'retry'\n | 'revoke'\n | 'save'\n | 'search'\n | 'select'\n | 'send'\n | 'set'\n | 'sign'\n | 'start'\n | 'submit'\n | 'switch'\n | 'sync'\n | 'toggle'\n | 'transfer'\n | 'unregister'\n | 'update'\n | 'upload'\n | 'use'\n | 'validate'\n | 'view'\n | 'visit'\n | 'wait'\n | 'warn'\n | 'exit';\n\nexport type MetricEventJoinFlowVersion = 'Other' | 'NewFTE';\nexport type MetricEventMeetingJoinPhase = 'pre-join' | 'join' | 'in-meeting';\n\nexport type SubmitClientEventOptions = {\n meetingId?: string;\n mediaConnections?: any[];\n rawError?: any;\n correlationId?: string;\n sessionCorrelationId?: string;\n preLoginId?: string;\n environment?: EnvironmentType;\n newEnvironmentType?: NewEnvironmentType;\n clientLaunchMethod?: ClientLaunchMethodType;\n browserLaunchMethod?: BrowserLaunchMethodType;\n webexConferenceIdStr?: string;\n globalMeetingId?: string;\n joinFlowVersion?: MetricEventJoinFlowVersion;\n meetingJoinPhase?: MetricEventMeetingJoinPhase;\n triggeredTime?: string;\n emailInput?: ClientEmailInput;\n userNameInput?: ClientUserNameInput;\n vendorId?: string;\n};\n\nexport type SubmitMQEOptions = {\n meetingId: string;\n mediaConnections?: any[];\n networkType?: Event['origin']['networkType'];\n webexConferenceIdStr?: string;\n globalMeetingId?: string;\n};\n\nexport type InternalEvent = {\n name:\n | 'internal.client.meetinginfo.request'\n | 'internal.client.meetinginfo.response'\n | 'internal.register.device.request'\n | 'internal.register.device.response'\n | 'internal.reset.join.latencies'\n | 'internal.client.meeting.click.joinbutton'\n | 'internal.host.meeting.participant.admitted'\n | 'internal.client.meeting.interstitial-window.showed'\n | 'internal.client.interstitial-window.click.joinbutton'\n | 'internal.client.add-media.turn-discovery.start'\n | 'internal.client.add-media.turn-discovery.end'\n | 'internal.client.share.initiated'\n | 'internal.client.share.stopped';\n\n payload?: never;\n options?: never;\n};\n\nexport interface ClientEvent {\n name: RawClientEvent['name'];\n payload?: RawClientEvent;\n options?: SubmitClientEventOptions;\n}\n\nexport interface DeviceContext {\n app: {version: string};\n device: {id: string};\n locale: string;\n os: {\n name: string;\n version: string;\n };\n}\n\nexport type MetricType = 'behavioral' | 'operational' | 'business';\n\nexport type Table = 'wbxapp_callend_metrics' | 'business_metrics' | 'business_ucf' | 'default';\n\ntype InternalEventPayload = string | number | boolean;\nexport type EventPayload = Record<string, InternalEventPayload>;\nexport type BehavioralEventPayload = EventPayload; // for compatibilty, can be remove after wxcc-desktop did change their imports.\n\nexport interface BusinessEventPayload {\n metricName: string;\n timestamp: number;\n context: DeviceContext;\n browserDetails: EventPayload;\n value: EventPayload;\n}\n\nexport interface BusinessEvent {\n type: string[];\n eventPayload: BusinessEventPayload;\n}\n\nexport interface TaggedEvent {\n context: DeviceContext;\n metricName: string;\n tags: EventPayload;\n timestamp: number;\n type: [MetricType];\n}\n\nexport type BehavioralEvent = TaggedEvent;\nexport type OperationalEvent = TaggedEvent;\n\nexport interface FeatureEvent {\n name: RawFeatureEvent['name'];\n payload?: RawFeatureEvent;\n options?: SubmitClientEventOptions;\n}\n\nexport interface MediaQualityEvent {\n name: RawMediaQualityEvent['name'];\n payload?: RawMediaQualityEvent;\n options: SubmitMQEOptions;\n}\n\nexport type RecursivePartial<T> = {\n [P in keyof T]?: T[P] extends (infer U)[]\n ? RecursivePartial<U>[]\n : T[P] extends object\n ? RecursivePartial<T[P]>\n : T[P];\n};\n\nexport type MetricEventNames =\n | InternalEvent['name']\n | ClientEvent['name']\n | BehavioralEvent['metricName']\n | OperationalEvent['metricName']\n | BusinessEvent['eventPayload']['metricName']\n | FeatureEvent['name']\n | MediaQualityEvent['name'];\n\nexport type ClientInfo = NonNullable<RawEvent['origin']['clientInfo']>;\nexport type ClientType = NonNullable<RawEvent['origin']['clientInfo']>['clientType'];\nexport type SubClientType = NonNullable<RawEvent['origin']['clientInfo']>['subClientType'];\nexport type NetworkType = NonNullable<RawEvent['origin']>['networkType'];\n\nexport type ClientSubServiceType = ClientEvent['payload']['webexSubServiceType'];\nexport type ClientEventPayload = RecursivePartial<ClientEvent['payload']>;\nexport type ClientEventLeaveReason = ClientEvent['payload']['leaveReason'];\nexport type ClientEventPayloadError = ClientEvent['payload']['errors'];\n\nexport type ClientFeatureEventPayload = RecursivePartial<FeatureEvent['payload']>;\n\nexport type MediaQualityEventAudioSetupDelayPayload = NonNullable<\n MediaQualityEvent['payload']\n>['audioSetupDelay'];\nexport type MediaQualityEventVideoSetupDelayPayload = NonNullable<\n MediaQualityEvent['payload']\n>['videoSetupDelay'];\n\nexport type SubmitMQEPayload = RecursivePartial<MediaQualityEvent['payload']> & {\n intervals: NonNullable<MediaQualityEvent['payload']>['intervals'];\n};\n\nexport type SubmitInternalEvent = (args: {\n name: InternalEvent['name'];\n payload?: RecursivePartial<InternalEvent['payload']>;\n options?: any;\n}) => void;\n\nexport type SubmitBehavioralEvent = (args: {\n product: MetricEventProduct;\n agent: MetricEventAgent;\n target: string;\n verb: MetricEventVerb;\n payload?: EventPayload;\n}) => void;\n\nexport type SubmitClientEvent = (args: {\n name: ClientEvent['name'];\n payload?: RecursivePartial<ClientEvent['payload']>;\n options?: SubmitClientEventOptions;\n}) => Promise<any>;\n\nexport type SubmitOperationalEvent = (args: {\n name: OperationalEvent['metricName'];\n payload: EventPayload;\n}) => void;\n\nexport type SubmitBusinessEvent = (args: {\n name: OperationalEvent['metricName'];\n payload: EventPayload;\n metadata?: EventPayload;\n table?: Table;\n}) => void;\n\nexport type SubmitMQE = (args: {\n name: MediaQualityEvent['name'];\n payload: SubmitMQEPayload;\n options: any;\n}) => void;\n\nexport type BuildClientEventFetchRequestOptions = (args: {\n name: ClientEvent['name'];\n payload?: RecursivePartial<ClientEvent['payload']>;\n options?: SubmitClientEventOptions;\n}) => Promise<any>;\n\nexport type PreComputedLatencies =\n | 'internal.client.pageJMT'\n | 'internal.download.time'\n | 'internal.get.cluster.time'\n | 'internal.click.to.interstitial'\n | 'internal.click.to.interstitial.with.user.delay'\n | 'internal.refresh.captcha.time'\n | 'internal.exchange.ci.token.time'\n | 'internal.get.u2c.time'\n | 'internal.call.init.join.req'\n | 'internal.other.app.api.time'\n | 'internal.api.fetch.intelligence.models';\n\nexport interface IdType {\n meetingId?: string;\n callId?: string;\n}\n\nexport interface IMetricsAttributes {\n type: string;\n version: string;\n userId: string;\n correlationId: string;\n connectionId: string;\n data: any[];\n meetingId?: string;\n callId?: string;\n}\n\nexport interface DelayedClientEvent {\n name: ClientEvent['name'];\n payload?: RecursivePartial<ClientEvent['payload']>;\n options?: SubmitClientEventOptions;\n}\n\nexport type SubmitFeatureEvent = (args: {\n name: FeatureEvent['name'];\n payload?: RecursivePartial<FeatureEvent['payload']>;\n options?: SubmitClientEventOptions;\n}) => Promise<any>;\n\nexport interface DelayedClientFeatureEvent {\n name: FeatureEvent['name'];\n payload?: RecursivePartial<FeatureEvent['payload']>;\n options?: SubmitClientEventOptions;\n}\n"],"mappings":""}
|
|
@@ -9,6 +9,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
9
9
|
latencyTimestamps: Map<MetricEventNames, number>;
|
|
10
10
|
precomputedLatencies: Map<PreComputedLatencies, number>;
|
|
11
11
|
private meetingId?;
|
|
12
|
+
private MAX_INTEGER;
|
|
12
13
|
/**
|
|
13
14
|
* @constructor
|
|
14
15
|
*/
|
|
@@ -73,7 +74,10 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
73
74
|
* @param b end
|
|
74
75
|
* @returns latency
|
|
75
76
|
*/
|
|
76
|
-
getDiffBetweenTimestamps(a: MetricEventNames, b: MetricEventNames
|
|
77
|
+
getDiffBetweenTimestamps(a: MetricEventNames, b: MetricEventNames, clampValues?: {
|
|
78
|
+
minimum?: number;
|
|
79
|
+
maximum?: number;
|
|
80
|
+
}): number;
|
|
77
81
|
/**
|
|
78
82
|
* Meeting Info Request
|
|
79
83
|
* @note Meeting Info request happen not just in the join phase. CA requires
|
|
@@ -230,6 +234,10 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
230
234
|
* Video setup delay transmit
|
|
231
235
|
*/
|
|
232
236
|
getVideoJoinRespTxStart(): number;
|
|
237
|
+
/**
|
|
238
|
+
* Time from share initiation to share stop (ms).
|
|
239
|
+
*/
|
|
240
|
+
getShareDuration(): number;
|
|
233
241
|
/**
|
|
234
242
|
* Total latency for all exchange ci token.
|
|
235
243
|
*/
|
|
@@ -8,6 +8,7 @@ type GetOriginOptions = {
|
|
|
8
8
|
browserLaunchMethod?: BrowserLaunchMethodType;
|
|
9
9
|
environment?: EnvironmentType;
|
|
10
10
|
newEnvironment?: NewEnvironmentType;
|
|
11
|
+
vendorId?: string;
|
|
11
12
|
};
|
|
12
13
|
type GetIdentifiersOptions = {
|
|
13
14
|
meeting?: any;
|
|
@@ -33,6 +34,8 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
33
34
|
private delayedClientFeatureEvents;
|
|
34
35
|
private eventErrorCache;
|
|
35
36
|
private isMercuryConnected;
|
|
37
|
+
private eventLimitTracker;
|
|
38
|
+
private eventLimitWarningsLogged;
|
|
36
39
|
validator: (options: {
|
|
37
40
|
type: 'mqe' | 'ce';
|
|
38
41
|
event: Event;
|
|
@@ -77,7 +80,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
77
80
|
* @returns
|
|
78
81
|
*/
|
|
79
82
|
getOrigin(options: GetOriginOptions, meetingId?: string): {
|
|
80
|
-
name: "endpoint" | "addin" | "antares" | "appapi" | "beech" | "breakout" | "calendar" | "cb" | "cca" | "ccc" | "cloudproxy" | "crc" | "edonus" | "givr" | "hecate" | "hedge" | "hesiod" | "homer" | "idbroker" | "superhomer" | "l2sip" | "linus" | "locus" | "mbs" | "mcc" | "mcs" | "mercury" | "mes" | "mjs" | "mmp" | "mrs" | "mygdon" | "ngpage" | "ngservice" | "oauth" | "orpheus" | "page" | "poros" | "publicapi" | "rhesos" | "terminus" | "tpgw" | "ucc" | "wdm" | "webexivr" | "meetingcontainer";
|
|
83
|
+
name: "endpoint" | "addin" | "antares" | "appapi" | "beech" | "breakout" | "calendar" | "cb" | "cca" | "ccc" | "cloudproxy" | "crc" | "edonus" | "givr" | "hecate" | "hedge" | "hesiod" | "homer" | "idbroker" | "superhomer" | "l2sip" | "linus" | "locus" | "mbs" | "mcc" | "mcs" | "mercury" | "mes" | "mjs" | "mmp" | "mrs" | "mygdon" | "ngpage" | "ngservice" | "oauth" | "orpheus" | "page" | "poros" | "publicapi" | "rhesos" | "sbs" | "terminus" | "tpgw" | "ucc" | "wdm" | "webexivr" | "meetingcontainer";
|
|
81
84
|
userAgent: string;
|
|
82
85
|
buildType?: "debug" | "test" | "prod" | "tap" | "analyzer-test";
|
|
83
86
|
upgradeChannel?: string;
|
|
@@ -98,10 +101,11 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
98
101
|
publicNetworkPrefix?: string;
|
|
99
102
|
browserLaunchMethod?: "url-handler" | "activex" | "npapi" | "extension" | "cwsapi" | "java" | "tfs" | "webacd" | "thinclient" | "switch-to-web" | "switch-to-native";
|
|
100
103
|
clientLaunchMethod?: "url-handler" | "universal-link" | "voice-command" | "notification" | "manual" | "teams-cross-launch" | "mc-cross-launch" | "cws" | "installer" | "installer-launcher" | "launcher" | "cws-launcher";
|
|
104
|
+
urlProtocolLaunchMethod?: "manual" | "auto" | "extension-fallback";
|
|
101
105
|
browser?: string;
|
|
102
106
|
browserVersion?: string;
|
|
103
|
-
clientType?: "MEETING_CENTER" | "EVENT_CENTER" | "TRAINING_CENTER" | "TEAMS_CLIENT" | "TEAMS_DEVICE" | "TEAMS_SHARE" | "SIP" | "RECORDING" | "CLOUD_AWARE_SIP" | "TEAMS_WXC_CLIENT" | "WXC_CLIENT" | "WXC_DEVICE" | "WEBEX_JS_SDK" | "VOICEA_CLIENT" | "CISCO_SIP_GW" | "WEBEX_SDK" | "CPAAS_THIRD_PARTY_SDK" | "WXC_THIRD_PARTY" | "WXCC" | "TEAMS_PHONE";
|
|
104
|
-
subClientType?: "TEAMS_DEVICE" | "AUTOMOTIVE_APP" | "DESKTOP_APP" | "DESKTOP_APP_VDI" | "DEVICE_CURRENT" | "DEVICE_LEGACY_2020" | "HOLOGRAM_HEADSET_APP" | "HVDI_APP" | "MIXED" | "MOBILE_APP" | "MOBILE_NETWORK" | "PAGE" | "VDI_APP" | "WEB_APP" | "PHONE_NOVUM" | "PHONE_ESPRESSO" | "PHONE_BUMBLEBEE";
|
|
107
|
+
clientType?: "MEETING_CENTER" | "EVENT_CENTER" | "TRAINING_CENTER" | "TEAMS_CLIENT" | "TEAMS_DEVICE" | "TEAMS_SHARE" | "SIP" | "RECORDING" | "CLOUD_AWARE_SIP" | "TEAMS_WXC_CLIENT" | "WXC_CLIENT" | "WXC_DEVICE" | "WEBEX_JS_SDK" | "VOICEA_CLIENT" | "CISCO_SIP_GW" | "WEBEX_SDK" | "CPAAS_THIRD_PARTY_SDK" | "WXC_THIRD_PARTY" | "WXCC" | "TEAMS_PHONE" | "WEBEX_RELAY";
|
|
108
|
+
subClientType?: "TEAMS_DEVICE" | "SIP" | "AUTOMOTIVE_APP" | "DESKTOP_APP" | "DESKTOP_APP_VDI" | "DEVICE_CURRENT" | "DEVICE_LEGACY_2020" | "HOLOGRAM_HEADSET_APP" | "HVDI_APP" | "MIXED" | "MOBILE_APP" | "MOBILE_NETWORK" | "PAGE" | "VDI_APP" | "WEB_APP" | "PHONE_NOVUM" | "PHONE_ESPRESSO" | "PHONE_BUMBLEBEE" | "SIP_PSTN";
|
|
105
109
|
schedulingClientType?: "TEAMS_CLIENT" | "GOOGLE_ADDON" | "PT" | "PUBLIC_API" | "UNIFIED_PAGE" | "WEBEX_PAGE" | "GOOGLE_NOTIFICATION_CALENDAR" | "MSFT_NOTIFICATION_ADDIN" | "MSFT_NOTIFICATION_CALENDAR" | "OUTLOOK_ADDIN";
|
|
106
110
|
clientVersion?: string;
|
|
107
111
|
clientVersionStatus?: "CURRENT" | "LEGACY" | "UNSUPPORTED";
|
|
@@ -144,6 +148,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
144
148
|
inMeetingUpdate?: boolean;
|
|
145
149
|
mtaVersion?: string;
|
|
146
150
|
isWarholOpening?: boolean;
|
|
151
|
+
vendorId?: string;
|
|
147
152
|
additionalProperties?: false;
|
|
148
153
|
};
|
|
149
154
|
emmVendorId?: string;
|
|
@@ -241,6 +246,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
241
246
|
recordingId?: string;
|
|
242
247
|
clientCorrelationId?: string;
|
|
243
248
|
idForEndpointAB?: string;
|
|
249
|
+
customerOrgId?: string;
|
|
244
250
|
correlationId: string;
|
|
245
251
|
additionalProperties?: false;
|
|
246
252
|
} | {
|
|
@@ -327,6 +333,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
327
333
|
recordingId?: string;
|
|
328
334
|
clientCorrelationId?: string;
|
|
329
335
|
idForEndpointAB?: string;
|
|
336
|
+
customerOrgId?: string;
|
|
330
337
|
correlationId: string;
|
|
331
338
|
additionalProperties?: false;
|
|
332
339
|
} | {
|
|
@@ -413,6 +420,7 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
413
420
|
recordingId?: string;
|
|
414
421
|
clientCorrelationId?: string;
|
|
415
422
|
idForEndpointAB?: string;
|
|
423
|
+
customerOrgId?: string;
|
|
416
424
|
correlationId: string;
|
|
417
425
|
additionalProperties?: false;
|
|
418
426
|
};
|
|
@@ -482,6 +490,30 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
|
|
|
482
490
|
* Clear the error cache
|
|
483
491
|
*/
|
|
484
492
|
clearErrorCache(): void;
|
|
493
|
+
/**
|
|
494
|
+
* Checks if an event should be limited based on criteria defined in the event dictionary.
|
|
495
|
+
* Returns true if the event should be sent, false if it has reached its limit.
|
|
496
|
+
* @param event - The diagnostic event object
|
|
497
|
+
* @returns boolean indicating whether the event should be sent
|
|
498
|
+
*/
|
|
499
|
+
private shouldSendEvent;
|
|
500
|
+
/**
|
|
501
|
+
* Checks the current count for a limit key and increments if under limit.
|
|
502
|
+
* @param limitKey - The unique key for this limit combination
|
|
503
|
+
* @param maxCount - Maximum allowed count
|
|
504
|
+
* @param eventDescription - Description for logging
|
|
505
|
+
* @returns true if under limit and incremented, false if at/over limit
|
|
506
|
+
*/
|
|
507
|
+
private checkAndIncrementEventCount;
|
|
508
|
+
/**
|
|
509
|
+
* Clears event limit tracking
|
|
510
|
+
*/
|
|
511
|
+
clearEventLimits(): void;
|
|
512
|
+
/**
|
|
513
|
+
* Clears event limit tracking for a specific correlationId only.
|
|
514
|
+
* Keeps limits for other meetings intact.
|
|
515
|
+
*/
|
|
516
|
+
clearEventLimitsForCorrelationId(correlationId: string): void;
|
|
485
517
|
/**
|
|
486
518
|
* Generate error payload for Client Event
|
|
487
519
|
* @param rawError
|
|
@@ -32,6 +32,7 @@ export type SubmitClientEventOptions = {
|
|
|
32
32
|
triggeredTime?: string;
|
|
33
33
|
emailInput?: ClientEmailInput;
|
|
34
34
|
userNameInput?: ClientUserNameInput;
|
|
35
|
+
vendorId?: string;
|
|
35
36
|
};
|
|
36
37
|
export type SubmitMQEOptions = {
|
|
37
38
|
meetingId: string;
|
|
@@ -41,7 +42,7 @@ export type SubmitMQEOptions = {
|
|
|
41
42
|
globalMeetingId?: string;
|
|
42
43
|
};
|
|
43
44
|
export type InternalEvent = {
|
|
44
|
-
name: 'internal.client.meetinginfo.request' | 'internal.client.meetinginfo.response' | 'internal.register.device.request' | 'internal.register.device.response' | 'internal.reset.join.latencies' | 'internal.client.meeting.click.joinbutton' | 'internal.host.meeting.participant.admitted' | 'internal.client.meeting.interstitial-window.showed' | 'internal.client.interstitial-window.click.joinbutton' | 'internal.client.add-media.turn-discovery.start' | 'internal.client.add-media.turn-discovery.end';
|
|
45
|
+
name: 'internal.client.meetinginfo.request' | 'internal.client.meetinginfo.response' | 'internal.register.device.request' | 'internal.register.device.response' | 'internal.reset.join.latencies' | 'internal.client.meeting.click.joinbutton' | 'internal.host.meeting.participant.admitted' | 'internal.client.meeting.interstitial-window.showed' | 'internal.client.interstitial-window.click.joinbutton' | 'internal.client.add-media.turn-discovery.start' | 'internal.client.add-media.turn-discovery.end' | 'internal.client.share.initiated' | 'internal.client.share.stopped';
|
|
45
46
|
payload?: never;
|
|
46
47
|
options?: never;
|
|
47
48
|
};
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"directory": "packages/@webex/internal-plugin-metrics"
|
|
12
12
|
},
|
|
13
13
|
"engines": {
|
|
14
|
-
"node": ">=
|
|
14
|
+
"node": ">=18"
|
|
15
15
|
},
|
|
16
16
|
"browserify": {
|
|
17
17
|
"transform": [
|
|
@@ -26,22 +26,21 @@
|
|
|
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.9.0-
|
|
30
|
-
"@webex/test-helper-mocha": "3.9.0-
|
|
31
|
-
"@webex/test-helper-mock-webex": "3.9.0-
|
|
32
|
-
"@webex/test-helper-test-users": "3.9.0-
|
|
29
|
+
"@webex/test-helper-chai": "3.9.0-multi-llms.1",
|
|
30
|
+
"@webex/test-helper-mocha": "3.9.0-multi-llms.1",
|
|
31
|
+
"@webex/test-helper-mock-webex": "3.9.0-multi-llms.1",
|
|
32
|
+
"@webex/test-helper-test-users": "3.9.0-multi-llms.1",
|
|
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.9.0-
|
|
39
|
-
"@webex/common-timers": "3.9.0-
|
|
40
|
-
"@webex/event-dictionary-ts": "^1.0.
|
|
41
|
-
"@webex/
|
|
42
|
-
"@webex/test-helper-
|
|
43
|
-
"@webex/
|
|
44
|
-
"@webex/webex-core": "3.9.0-webinar5k.1",
|
|
38
|
+
"@webex/common": "3.9.0-multi-llms.1",
|
|
39
|
+
"@webex/common-timers": "3.9.0-multi-llms.1",
|
|
40
|
+
"@webex/event-dictionary-ts": "^1.0.1930",
|
|
41
|
+
"@webex/test-helper-chai": "3.9.0-multi-llms.1",
|
|
42
|
+
"@webex/test-helper-mock-webex": "3.9.0-multi-llms.1",
|
|
43
|
+
"@webex/webex-core": "3.10.0-multi-llms.1",
|
|
45
44
|
"ip-anonymize": "^0.1.0",
|
|
46
45
|
"lodash": "^4.17.21",
|
|
47
46
|
"uuid": "^3.3.2"
|
|
@@ -54,5 +53,5 @@
|
|
|
54
53
|
"test:style": "eslint ./src/**/*.*",
|
|
55
54
|
"test:unit": "webex-legacy-tools test --unit --runner mocha"
|
|
56
55
|
},
|
|
57
|
-
"version": "3.
|
|
56
|
+
"version": "3.10.0-multi-llms.1"
|
|
58
57
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable class-methods-use-this */
|
|
2
2
|
/* eslint-disable valid-jsdoc */
|
|
3
3
|
import {WebexPlugin} from '@webex/webex-core';
|
|
4
|
+
import {clamp} from 'lodash';
|
|
4
5
|
|
|
5
6
|
import {MetricEventNames, PreComputedLatencies} from '../metrics.types';
|
|
6
7
|
|
|
@@ -16,6 +17,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
16
17
|
precomputedLatencies: Map<PreComputedLatencies, number>;
|
|
17
18
|
// meetingId that the current latencies are for
|
|
18
19
|
private meetingId?: string;
|
|
20
|
+
private MAX_INTEGER = 2147483647;
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* @constructor
|
|
@@ -148,15 +150,23 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
148
150
|
* @param b end
|
|
149
151
|
* @returns latency
|
|
150
152
|
*/
|
|
151
|
-
public getDiffBetweenTimestamps(
|
|
153
|
+
public getDiffBetweenTimestamps(
|
|
154
|
+
a: MetricEventNames,
|
|
155
|
+
b: MetricEventNames,
|
|
156
|
+
clampValues?: {minimum?: number; maximum?: number}
|
|
157
|
+
) {
|
|
152
158
|
const start = this.latencyTimestamps.get(a);
|
|
153
159
|
const end = this.latencyTimestamps.get(b);
|
|
154
160
|
|
|
155
|
-
if (typeof start
|
|
156
|
-
return
|
|
161
|
+
if (typeof start !== 'number' || typeof end !== 'number') {
|
|
162
|
+
return undefined;
|
|
157
163
|
}
|
|
158
164
|
|
|
159
|
-
|
|
165
|
+
const diff = end - start;
|
|
166
|
+
|
|
167
|
+
const {minimum = 0, maximum = this.MAX_INTEGER} = clampValues || {};
|
|
168
|
+
|
|
169
|
+
return clamp(diff, minimum, maximum);
|
|
160
170
|
}
|
|
161
171
|
|
|
162
172
|
/**
|
|
@@ -172,7 +182,8 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
172
182
|
public getMeetingInfoReqResp() {
|
|
173
183
|
return this.getDiffBetweenTimestamps(
|
|
174
184
|
'internal.client.meetinginfo.request',
|
|
175
|
-
'internal.client.meetinginfo.response'
|
|
185
|
+
'internal.client.meetinginfo.response',
|
|
186
|
+
{maximum: 1200000}
|
|
176
187
|
);
|
|
177
188
|
}
|
|
178
189
|
|
|
@@ -215,7 +226,8 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
215
226
|
public getCallInitJoinReq() {
|
|
216
227
|
return this.getDiffBetweenTimestamps(
|
|
217
228
|
'internal.client.interstitial-window.click.joinbutton',
|
|
218
|
-
'client.locus.join.request'
|
|
229
|
+
'client.locus.join.request',
|
|
230
|
+
{maximum: 1200000}
|
|
219
231
|
);
|
|
220
232
|
}
|
|
221
233
|
|
|
@@ -224,7 +236,11 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
224
236
|
* @returns - latency
|
|
225
237
|
*/
|
|
226
238
|
public getJoinReqResp() {
|
|
227
|
-
return this.getDiffBetweenTimestamps(
|
|
239
|
+
return this.getDiffBetweenTimestamps(
|
|
240
|
+
'client.locus.join.request',
|
|
241
|
+
'client.locus.join.response',
|
|
242
|
+
{maximum: 1200000}
|
|
243
|
+
);
|
|
228
244
|
}
|
|
229
245
|
|
|
230
246
|
/**
|
|
@@ -245,7 +261,8 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
245
261
|
public getLocalSDPGenRemoteSDPRecv() {
|
|
246
262
|
return this.getDiffBetweenTimestamps(
|
|
247
263
|
'client.media-engine.local-sdp-generated',
|
|
248
|
-
'client.media-engine.remote-sdp-received'
|
|
264
|
+
'client.media-engine.remote-sdp-received',
|
|
265
|
+
{maximum: 1200000}
|
|
249
266
|
);
|
|
250
267
|
}
|
|
251
268
|
|
|
@@ -254,7 +271,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
254
271
|
* @returns - latency
|
|
255
272
|
*/
|
|
256
273
|
public getICESetupTime() {
|
|
257
|
-
return this.getDiffBetweenTimestamps('client.ice.start', 'client.ice.end');
|
|
274
|
+
return this.getDiffBetweenTimestamps('client.ice.start', 'client.ice.end', {maximum: 1200000});
|
|
258
275
|
}
|
|
259
276
|
|
|
260
277
|
/**
|
|
@@ -299,7 +316,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
299
316
|
public getPageJMT() {
|
|
300
317
|
const latency = this.precomputedLatencies.get('internal.client.pageJMT');
|
|
301
318
|
|
|
302
|
-
return typeof latency === 'number' ? latency : undefined;
|
|
319
|
+
return typeof latency === 'number' ? clamp(latency, 0, this.MAX_INTEGER) : undefined;
|
|
303
320
|
}
|
|
304
321
|
|
|
305
322
|
/**
|
|
@@ -309,7 +326,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
309
326
|
public getDownloadTimeJMT() {
|
|
310
327
|
const latency = this.precomputedLatencies.get('internal.download.time');
|
|
311
328
|
|
|
312
|
-
return typeof latency === 'number' ? latency : undefined;
|
|
329
|
+
return typeof latency === 'number' ? clamp(latency, 0, this.MAX_INTEGER) : undefined;
|
|
313
330
|
}
|
|
314
331
|
|
|
315
332
|
/**
|
|
@@ -330,7 +347,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
330
347
|
);
|
|
331
348
|
|
|
332
349
|
if (typeof clickToInterstitialLatency === 'number') {
|
|
333
|
-
return clickToInterstitialLatency;
|
|
350
|
+
return clamp(clickToInterstitialLatency, 0, this.MAX_INTEGER);
|
|
334
351
|
}
|
|
335
352
|
|
|
336
353
|
return undefined;
|
|
@@ -354,7 +371,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
354
371
|
);
|
|
355
372
|
|
|
356
373
|
if (typeof clickToInterstitialWithUserDelayLatency === 'number') {
|
|
357
|
-
return clickToInterstitialWithUserDelayLatency;
|
|
374
|
+
return clamp(clickToInterstitialWithUserDelayLatency, 0, this.MAX_INTEGER);
|
|
358
375
|
}
|
|
359
376
|
|
|
360
377
|
return undefined;
|
|
@@ -378,7 +395,8 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
378
395
|
public getCallInitMediaEngineReady() {
|
|
379
396
|
return this.getDiffBetweenTimestamps(
|
|
380
397
|
'internal.client.interstitial-window.click.joinbutton',
|
|
381
|
-
'client.media-engine.ready'
|
|
398
|
+
'client.media-engine.ready',
|
|
399
|
+
{maximum: 1200000}
|
|
382
400
|
);
|
|
383
401
|
}
|
|
384
402
|
|
|
@@ -398,7 +416,9 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
398
416
|
const lobbyTime = typeof lobbyTimeLatency === 'number' ? lobbyTimeLatency : 0;
|
|
399
417
|
|
|
400
418
|
if (interstitialJoinClickTimestamp && connectedMedia) {
|
|
401
|
-
|
|
419
|
+
const interstitialToMediaOKJmt = connectedMedia - interstitialJoinClickTimestamp - lobbyTime;
|
|
420
|
+
|
|
421
|
+
return clamp(interstitialToMediaOKJmt, 0, this.MAX_INTEGER);
|
|
402
422
|
}
|
|
403
423
|
|
|
404
424
|
return undefined;
|
|
@@ -413,7 +433,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
413
433
|
const interstitialToJoinOk = this.getInterstitialToJoinOK();
|
|
414
434
|
|
|
415
435
|
if (typeof clickToInterstitial === 'number' && typeof interstitialToJoinOk === 'number') {
|
|
416
|
-
return clickToInterstitial + interstitialToJoinOk;
|
|
436
|
+
return clamp(clickToInterstitial + interstitialToJoinOk, 0, this.MAX_INTEGER);
|
|
417
437
|
}
|
|
418
438
|
|
|
419
439
|
return undefined;
|
|
@@ -431,7 +451,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
431
451
|
typeof clickToInterstitialWithUserDelay === 'number' &&
|
|
432
452
|
typeof interstitialToJoinOk === 'number'
|
|
433
453
|
) {
|
|
434
|
-
return clickToInterstitialWithUserDelay + interstitialToJoinOk;
|
|
454
|
+
return clamp(clickToInterstitialWithUserDelay + interstitialToJoinOk, 0, this.MAX_INTEGER);
|
|
435
455
|
}
|
|
436
456
|
|
|
437
457
|
return undefined;
|
|
@@ -446,7 +466,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
446
466
|
const ICESetupTime = this.getICESetupTime();
|
|
447
467
|
|
|
448
468
|
if (joinReqResp && ICESetupTime) {
|
|
449
|
-
return joinReqResp + ICESetupTime;
|
|
469
|
+
return clamp(joinReqResp + ICESetupTime, 0, this.MAX_INTEGER);
|
|
450
470
|
}
|
|
451
471
|
|
|
452
472
|
return undefined;
|
|
@@ -463,12 +483,16 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
463
483
|
const lobbyTime = this.getStayLobbyTime();
|
|
464
484
|
|
|
465
485
|
if (clickToInterstitial && interstitialToJoinOk && joinConfJMT) {
|
|
466
|
-
const totalMediaJMT =
|
|
486
|
+
const totalMediaJMT = clamp(
|
|
487
|
+
clickToInterstitial + interstitialToJoinOk + joinConfJMT,
|
|
488
|
+
0,
|
|
489
|
+
Infinity
|
|
490
|
+
);
|
|
467
491
|
if (this.getMeeting()?.allowMediaInLobby) {
|
|
468
|
-
return totalMediaJMT;
|
|
492
|
+
return clamp(totalMediaJMT, 0, this.MAX_INTEGER);
|
|
469
493
|
}
|
|
470
494
|
|
|
471
|
-
return totalMediaJMT - lobbyTime;
|
|
495
|
+
return clamp(totalMediaJMT - lobbyTime, 0, this.MAX_INTEGER);
|
|
472
496
|
}
|
|
473
497
|
|
|
474
498
|
return undefined;
|
|
@@ -484,7 +508,11 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
484
508
|
const joinConfJMT = this.getJoinConfJMT();
|
|
485
509
|
|
|
486
510
|
if (clickToInterstitialWithUserDelay && interstitialToJoinOk && joinConfJMT) {
|
|
487
|
-
return
|
|
511
|
+
return clamp(
|
|
512
|
+
clickToInterstitialWithUserDelay + interstitialToJoinOk + joinConfJMT,
|
|
513
|
+
0,
|
|
514
|
+
this.MAX_INTEGER
|
|
515
|
+
);
|
|
488
516
|
}
|
|
489
517
|
|
|
490
518
|
return undefined;
|
|
@@ -499,7 +527,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
499
527
|
const joinConfJMT = this.getJoinConfJMT();
|
|
500
528
|
|
|
501
529
|
if (typeof interstitialToJoinOk === 'number' && typeof joinConfJMT === 'number') {
|
|
502
|
-
return interstitialToJoinOk - joinConfJMT;
|
|
530
|
+
return clamp(interstitialToJoinOk - joinConfJMT, 0, this.MAX_INTEGER);
|
|
503
531
|
}
|
|
504
532
|
|
|
505
533
|
return undefined;
|
|
@@ -526,7 +554,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
526
554
|
const reachablityClusterReqResp = this.precomputedLatencies.get('internal.get.cluster.time');
|
|
527
555
|
|
|
528
556
|
return typeof reachablityClusterReqResp === 'number'
|
|
529
|
-
? Math.floor(reachablityClusterReqResp)
|
|
557
|
+
? clamp(Math.floor(reachablityClusterReqResp), 0, this.MAX_INTEGER)
|
|
530
558
|
: undefined;
|
|
531
559
|
}
|
|
532
560
|
|
|
@@ -544,13 +572,25 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
544
572
|
return this.getDiffBetweenTimestamps('client.locus.join.response', 'client.media.tx.start');
|
|
545
573
|
}
|
|
546
574
|
|
|
575
|
+
/**
|
|
576
|
+
* Time from share initiation to share stop (ms).
|
|
577
|
+
*/
|
|
578
|
+
public getShareDuration() {
|
|
579
|
+
return this.getDiffBetweenTimestamps(
|
|
580
|
+
'internal.client.share.initiated',
|
|
581
|
+
'internal.client.share.stopped'
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
|
|
547
585
|
/**
|
|
548
586
|
* Total latency for all exchange ci token.
|
|
549
587
|
*/
|
|
550
588
|
public getExchangeCITokenJMT() {
|
|
551
589
|
const exchangeCITokenJMT = this.precomputedLatencies.get('internal.exchange.ci.token.time');
|
|
552
590
|
|
|
553
|
-
return typeof exchangeCITokenJMT === 'number'
|
|
591
|
+
return typeof exchangeCITokenJMT === 'number'
|
|
592
|
+
? clamp(Math.floor(exchangeCITokenJMT), 0, this.MAX_INTEGER)
|
|
593
|
+
: undefined;
|
|
554
594
|
}
|
|
555
595
|
|
|
556
596
|
/**
|
|
@@ -560,7 +600,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
560
600
|
const refreshCaptchaReqResp = this.precomputedLatencies.get('internal.refresh.captcha.time');
|
|
561
601
|
|
|
562
602
|
return typeof refreshCaptchaReqResp === 'number'
|
|
563
|
-
? Math.floor(refreshCaptchaReqResp)
|
|
603
|
+
? clamp(Math.floor(refreshCaptchaReqResp), 0, this.MAX_INTEGER)
|
|
564
604
|
: undefined;
|
|
565
605
|
}
|
|
566
606
|
|
|
@@ -574,7 +614,7 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
574
614
|
);
|
|
575
615
|
|
|
576
616
|
return typeof downloadIntelligenceModelsReqResp === 'number'
|
|
577
|
-
? Math.floor(downloadIntelligenceModelsReqResp)
|
|
617
|
+
? clamp(Math.floor(downloadIntelligenceModelsReqResp), 0, this.MAX_INTEGER)
|
|
578
618
|
: undefined;
|
|
579
619
|
}
|
|
580
620
|
|
|
@@ -586,6 +626,6 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
|
|
|
586
626
|
public getOtherAppApiReqResp() {
|
|
587
627
|
const otherAppApiJMT = this.precomputedLatencies.get('internal.other.app.api.time');
|
|
588
628
|
|
|
589
|
-
return otherAppApiJMT > 0 ? Math.floor(otherAppApiJMT) : undefined;
|
|
629
|
+
return otherAppApiJMT > 0 ? clamp(Math.floor(otherAppApiJMT), 0, this.MAX_INTEGER) : undefined;
|
|
590
630
|
}
|
|
591
631
|
}
|