@webex/internal-plugin-metrics 3.0.0-beta.270 → 3.0.0-beta.271

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.
@@ -213,6 +213,16 @@ var CallDiagnosticLatencies = /*#__PURE__*/function (_WebexPlugin) {
213
213
  return undefined;
214
214
  }
215
215
 
216
+ /**
217
+ * Time taken to do turn discovery
218
+ * @returns - latency
219
+ */
220
+ }, {
221
+ key: "getTurnDiscoveryTime",
222
+ value: function getTurnDiscoveryTime() {
223
+ return this.getDiffBetweenTimestamps('internal.client.add-media.turn-discovery.start', 'internal.client.add-media.turn-discovery.end');
224
+ }
225
+
216
226
  /**
217
227
  * Local SDP Generated Remote SDP REceived
218
228
  * @returns - latency
@@ -1 +1 @@
1
- {"version":3,"names":["CallDiagnosticLatencies","args","latencyTimestamps","precomputedLatencies","clear","meetingId","webex","meetings","meetingCollection","get","undefined","key","value","Date","getTime","options","setMeetingId","saveFirstTimestampOnly","set","has","a","b","start","end","getDiffBetweenTimestamps","interstitialJoinClickTimestamp","mediaFlowStartedTimestamp","Math","min","lobbyTime","getStayLobbyTime","clickToInterstitial","getClickToInterstitial","interstitialToJoinOk","getInterstitialToJoinOK","joinReqResp","getJoinReqResp","ICESetupTime","getICESetupTime","joinConfJMT","getJoinConfJMT","totalMediaJMT","getMeeting","allowMediaInLobby","WebexPlugin"],"sources":["call-diagnostic-metrics-latencies.ts"],"sourcesContent":["/* eslint-disable class-methods-use-this */\n/* eslint-disable valid-jsdoc */\nimport {WebexPlugin} from '@webex/webex-core';\n\nimport {MetricEventNames} from '../metrics.types';\n\n// we only care about client event and feature event for now\n\n/**\n * @description Helper class to store latencies timestamp and to calculate various latencies for CA.\n * @exports\n * @class CallDiagnosticLatencies\n */\nexport default class CallDiagnosticLatencies extends WebexPlugin {\n latencyTimestamps: Map<MetricEventNames, number>;\n precomputedLatencies: Map<string, number>;\n // meetingId that the current latencies are for\n private meetingId?: string;\n\n /**\n * @constructor\n */\n constructor(...args) {\n super(...args);\n this.latencyTimestamps = new Map();\n this.precomputedLatencies = new Map();\n }\n\n /**\n * Clear timestamps\n */\n public clearTimestamps() {\n this.latencyTimestamps.clear();\n }\n\n /**\n * Associate current latencies with a meeting id\n * @param meetingId\n */\n private setMeetingId(meetingId: string) {\n this.meetingId = meetingId;\n }\n\n /**\n * Returns the meeting object associated with current latencies\n * @returns meeting object\n */\n private getMeeting() {\n if (this.meetingId) {\n // @ts-ignore\n return this.webex.meetings.meetingCollection.get(this.meetingId);\n }\n\n return undefined;\n }\n\n /**\n * Store timestamp value\n * @param key - key\n * @param value -value\n * @throws\n * @returns\n */\n public saveTimestamp({\n key,\n value = new Date().getTime(),\n options = {},\n }: {\n key: MetricEventNames;\n value?: number;\n options?: {meetingId?: string};\n }) {\n // save the meetingId so we can use the meeting object in latency calculations if needed\n const {meetingId} = options;\n if (meetingId) {\n this.setMeetingId(meetingId);\n }\n // for some events we're only interested in the first timestamp not last\n // as these events can happen multiple times\n if (key === 'client.media.rx.start' || key === 'client.media.tx.start') {\n this.saveFirstTimestampOnly(key, value);\n } else {\n this.latencyTimestamps.set(key, value);\n }\n }\n\n /**\n * Store precomputed latency value\n * @param key - key\n * @param value -value\n * @throws\n * @returns\n */\n public saveLatency(key: string, value: number) {\n this.precomputedLatencies.set(key, value);\n }\n\n /**\n * Store only the first timestamp value for the given key\n * @param key - key\n * @param value -value\n * @throws\n * @returns\n */\n saveFirstTimestampOnly(key: MetricEventNames, value: number = new Date().getTime()) {\n if (this.latencyTimestamps.has(key)) {\n return;\n }\n this.latencyTimestamps.set(key, value);\n }\n\n /**\n * Helper to calculate end - start\n * @param a start\n * @param b end\n * @returns latency\n */\n public getDiffBetweenTimestamps(a: MetricEventNames, b: MetricEventNames) {\n const start = this.latencyTimestamps.get(a);\n const end = this.latencyTimestamps.get(b);\n if (start && end) {\n return end - start;\n }\n\n return undefined;\n }\n\n /**\n * Meeting Info Request\n * @note Meeting Info request happen not just in the join phase. CA requires\n * metrics around meeting info request that are only part of join phase.\n * This internal.* event is used to track the real timestamps\n * (when the actual request/response happen). This is because the actual CA event is\n * sent inside the join method on the meeting object based on some logic, but that's not exactly when\n * those events are actually fired. The logic only confirms that they have happened, and we send them over.\n * @returns - latency\n */\n public getMeetingInfoReqResp() {\n return this.getDiffBetweenTimestamps(\n 'internal.client.meetinginfo.request',\n 'internal.client.meetinginfo.response'\n );\n }\n\n /**\n * Interstitial Time\n * @returns - latency\n */\n public getShowInterstitialTime() {\n return this.getDiffBetweenTimestamps(\n 'client.interstitial-window.start-launch',\n 'internal.client.interstitial-window.click.joinbutton'\n );\n }\n\n /**\n * Call Init Join Request\n * @returns - latency\n */\n public getCallInitJoinReq() {\n return this.getDiffBetweenTimestamps(\n 'internal.client.interstitial-window.click.joinbutton',\n 'client.locus.join.request'\n );\n }\n\n /**\n * Locus Join Request\n * @returns - latency\n */\n public getJoinReqResp() {\n return this.getDiffBetweenTimestamps('client.locus.join.request', 'client.locus.join.response');\n }\n\n /**\n * Locus Join Response Sent Received\n * @returns - latency\n */\n public getJoinRespSentReceived() {\n // TODO: not clear SPARK-440554\n return undefined;\n }\n\n /**\n * Local SDP Generated Remote SDP REceived\n * @returns - latency\n */\n public getLocalSDPGenRemoteSDPRecv() {\n return this.getDiffBetweenTimestamps(\n 'client.media-engine.local-sdp-generated',\n 'client.media-engine.remote-sdp-received'\n );\n }\n\n /**\n * ICE Setup Time\n * @returns - latency\n */\n public getICESetupTime() {\n return this.getDiffBetweenTimestamps('client.ice.start', 'client.ice.end');\n }\n\n /**\n * Audio ICE time\n * @returns - latency\n */\n public getAudioICESetupTime() {\n return this.getDiffBetweenTimestamps('client.ice.start', 'client.ice.end');\n }\n\n /**\n * Video ICE Time\n * @returns - latency\n */\n public getVideoICESetupTime() {\n return this.getDiffBetweenTimestamps('client.ice.start', 'client.ice.end');\n }\n\n /**\n * Share ICE Time\n * @returns - latency\n */\n public getShareICESetupTime() {\n return this.getDiffBetweenTimestamps('client.ice.start', 'client.ice.end');\n }\n\n /**\n * Stay Lobby Time\n * @returns - latency\n */\n public getStayLobbyTime() {\n return this.getDiffBetweenTimestamps(\n 'client.locus.join.response',\n 'internal.host.meeting.participant.admitted'\n );\n }\n\n /**\n * Page JMT\n * @returns - latency\n */\n public getPageJMT() {\n return this.precomputedLatencies.get('internal.client.pageJMT') || undefined;\n }\n\n /**\n * Click To Interstitial\n * @returns - latency\n */\n public getClickToInterstitial() {\n // for normal join (where green join button exists before interstitial, i.e reminder, space list etc)\n if (this.latencyTimestamps.get('internal.client.meeting.click.joinbutton')) {\n return this.getDiffBetweenTimestamps(\n 'internal.client.meeting.click.joinbutton',\n 'internal.client.meeting.interstitial-window.showed'\n );\n }\n\n // for cross launch and guest flows\n return this.precomputedLatencies.get('internal.click.to.interstitial') || undefined;\n }\n\n /**\n * Interstitial To Join Ok\n * @returns - latency\n */\n public getInterstitialToJoinOK() {\n return this.getDiffBetweenTimestamps(\n 'internal.client.interstitial-window.click.joinbutton',\n 'client.locus.join.response'\n );\n }\n\n /**\n * Call Init To MediaEngineReady\n * @returns - latency\n */\n public getCallInitMediaEngineReady() {\n return this.getDiffBetweenTimestamps(\n 'internal.client.interstitial-window.click.joinbutton',\n 'client.media-engine.ready'\n );\n }\n\n /**\n * Interstitial To Media Ok\n * @returns - latency\n */\n public getInterstitialToMediaOKJMT() {\n const interstitialJoinClickTimestamp = this.latencyTimestamps.get(\n 'internal.client.interstitial-window.click.joinbutton'\n );\n\n // get the first timestamp\n const mediaFlowStartedTimestamp = Math.min(\n this.latencyTimestamps.get('client.media.rx.start'),\n this.latencyTimestamps.get('client.media.tx.start')\n );\n\n const lobbyTime = this.getStayLobbyTime() || 0;\n\n if (interstitialJoinClickTimestamp && mediaFlowStartedTimestamp) {\n return mediaFlowStartedTimestamp - interstitialJoinClickTimestamp - lobbyTime;\n }\n\n return undefined;\n }\n\n /**\n * Total JMT\n * @returns - latency\n */\n public getTotalJMT() {\n const clickToInterstitial = this.getClickToInterstitial();\n const interstitialToJoinOk = this.getInterstitialToJoinOK();\n\n if (clickToInterstitial && interstitialToJoinOk) {\n return clickToInterstitial + interstitialToJoinOk;\n }\n\n return undefined;\n }\n\n /**\n * Join Conf JMT\n * @returns - latency\n */\n public getJoinConfJMT() {\n const joinReqResp = this.getJoinReqResp();\n const ICESetupTime = this.getICESetupTime();\n\n if (joinReqResp && ICESetupTime) {\n return joinReqResp + ICESetupTime;\n }\n\n return undefined;\n }\n\n /**\n * Total Media JMT\n * @returns - latency\n */\n public getTotalMediaJMT() {\n const clickToInterstitial = this.getClickToInterstitial();\n const interstitialToJoinOk = this.getInterstitialToJoinOK();\n const joinConfJMT = this.getJoinConfJMT();\n const lobbyTime = this.getStayLobbyTime();\n\n if (clickToInterstitial && interstitialToJoinOk && joinConfJMT) {\n const totalMediaJMT = clickToInterstitial + interstitialToJoinOk + joinConfJMT;\n if (this.getMeeting()?.allowMediaInLobby) {\n return totalMediaJMT;\n }\n\n return totalMediaJMT - lobbyTime;\n }\n\n return undefined;\n }\n\n /**\n * Client JMT\n * @returns - latency\n */\n public getClientJMT() {\n const interstitialToJoinOk = this.getInterstitialToJoinOK();\n const joinConfJMT = this.getJoinConfJMT();\n\n if (interstitialToJoinOk && joinConfJMT) {\n return interstitialToJoinOk - joinConfJMT;\n }\n\n return undefined;\n }\n\n /**\n * Audio setup delay receive\n */\n public getAudioJoinRespRxStart() {\n return this.getDiffBetweenTimestamps('client.locus.join.response', 'client.media.rx.start');\n }\n\n /**\n * Video setup delay receive\n */\n public getVideoJoinRespRxStart() {\n return this.getDiffBetweenTimestamps('client.locus.join.response', 'client.media.rx.start');\n }\n\n /**\n * Audio setup delay transmit\n */\n public getAudioJoinRespTxStart() {\n return this.getDiffBetweenTimestamps('client.locus.join.response', 'client.media.tx.start');\n }\n\n /**\n * Video setup delay transmit\n */\n public getVideoJoinRespTxStart() {\n return this.getDiffBetweenTimestamps('client.locus.join.response', 'client.media.tx.start');\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"names":["CallDiagnosticLatencies","args","latencyTimestamps","precomputedLatencies","clear","meetingId","webex","meetings","meetingCollection","get","undefined","key","value","Date","getTime","options","setMeetingId","saveFirstTimestampOnly","set","has","a","b","start","end","getDiffBetweenTimestamps","interstitialJoinClickTimestamp","mediaFlowStartedTimestamp","Math","min","lobbyTime","getStayLobbyTime","clickToInterstitial","getClickToInterstitial","interstitialToJoinOk","getInterstitialToJoinOK","joinReqResp","getJoinReqResp","ICESetupTime","getICESetupTime","joinConfJMT","getJoinConfJMT","totalMediaJMT","getMeeting","allowMediaInLobby","WebexPlugin"],"sources":["call-diagnostic-metrics-latencies.ts"],"sourcesContent":["/* eslint-disable class-methods-use-this */\n/* eslint-disable valid-jsdoc */\nimport {WebexPlugin} from '@webex/webex-core';\n\nimport {MetricEventNames} from '../metrics.types';\n\n// we only care about client event and feature event for now\n\n/**\n * @description Helper class to store latencies timestamp and to calculate various latencies for CA.\n * @exports\n * @class CallDiagnosticLatencies\n */\nexport default class CallDiagnosticLatencies extends WebexPlugin {\n latencyTimestamps: Map<MetricEventNames, number>;\n precomputedLatencies: Map<string, number>;\n // meetingId that the current latencies are for\n private meetingId?: string;\n\n /**\n * @constructor\n */\n constructor(...args) {\n super(...args);\n this.latencyTimestamps = new Map();\n this.precomputedLatencies = new Map();\n }\n\n /**\n * Clear timestamps\n */\n public clearTimestamps() {\n this.latencyTimestamps.clear();\n }\n\n /**\n * Associate current latencies with a meeting id\n * @param meetingId\n */\n private setMeetingId(meetingId: string) {\n this.meetingId = meetingId;\n }\n\n /**\n * Returns the meeting object associated with current latencies\n * @returns meeting object\n */\n private getMeeting() {\n if (this.meetingId) {\n // @ts-ignore\n return this.webex.meetings.meetingCollection.get(this.meetingId);\n }\n\n return undefined;\n }\n\n /**\n * Store timestamp value\n * @param key - key\n * @param value -value\n * @throws\n * @returns\n */\n public saveTimestamp({\n key,\n value = new Date().getTime(),\n options = {},\n }: {\n key: MetricEventNames;\n value?: number;\n options?: {meetingId?: string};\n }) {\n // save the meetingId so we can use the meeting object in latency calculations if needed\n const {meetingId} = options;\n if (meetingId) {\n this.setMeetingId(meetingId);\n }\n // for some events we're only interested in the first timestamp not last\n // as these events can happen multiple times\n if (key === 'client.media.rx.start' || key === 'client.media.tx.start') {\n this.saveFirstTimestampOnly(key, value);\n } else {\n this.latencyTimestamps.set(key, value);\n }\n }\n\n /**\n * Store precomputed latency value\n * @param key - key\n * @param value -value\n * @throws\n * @returns\n */\n public saveLatency(key: string, value: number) {\n this.precomputedLatencies.set(key, value);\n }\n\n /**\n * Store only the first timestamp value for the given key\n * @param key - key\n * @param value -value\n * @throws\n * @returns\n */\n saveFirstTimestampOnly(key: MetricEventNames, value: number = new Date().getTime()) {\n if (this.latencyTimestamps.has(key)) {\n return;\n }\n this.latencyTimestamps.set(key, value);\n }\n\n /**\n * Helper to calculate end - start\n * @param a start\n * @param b end\n * @returns latency\n */\n public getDiffBetweenTimestamps(a: MetricEventNames, b: MetricEventNames) {\n const start = this.latencyTimestamps.get(a);\n const end = this.latencyTimestamps.get(b);\n if (start && end) {\n return end - start;\n }\n\n return undefined;\n }\n\n /**\n * Meeting Info Request\n * @note Meeting Info request happen not just in the join phase. CA requires\n * metrics around meeting info request that are only part of join phase.\n * This internal.* event is used to track the real timestamps\n * (when the actual request/response happen). This is because the actual CA event is\n * sent inside the join method on the meeting object based on some logic, but that's not exactly when\n * those events are actually fired. The logic only confirms that they have happened, and we send them over.\n * @returns - latency\n */\n public getMeetingInfoReqResp() {\n return this.getDiffBetweenTimestamps(\n 'internal.client.meetinginfo.request',\n 'internal.client.meetinginfo.response'\n );\n }\n\n /**\n * Interstitial Time\n * @returns - latency\n */\n public getShowInterstitialTime() {\n return this.getDiffBetweenTimestamps(\n 'client.interstitial-window.start-launch',\n 'internal.client.interstitial-window.click.joinbutton'\n );\n }\n\n /**\n * Call Init Join Request\n * @returns - latency\n */\n public getCallInitJoinReq() {\n return this.getDiffBetweenTimestamps(\n 'internal.client.interstitial-window.click.joinbutton',\n 'client.locus.join.request'\n );\n }\n\n /**\n * Locus Join Request\n * @returns - latency\n */\n public getJoinReqResp() {\n return this.getDiffBetweenTimestamps('client.locus.join.request', 'client.locus.join.response');\n }\n\n /**\n * Locus Join Response Sent Received\n * @returns - latency\n */\n public getJoinRespSentReceived() {\n // TODO: not clear SPARK-440554\n return undefined;\n }\n\n /**\n * Time taken to do turn discovery\n * @returns - latency\n */\n public getTurnDiscoveryTime() {\n return this.getDiffBetweenTimestamps(\n 'internal.client.add-media.turn-discovery.start',\n 'internal.client.add-media.turn-discovery.end'\n );\n }\n\n /**\n * Local SDP Generated Remote SDP REceived\n * @returns - latency\n */\n public getLocalSDPGenRemoteSDPRecv() {\n return this.getDiffBetweenTimestamps(\n 'client.media-engine.local-sdp-generated',\n 'client.media-engine.remote-sdp-received'\n );\n }\n\n /**\n * ICE Setup Time\n * @returns - latency\n */\n public getICESetupTime() {\n return this.getDiffBetweenTimestamps('client.ice.start', 'client.ice.end');\n }\n\n /**\n * Audio ICE time\n * @returns - latency\n */\n public getAudioICESetupTime() {\n return this.getDiffBetweenTimestamps('client.ice.start', 'client.ice.end');\n }\n\n /**\n * Video ICE Time\n * @returns - latency\n */\n public getVideoICESetupTime() {\n return this.getDiffBetweenTimestamps('client.ice.start', 'client.ice.end');\n }\n\n /**\n * Share ICE Time\n * @returns - latency\n */\n public getShareICESetupTime() {\n return this.getDiffBetweenTimestamps('client.ice.start', 'client.ice.end');\n }\n\n /**\n * Stay Lobby Time\n * @returns - latency\n */\n public getStayLobbyTime() {\n return this.getDiffBetweenTimestamps(\n 'client.locus.join.response',\n 'internal.host.meeting.participant.admitted'\n );\n }\n\n /**\n * Page JMT\n * @returns - latency\n */\n public getPageJMT() {\n return this.precomputedLatencies.get('internal.client.pageJMT') || undefined;\n }\n\n /**\n * Click To Interstitial\n * @returns - latency\n */\n public getClickToInterstitial() {\n // for normal join (where green join button exists before interstitial, i.e reminder, space list etc)\n if (this.latencyTimestamps.get('internal.client.meeting.click.joinbutton')) {\n return this.getDiffBetweenTimestamps(\n 'internal.client.meeting.click.joinbutton',\n 'internal.client.meeting.interstitial-window.showed'\n );\n }\n\n // for cross launch and guest flows\n return this.precomputedLatencies.get('internal.click.to.interstitial') || undefined;\n }\n\n /**\n * Interstitial To Join Ok\n * @returns - latency\n */\n public getInterstitialToJoinOK() {\n return this.getDiffBetweenTimestamps(\n 'internal.client.interstitial-window.click.joinbutton',\n 'client.locus.join.response'\n );\n }\n\n /**\n * Call Init To MediaEngineReady\n * @returns - latency\n */\n public getCallInitMediaEngineReady() {\n return this.getDiffBetweenTimestamps(\n 'internal.client.interstitial-window.click.joinbutton',\n 'client.media-engine.ready'\n );\n }\n\n /**\n * Interstitial To Media Ok\n * @returns - latency\n */\n public getInterstitialToMediaOKJMT() {\n const interstitialJoinClickTimestamp = this.latencyTimestamps.get(\n 'internal.client.interstitial-window.click.joinbutton'\n );\n\n // get the first timestamp\n const mediaFlowStartedTimestamp = Math.min(\n this.latencyTimestamps.get('client.media.rx.start'),\n this.latencyTimestamps.get('client.media.tx.start')\n );\n\n const lobbyTime = this.getStayLobbyTime() || 0;\n\n if (interstitialJoinClickTimestamp && mediaFlowStartedTimestamp) {\n return mediaFlowStartedTimestamp - interstitialJoinClickTimestamp - lobbyTime;\n }\n\n return undefined;\n }\n\n /**\n * Total JMT\n * @returns - latency\n */\n public getTotalJMT() {\n const clickToInterstitial = this.getClickToInterstitial();\n const interstitialToJoinOk = this.getInterstitialToJoinOK();\n\n if (clickToInterstitial && interstitialToJoinOk) {\n return clickToInterstitial + interstitialToJoinOk;\n }\n\n return undefined;\n }\n\n /**\n * Join Conf JMT\n * @returns - latency\n */\n public getJoinConfJMT() {\n const joinReqResp = this.getJoinReqResp();\n const ICESetupTime = this.getICESetupTime();\n\n if (joinReqResp && ICESetupTime) {\n return joinReqResp + ICESetupTime;\n }\n\n return undefined;\n }\n\n /**\n * Total Media JMT\n * @returns - latency\n */\n public getTotalMediaJMT() {\n const clickToInterstitial = this.getClickToInterstitial();\n const interstitialToJoinOk = this.getInterstitialToJoinOK();\n const joinConfJMT = this.getJoinConfJMT();\n const lobbyTime = this.getStayLobbyTime();\n\n if (clickToInterstitial && interstitialToJoinOk && joinConfJMT) {\n const totalMediaJMT = clickToInterstitial + interstitialToJoinOk + joinConfJMT;\n if (this.getMeeting()?.allowMediaInLobby) {\n return totalMediaJMT;\n }\n\n return totalMediaJMT - lobbyTime;\n }\n\n return undefined;\n }\n\n /**\n * Client JMT\n * @returns - latency\n */\n public getClientJMT() {\n const interstitialToJoinOk = this.getInterstitialToJoinOK();\n const joinConfJMT = this.getJoinConfJMT();\n\n if (interstitialToJoinOk && joinConfJMT) {\n return interstitialToJoinOk - joinConfJMT;\n }\n\n return undefined;\n }\n\n /**\n * Audio setup delay receive\n */\n public getAudioJoinRespRxStart() {\n return this.getDiffBetweenTimestamps('client.locus.join.response', 'client.media.rx.start');\n }\n\n /**\n * Video setup delay receive\n */\n public getVideoJoinRespRxStart() {\n return this.getDiffBetweenTimestamps('client.locus.join.response', 'client.media.rx.start');\n }\n\n /**\n * Audio setup delay transmit\n */\n public getAudioJoinRespTxStart() {\n return this.getDiffBetweenTimestamps('client.locus.join.response', 'client.media.tx.start');\n }\n\n /**\n * Video setup delay transmit\n */\n public getVideoJoinRespTxStart() {\n return this.getDiffBetweenTimestamps('client.locus.join.response', 'client.media.tx.start');\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAEA;AAA8C;AAAA;AAI9C;AAEA;AACA;AACA;AACA;AACA;AAJA,IAKqBA,uBAAuB;EAAA;EAAA;EAG1C;;EAGA;AACF;AACA;EACE,mCAAqB;IAAA;IAAA;IAAA,kCAANC,IAAI;MAAJA,IAAI;IAAA;IACjB,gDAASA,IAAI;IAAE;IAAA;IAAA;IACf,MAAKC,iBAAiB,GAAG,kBAAS;IAClC,MAAKC,oBAAoB,GAAG,kBAAS;IAAC;EACxC;;EAEA;AACF;AACA;EAFE;IAAA;IAAA,OAGA,2BAAyB;MACvB,IAAI,CAACD,iBAAiB,CAACE,KAAK,EAAE;IAChC;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,sBAAqBC,SAAiB,EAAE;MACtC,IAAI,CAACA,SAAS,GAAGA,SAAS;IAC5B;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,sBAAqB;MACnB,IAAI,IAAI,CAACA,SAAS,EAAE;QAClB;QACA,OAAO,IAAI,CAACC,KAAK,CAACC,QAAQ,CAACC,iBAAiB,CAACC,GAAG,CAAC,IAAI,CAACJ,SAAS,CAAC;MAClE;MAEA,OAAOK,SAAS;IAClB;;IAEA;AACF;AACA;AACA;AACA;AACA;AACA;EANE;IAAA;IAAA,OAOA,6BAQG;MAAA,IAPDC,GAAG,QAAHA,GAAG;QAAA,kBACHC,KAAK;QAALA,KAAK,2BAAG,IAAIC,IAAI,EAAE,CAACC,OAAO,EAAE;QAAA,oBAC5BC,OAAO;QAAPA,OAAO,6BAAG,CAAC,CAAC;MAMZ;MACA,IAAOV,SAAS,GAAIU,OAAO,CAApBV,SAAS;MAChB,IAAIA,SAAS,EAAE;QACb,IAAI,CAACW,YAAY,CAACX,SAAS,CAAC;MAC9B;MACA;MACA;MACA,IAAIM,GAAG,KAAK,uBAAuB,IAAIA,GAAG,KAAK,uBAAuB,EAAE;QACtE,IAAI,CAACM,sBAAsB,CAACN,GAAG,EAAEC,KAAK,CAAC;MACzC,CAAC,MAAM;QACL,IAAI,CAACV,iBAAiB,CAACgB,GAAG,CAACP,GAAG,EAAEC,KAAK,CAAC;MACxC;IACF;;IAEA;AACF;AACA;AACA;AACA;AACA;AACA;EANE;IAAA;IAAA,OAOA,qBAAmBD,GAAW,EAAEC,KAAa,EAAE;MAC7C,IAAI,CAACT,oBAAoB,CAACe,GAAG,CAACP,GAAG,EAAEC,KAAK,CAAC;IAC3C;;IAEA;AACF;AACA;AACA;AACA;AACA;AACA;EANE;IAAA;IAAA,OAOA,gCAAuBD,GAAqB,EAAwC;MAAA,IAAtCC,KAAa,uEAAG,IAAIC,IAAI,EAAE,CAACC,OAAO,EAAE;MAChF,IAAI,IAAI,CAACZ,iBAAiB,CAACiB,GAAG,CAACR,GAAG,CAAC,EAAE;QACnC;MACF;MACA,IAAI,CAACT,iBAAiB,CAACgB,GAAG,CAACP,GAAG,EAAEC,KAAK,CAAC;IACxC;;IAEA;AACF;AACA;AACA;AACA;AACA;EALE;IAAA;IAAA,OAMA,kCAAgCQ,CAAmB,EAAEC,CAAmB,EAAE;MACxE,IAAMC,KAAK,GAAG,IAAI,CAACpB,iBAAiB,CAACO,GAAG,CAACW,CAAC,CAAC;MAC3C,IAAMG,GAAG,GAAG,IAAI,CAACrB,iBAAiB,CAACO,GAAG,CAACY,CAAC,CAAC;MACzC,IAAIC,KAAK,IAAIC,GAAG,EAAE;QAChB,OAAOA,GAAG,GAAGD,KAAK;MACpB;MAEA,OAAOZ,SAAS;IAClB;;IAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EATE;IAAA;IAAA,OAUA,iCAA+B;MAC7B,OAAO,IAAI,CAACc,wBAAwB,CAClC,qCAAqC,EACrC,sCAAsC,CACvC;IACH;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,mCAAiC;MAC/B,OAAO,IAAI,CAACA,wBAAwB,CAClC,yCAAyC,EACzC,sDAAsD,CACvD;IACH;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,8BAA4B;MAC1B,OAAO,IAAI,CAACA,wBAAwB,CAClC,sDAAsD,EACtD,2BAA2B,CAC5B;IACH;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,0BAAwB;MACtB,OAAO,IAAI,CAACA,wBAAwB,CAAC,2BAA2B,EAAE,4BAA4B,CAAC;IACjG;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,mCAAiC;MAC/B;MACA,OAAOd,SAAS;IAClB;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,gCAA8B;MAC5B,OAAO,IAAI,CAACc,wBAAwB,CAClC,gDAAgD,EAChD,8CAA8C,CAC/C;IACH;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,uCAAqC;MACnC,OAAO,IAAI,CAACA,wBAAwB,CAClC,yCAAyC,EACzC,yCAAyC,CAC1C;IACH;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,2BAAyB;MACvB,OAAO,IAAI,CAACA,wBAAwB,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IAC5E;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,gCAA8B;MAC5B,OAAO,IAAI,CAACA,wBAAwB,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IAC5E;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,gCAA8B;MAC5B,OAAO,IAAI,CAACA,wBAAwB,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IAC5E;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,gCAA8B;MAC5B,OAAO,IAAI,CAACA,wBAAwB,CAAC,kBAAkB,EAAE,gBAAgB,CAAC;IAC5E;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,4BAA0B;MACxB,OAAO,IAAI,CAACA,wBAAwB,CAClC,4BAA4B,EAC5B,4CAA4C,CAC7C;IACH;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,sBAAoB;MAClB,OAAO,IAAI,CAACrB,oBAAoB,CAACM,GAAG,CAAC,yBAAyB,CAAC,IAAIC,SAAS;IAC9E;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,kCAAgC;MAC9B;MACA,IAAI,IAAI,CAACR,iBAAiB,CAACO,GAAG,CAAC,0CAA0C,CAAC,EAAE;QAC1E,OAAO,IAAI,CAACe,wBAAwB,CAClC,0CAA0C,EAC1C,oDAAoD,CACrD;MACH;;MAEA;MACA,OAAO,IAAI,CAACrB,oBAAoB,CAACM,GAAG,CAAC,gCAAgC,CAAC,IAAIC,SAAS;IACrF;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,mCAAiC;MAC/B,OAAO,IAAI,CAACc,wBAAwB,CAClC,sDAAsD,EACtD,4BAA4B,CAC7B;IACH;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,uCAAqC;MACnC,OAAO,IAAI,CAACA,wBAAwB,CAClC,sDAAsD,EACtD,2BAA2B,CAC5B;IACH;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,uCAAqC;MACnC,IAAMC,8BAA8B,GAAG,IAAI,CAACvB,iBAAiB,CAACO,GAAG,CAC/D,sDAAsD,CACvD;;MAED;MACA,IAAMiB,yBAAyB,GAAGC,IAAI,CAACC,GAAG,CACxC,IAAI,CAAC1B,iBAAiB,CAACO,GAAG,CAAC,uBAAuB,CAAC,EACnD,IAAI,CAACP,iBAAiB,CAACO,GAAG,CAAC,uBAAuB,CAAC,CACpD;MAED,IAAMoB,SAAS,GAAG,IAAI,CAACC,gBAAgB,EAAE,IAAI,CAAC;MAE9C,IAAIL,8BAA8B,IAAIC,yBAAyB,EAAE;QAC/D,OAAOA,yBAAyB,GAAGD,8BAA8B,GAAGI,SAAS;MAC/E;MAEA,OAAOnB,SAAS;IAClB;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,uBAAqB;MACnB,IAAMqB,mBAAmB,GAAG,IAAI,CAACC,sBAAsB,EAAE;MACzD,IAAMC,oBAAoB,GAAG,IAAI,CAACC,uBAAuB,EAAE;MAE3D,IAAIH,mBAAmB,IAAIE,oBAAoB,EAAE;QAC/C,OAAOF,mBAAmB,GAAGE,oBAAoB;MACnD;MAEA,OAAOvB,SAAS;IAClB;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,0BAAwB;MACtB,IAAMyB,WAAW,GAAG,IAAI,CAACC,cAAc,EAAE;MACzC,IAAMC,YAAY,GAAG,IAAI,CAACC,eAAe,EAAE;MAE3C,IAAIH,WAAW,IAAIE,YAAY,EAAE;QAC/B,OAAOF,WAAW,GAAGE,YAAY;MACnC;MAEA,OAAO3B,SAAS;IAClB;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,4BAA0B;MACxB,IAAMqB,mBAAmB,GAAG,IAAI,CAACC,sBAAsB,EAAE;MACzD,IAAMC,oBAAoB,GAAG,IAAI,CAACC,uBAAuB,EAAE;MAC3D,IAAMK,WAAW,GAAG,IAAI,CAACC,cAAc,EAAE;MACzC,IAAMX,SAAS,GAAG,IAAI,CAACC,gBAAgB,EAAE;MAEzC,IAAIC,mBAAmB,IAAIE,oBAAoB,IAAIM,WAAW,EAAE;QAAA;QAC9D,IAAME,aAAa,GAAGV,mBAAmB,GAAGE,oBAAoB,GAAGM,WAAW;QAC9E,wBAAI,IAAI,CAACG,UAAU,EAAE,6CAAjB,iBAAmBC,iBAAiB,EAAE;UACxC,OAAOF,aAAa;QACtB;QAEA,OAAOA,aAAa,GAAGZ,SAAS;MAClC;MAEA,OAAOnB,SAAS;IAClB;;IAEA;AACF;AACA;AACA;EAHE;IAAA;IAAA,OAIA,wBAAsB;MACpB,IAAMuB,oBAAoB,GAAG,IAAI,CAACC,uBAAuB,EAAE;MAC3D,IAAMK,WAAW,GAAG,IAAI,CAACC,cAAc,EAAE;MAEzC,IAAIP,oBAAoB,IAAIM,WAAW,EAAE;QACvC,OAAON,oBAAoB,GAAGM,WAAW;MAC3C;MAEA,OAAO7B,SAAS;IAClB;;IAEA;AACF;AACA;EAFE;IAAA;IAAA,OAGA,mCAAiC;MAC/B,OAAO,IAAI,CAACc,wBAAwB,CAAC,4BAA4B,EAAE,uBAAuB,CAAC;IAC7F;;IAEA;AACF;AACA;EAFE;IAAA;IAAA,OAGA,mCAAiC;MAC/B,OAAO,IAAI,CAACA,wBAAwB,CAAC,4BAA4B,EAAE,uBAAuB,CAAC;IAC7F;;IAEA;AACF;AACA;EAFE;IAAA;IAAA,OAGA,mCAAiC;MAC/B,OAAO,IAAI,CAACA,wBAAwB,CAAC,4BAA4B,EAAE,uBAAuB,CAAC;IAC7F;;IAEA;AACF;AACA;EAFE;IAAA;IAAA,OAGA,mCAAiC;MAC/B,OAAO,IAAI,CAACA,wBAAwB,CAAC,4BAA4B,EAAE,uBAAuB,CAAC;IAC7F;EAAC;EAAA;AAAA,EA/YkDoB,sBAAW;AAAA"}
package/dist/metrics.js CHANGED
@@ -161,7 +161,7 @@ var Metrics = _webexCore.WebexPlugin.extend({
161
161
  });
162
162
  });
163
163
  },
164
- version: "3.0.0-beta.270"
164
+ version: "3.0.0-beta.271"
165
165
  });
166
166
  var _default = Metrics;
167
167
  exports.default = _default;
@@ -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} from '@webex/event-dictionary-ts';\n\nexport type Event = Omit<RawEvent, 'event'> & {event: RawClientEvent | RawMediaQualityEvent};\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 SubmitClientEventOptions = {\n meetingId?: string;\n mediaConnections?: any[];\n rawError?: any;\n correlationId?: string;\n preLoginId?: string;\n environment?: EnvironmentType;\n newEnvironmentType?: NewEnvironmentType;\n clientLaunchMethod?: ClientLaunchMethodType;\n};\n\nexport type SubmitMQEOptions = {\n meetingId: string;\n mediaConnections?: any[];\n networkType?: Event['origin']['networkType'];\n};\n\nexport type InternalEvent = {\n name:\n | 'internal.client.meetinginfo.request'\n | 'internal.client.meetinginfo.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 payload?: never;\n options?: never;\n};\n\nexport interface ClientEvent {\n name: RawClientEvent['name'];\n payload?: RawClientEvent;\n options?: SubmitClientEventOptions;\n}\n\nexport interface BehavioralEvent {\n // TODO: not implemented\n name: 'host.meeting.participant.admitted' | 'sdk.media-flow.started';\n payload?: never;\n options?: never;\n}\n\nexport interface OperationalEvent {\n // TODO: not implemented\n name: never;\n payload?: never;\n options?: never;\n}\n\nexport interface FeatureEvent {\n // TODO: not implemented\n name: never;\n payload?: never;\n options?: never;\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['name']\n | OperationalEvent['name']\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 ClientEventPayload = RecursivePartial<ClientEvent['payload']>;\nexport type ClientEventLeaveReason = ClientEvent['payload']['leaveReason'];\nexport type ClientEventPayloadError = ClientEvent['payload']['errors'];\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 name: BehavioralEvent['name'];\n payload?: RecursivePartial<BehavioralEvent['payload']>;\n options?: any;\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['name'];\n payload?: RecursivePartial<OperationalEvent['payload']>;\n options?: any;\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"],"mappings":""}
1
+ {"version":3,"names":[],"sources":["metrics.types.ts"],"sourcesContent":["import {\n ClientEvent as RawClientEvent,\n Event as RawEvent,\n MediaQualityEvent as RawMediaQualityEvent,\n} from '@webex/event-dictionary-ts';\n\nexport type Event = Omit<RawEvent, 'event'> & {event: RawClientEvent | RawMediaQualityEvent};\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 SubmitClientEventOptions = {\n meetingId?: string;\n mediaConnections?: any[];\n rawError?: any;\n correlationId?: string;\n preLoginId?: string;\n environment?: EnvironmentType;\n newEnvironmentType?: NewEnvironmentType;\n clientLaunchMethod?: ClientLaunchMethodType;\n};\n\nexport type SubmitMQEOptions = {\n meetingId: string;\n mediaConnections?: any[];\n networkType?: Event['origin']['networkType'];\n};\n\nexport type InternalEvent = {\n name:\n | 'internal.client.meetinginfo.request'\n | 'internal.client.meetinginfo.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 BehavioralEvent {\n // TODO: not implemented\n name: 'host.meeting.participant.admitted' | 'sdk.media-flow.started';\n payload?: never;\n options?: never;\n}\n\nexport interface OperationalEvent {\n // TODO: not implemented\n name: never;\n payload?: never;\n options?: never;\n}\n\nexport interface FeatureEvent {\n // TODO: not implemented\n name: never;\n payload?: never;\n options?: never;\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['name']\n | OperationalEvent['name']\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 ClientEventPayload = RecursivePartial<ClientEvent['payload']>;\nexport type ClientEventLeaveReason = ClientEvent['payload']['leaveReason'];\nexport type ClientEventPayloadError = ClientEvent['payload']['errors'];\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 name: BehavioralEvent['name'];\n payload?: RecursivePartial<BehavioralEvent['payload']>;\n options?: any;\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['name'];\n payload?: RecursivePartial<OperationalEvent['payload']>;\n options?: any;\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"],"mappings":""}
@@ -95,6 +95,11 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
95
95
  * @returns - latency
96
96
  */
97
97
  getJoinRespSentReceived(): any;
98
+ /**
99
+ * Time taken to do turn discovery
100
+ * @returns - latency
101
+ */
102
+ getTurnDiscoveryTime(): number;
98
103
  /**
99
104
  * Local SDP Generated Remote SDP REceived
100
105
  * @returns - latency
@@ -22,7 +22,7 @@ export type SubmitMQEOptions = {
22
22
  networkType?: Event['origin']['networkType'];
23
23
  };
24
24
  export type InternalEvent = {
25
- name: 'internal.client.meetinginfo.request' | 'internal.client.meetinginfo.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';
25
+ name: 'internal.client.meetinginfo.request' | 'internal.client.meetinginfo.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';
26
26
  payload?: never;
27
27
  options?: never;
28
28
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/internal-plugin-metrics",
3
- "version": "3.0.0-beta.270",
3
+ "version": "3.0.0-beta.271",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -28,13 +28,13 @@
28
28
  "build": "yarn run -T tsc --declaration true --declarationDir ./dist/types"
29
29
  },
30
30
  "dependencies": {
31
- "@webex/common": "3.0.0-beta.270",
32
- "@webex/common-timers": "3.0.0-beta.270",
31
+ "@webex/common": "3.0.0-beta.271",
32
+ "@webex/common-timers": "3.0.0-beta.271",
33
33
  "@webex/event-dictionary-ts": "^1.0.1290",
34
- "@webex/internal-plugin-device": "3.0.0-beta.270",
35
- "@webex/internal-plugin-metrics": "3.0.0-beta.270",
36
- "@webex/test-helper-chai": "3.0.0-beta.270",
37
- "@webex/test-helper-mock-webex": "3.0.0-beta.270",
38
- "@webex/webex-core": "3.0.0-beta.270"
34
+ "@webex/internal-plugin-device": "3.0.0-beta.271",
35
+ "@webex/internal-plugin-metrics": "3.0.0-beta.271",
36
+ "@webex/test-helper-chai": "3.0.0-beta.271",
37
+ "@webex/test-helper-mock-webex": "3.0.0-beta.271",
38
+ "@webex/webex-core": "3.0.0-beta.271"
39
39
  }
40
40
  }
@@ -181,6 +181,17 @@ export default class CallDiagnosticLatencies extends WebexPlugin {
181
181
  return undefined;
182
182
  }
183
183
 
184
+ /**
185
+ * Time taken to do turn discovery
186
+ * @returns - latency
187
+ */
188
+ public getTurnDiscoveryTime() {
189
+ return this.getDiffBetweenTimestamps(
190
+ 'internal.client.add-media.turn-discovery.start',
191
+ 'internal.client.add-media.turn-discovery.end'
192
+ );
193
+ }
194
+
184
195
  /**
185
196
  * Local SDP Generated Remote SDP REceived
186
197
  * @returns - latency
@@ -41,7 +41,10 @@ export type InternalEvent = {
41
41
  | 'internal.client.meeting.click.joinbutton'
42
42
  | 'internal.host.meeting.participant.admitted'
43
43
  | 'internal.client.meeting.interstitial-window.showed'
44
- | 'internal.client.interstitial-window.click.joinbutton';
44
+ | 'internal.client.interstitial-window.click.joinbutton'
45
+ | 'internal.client.add-media.turn-discovery.start'
46
+ | 'internal.client.add-media.turn-discovery.end';
47
+
45
48
  payload?: never;
46
49
  options?: never;
47
50
  };
@@ -127,6 +127,18 @@ describe('internal-plugin-metrics', () => {
127
127
  assert.deepEqual(cdl.getJoinReqResp(), 10);
128
128
  });
129
129
 
130
+ it('calculates getTurnDiscoveryTime correctly', () => {
131
+ cdl.saveTimestamp({
132
+ key: 'internal.client.add-media.turn-discovery.start',
133
+ value: 10,
134
+ });
135
+ cdl.saveTimestamp({
136
+ key: 'internal.client.add-media.turn-discovery.end',
137
+ value: 20,
138
+ });
139
+ assert.deepEqual(cdl.getTurnDiscoveryTime(), 10);
140
+ });
141
+
130
142
  it('calculates getLocalSDPGenRemoteSDPRecv correctly', () => {
131
143
  cdl.saveTimestamp({
132
144
  key: 'client.media-engine.local-sdp-generated',