From 7072237e534cef6c19dd8a2a3c492136a92b037c Mon Sep 17 00:00:00 2001 From: Jeremy Gunawan Date: Tue, 2 Apr 2024 13:26:58 -0700 Subject: [PATCH] Separate connecting to signaling vs signing the request metric and print the values out --- README.md | 63 ++++++++++++------------ examples/master.js | 24 ++++++++++ examples/viewer.js | 116 +++++++++++++++++++++++++++------------------ 3 files changed, 127 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 9514662..6f470bf 100644 --- a/README.md +++ b/README.md @@ -371,37 +371,38 @@ An enum with the following values: ## Metrics -The DQP metrics can be enabled in the sample application by checking a box before starting the viewer on the JS side. On the master, there is a flag in the sample application which `(pSampleConfiguration->enableSendingMetricsToViewerViaDc)` can be set to TRUE to send metrics from the master to the [JS](https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/index.html) viewer. This helps get a detailed breakdown of time-to-first-frame and all the processes and API calls on master and the viewer both. This is intended to be used with the KVS WebRTC C SDK running as the master and the JS SDK as the viewer. The master sends peer, ice-agent, signaling and data-channel metrics to the viewer which are plotted ~ 20 seconds after the viewer is started. Since the timeline plot is intended to understand the time-to-first-frame, the sample web page needs to be refreshed and the master needs to be restarted if a new / updated plot is needed. While using the SDK in this mode, it is expected that all datachannel messages are JSON messages. This feature is only meant to be used for a single viewer at a time. - -| Category | Metric | Calculation | Description | -|--------------------|--------------------------------|-------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| viewer-wait | viewer-waiting-for-master | Calculated as the time between the signaling client going to `open` state and the time to start the master | Time duration the viewer was waiting for the master to start (time to start the SDK after the viewer signaling channel was connected) | -| viewer-signaling | signaling-viewer | Calculated as the time between creation of the `KinesisVideoClient` and the signaling client going to `open` state | Time taken to establish a signaling connection on the viewer-side | -| viewer-signaling | setup-media-player-viewer | Calculated as the time taken for `getUserMedia` call | Time taken to setup a media player on the viewer-side by seeking permissions for mic / camera (if needed), fetch tracks from the same and add them to the peer connection peer. | -| viewer-signaling | signaling-viewer-describe-channel | Calculated as the time taken for the `describeSignalingChannel` call | Time taken for the API call to describeSignalingChannel on the viewer | -| viewer-signaling | signaling-viewer-describe-media-storage-config | Calculated as the time taken for the `describeMediaStorageConfiguration` call | Time taken for the API call to describeSignalingChannel on the viewer | -| viewer-signaling | signaling-viewer-get-signaling-channel-endpoint | Calculated as the time taken for the `getSignalingChannelEndpoint` | Time taken for the API call to getSignalingChannelEndpoint on the viewer | -| viewer-signaling | signaling-viewer-get-ice-server-config | Calculated as the time taken for the `getIceServerConfig` | Time taken for the API call to getIceServerConfig on the viewer | -| viewer-signaling | signaling-connect-as-viewer | Calculated as the time taken between the signalingClient creation with all the information from the previous steps and it reaching the `open` state | Time taken to open the websocket via connectAsViewer | -| viewer-sdp-exchange | sdp-exchange-viewer | Calculated as the time between setting the local description and the reception of an answer from the master | Time taken to send an offer and receive a response | -| viewer-ice | ice-gathering-viewer | Calculated as the time between `viewer.peerConnection.iceGatheringState` going from `gathering` to `complete` | Time taken to gather all ice candidates on the viewer | -| viewer-peer-connection | pc-establishment-viewer | Calculated as the time between `viewer.peerConnection.connectionState` going from `new` to `connected` | Time taken to establish the peer connection on the viewer | -| viewer-datachannel | datachannel-viewer | Calculated as the time between `timestamp1` (time at which the viewer sends a message) and `timestamp3` (time at which the viewer receives a response from the master) | Time taken to send a message to the master and receive a response back -| viewer-ttff | ttff-after-pc-viewer | Calculated as time between `viewer.peerConnection.connectionState` in `connected` state and `viewer.remoteView.addEventListener` goes to `loadeddata` | Time to first frame after the viewer\'s peer connection has been established | -| master-wait | master-waiting-for-viewer | Calculated as the time between signaling state going to connected and the button to start the viewer | Time duration the master was waiting for the viewer to start (time to click the button after the master signaling channel was connected) | -| master-signaling | signaling-master | Calculated as the time for the entire signaling process on the master | Time taken to establish a signaling connection on the master-side | -| master-signaling | signaling-master-describe-channel | Calculated as the time taken for the `describeSignalingChannel` call | Time taken for the API call to desribeSignalingChannel on the master | -| master-signaling | signaling-master-get-signaling-channel-endpoint | Calculated as the time taken for the `getSignalingChannelEndpoint` | Time taken for the API call to getSignalingChannelEndpoint on the master | -| master-signaling | signaling-master-get-ice-server-config | Calculated as the time taken for the `getIceServerConfig` | Time taken for the API call to getIceServerConfig on the master | -| master-signaling | signaling-master-get-token | Calculated as the time taken for `getCredentialsFn` for authentication | Time taken for the getToken call on the master | -| master-signaling | signaling-master-create-channel | Calculated as the time taken for the `createSignalingChannel` | Time taken createChannel API call on the master | -| master-signaling | signaling-master-connect | Calculated as the time taken for the `connectAsMaster` | Time taken for the signaling connect on the master | -| master-sdp-exchange | sdp-exchange-master | Calculated as the time between the master receiving an offer, processing it and sending an answer to the viewer | Time taken to respond to an offer from the viewer with an answer | -| master-ice | ice-gathering-master | Calculated as the time from starting the gathering to the time its scheduling was stopped | Time taken to gather all ice candidates on the master | -| master-peer-connection | pc-establishment-master | Calculated as the time taken to go to `RTC_PEER_CONNECTION_STATE_CONNECTED` | Time taken to establish the peer connection on the master | -| master-datachannel | datachannel-master | Calculated as the time between `timestamp2` (time at which the master sends a message) and `timestamp4` (time at which the master receives a response from the master) | Time taken to send a message to the viewer and receive a response back | -| master-ttff | ttff-after-pc-master | Calculated as the time between `metrics.master.peerConnection.endTime` and `viewer.remoteView.addEventListener` reaches `loadeddata` | Time to first frame after the master's peer connection has been established | -| ttff | ttff | Calculated as the time taken between the viewer button is clicked and `viewer.remoteView.addEventListener` reaches `loadeddata` | Time to first frame since the viewer button was clicked | +The DQP metrics can be enabled in the sample application by checking a box before starting the viewer on the JS side. On the master, there is a flag in the sample application which `(pSampleConfiguration->enableSendingMetricsToViewerViaDc)` can be set to TRUE to send metrics from the master to the [JS](https://awslabs.github.io/amazon-kinesis-video-streams-webrtc-sdk-js/examples/index.html) viewer. This helps get a detailed breakdown of time-to-first-frame and all the processes and API calls on master and the viewer both. This is intended to be used with the KVS WebRTC C SDK running as the master and the JS SDK as the viewer. The master sends peer, ice-agent, signaling and data-channel metrics to the viewer which are plotted ~ 20 seconds after the viewer is started. Since the timeline plot is intended to understand the time-to-first-frame, the sample web page needs to be refreshed and the master needs to be restarted if a new / updated plot is needed. While using the SDK in this mode, it is expected that all datachannel messages are JSON messages. This feature is only meant to be used for a single viewer at a time. + +| Category | Metric | Calculation | Description | +|--------------------|--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| viewer-wait | viewer-waiting-for-master | Calculated as the time between the signaling client going to `open` state and the time to start the master | Time duration the viewer was waiting for the master to start (time to start the SDK after the viewer signaling channel was connected) | +| viewer-signaling | signaling-viewer | Calculated as the time between creation of the `KinesisVideoClient` and the signaling client going to `open` state | Time taken to establish a signaling connection on the viewer-side | +| viewer-signaling | setup-media-player-viewer | Calculated as the time taken for `getUserMedia` call | Time taken to setup a media player on the viewer-side by seeking permissions for mic / camera (if needed), fetch tracks from the same and add them to the peer connection peer. | +| viewer-signaling | signaling-viewer-describe-channel | Calculated as the time taken for the `describeSignalingChannel` call | Time taken for the API call to describeSignalingChannel on the viewer | +| viewer-signaling | signaling-viewer-describe-media-storage-config | Calculated as the time taken for the `describeMediaStorageConfiguration` call | Time taken for the API call to describeSignalingChannel on the viewer | +| viewer-signaling | signaling-viewer-get-signaling-channel-endpoint | Calculated as the time taken for the `getSignalingChannelEndpoint` | Time taken for the API call to getSignalingChannelEndpoint on the viewer | +| viewer-signaling | signaling-viewer-get-ice-server-config | Calculated as the time taken for the `getIceServerConfig` | Time taken for the API call to getIceServerConfig on the viewer | +| viewer-signaling | sign-connect-as-viewer | Calculated as the time to sign the websocket url to connect to Signaling via connectAsViewer | Time taken to sign the websocket url | +| viewer-signaling | signaling-connect-as-viewer | Calculated as the time the Websocket object is created with the signed url, to it reaching the `open` state | Time taken to establish a connection to Signaling via connectAsViewer | +| viewer-sdp-exchange | sdp-exchange-viewer | Calculated as the time between setting the local description and the reception of an answer from the master | Time taken to send an offer and receive a response | +| viewer-ice | ice-gathering-viewer | Calculated as the time between `viewer.peerConnection.iceGatheringState` going from `gathering` to `complete` | Time taken to gather all ice candidates on the viewer | +| viewer-peer-connection | pc-establishment-viewer | Calculated as the time between `viewer.peerConnection.connectionState` going from `new` to `connected` | Time taken to establish the peer connection on the viewer | +| viewer-datachannel | datachannel-viewer | Calculated as the time between `timestamp1` (time at which the viewer sends a message) and `timestamp3` (time at which the viewer receives a response from the master) | Time taken to send a message to the master and receive a response back +| viewer-ttff | ttff-after-pc-viewer | Calculated as time between `viewer.peerConnection.connectionState` in `connected` state and `viewer.remoteView.addEventListener` goes to `loadeddata` | Time to first frame after the viewer\'s peer connection has been established | +| master-wait | master-waiting-for-viewer | Calculated as the time between signaling state going to connected and the button to start the viewer | Time duration the master was waiting for the viewer to start (time to click the button after the master signaling channel was connected) | +| master-signaling | signaling-master | Calculated as the time for the entire signaling process on the master | Time taken to establish a signaling connection on the master-side | +| master-signaling | signaling-master-describe-channel | Calculated as the time taken for the `describeSignalingChannel` call | Time taken for the API call to desribeSignalingChannel on the master | +| master-signaling | signaling-master-get-signaling-channel-endpoint | Calculated as the time taken for the `getSignalingChannelEndpoint` | Time taken for the API call to getSignalingChannelEndpoint on the master | +| master-signaling | signaling-master-get-ice-server-config | Calculated as the time taken for the `getIceServerConfig` | Time taken for the API call to getIceServerConfig on the master | +| master-signaling | signaling-master-get-token | Calculated as the time taken for `getCredentialsFn` for authentication | Time taken for the getToken call on the master | +| master-signaling | signaling-master-create-channel | Calculated as the time taken for the `createSignalingChannel` | Time taken createChannel API call on the master | +| master-signaling | signaling-master-connect | Calculated as the time taken for the `connectAsMaster` | Time taken for the signaling connect on the master | +| master-sdp-exchange | sdp-exchange-master | Calculated as the time between the master receiving an offer, processing it and sending an answer to the viewer | Time taken to respond to an offer from the viewer with an answer | +| master-ice | ice-gathering-master | Calculated as the time from starting the gathering to the time its scheduling was stopped | Time taken to gather all ice candidates on the master | +| master-peer-connection | pc-establishment-master | Calculated as the time taken to go to `RTC_PEER_CONNECTION_STATE_CONNECTED` | Time taken to establish the peer connection on the master | +| master-datachannel | datachannel-master | Calculated as the time between `timestamp2` (time at which the master sends a message) and `timestamp4` (time at which the master receives a response from the master) | Time taken to send a message to the viewer and receive a response back | +| master-ttff | ttff-after-pc-master | Calculated as the time between `metrics.master.peerConnection.endTime` and `viewer.remoteView.addEventListener` reaches `loadeddata` | Time to first frame after the master's peer connection has been established | +| ttff | ttff | Calculated as the time taken between the viewer button is clicked and `viewer.remoteView.addEventListener` reaches `loadeddata` | Time to first frame since the viewer button was clicked | ## Compatibility diff --git a/examples/master.js b/examples/master.js index 3309db6..ce5a4bc 100644 --- a/examples/master.js +++ b/examples/master.js @@ -45,6 +45,7 @@ async function startMaster(localView, remoteView, formValues, onStatsReport, onR master.sdpOfferReceived = false; master.connectionFailures = []; master.currentJoinStorageSessionRetries = 0; + let signalingConnectionStarted; try { master.localView = localView; @@ -135,6 +136,26 @@ async function startMaster(localView, remoteView, formValues, onStatsReport, onR secretAccessKey: formValues.secretAccessKey, sessionToken: formValues.sessionToken, }, + requestSigner: { + getSignedURL: async function(signalingEndpoint, queryParams, date) { + const signer = new KVSWebRTC.SigV4RequestSigner(formValues.region, { + accessKeyId: formValues.accessKeyId, + secretAccessKey: formValues.secretAccessKey, + sessionToken: formValues.sessionToken, + }); + + const signingStart = new Date(); + console.debug('[MASTER] Signing the url started at', signingStart); + const retVal = await signer.getSignedURL(signalingEndpoint, queryParams, date); + const signingEnd = new Date(); + console.debug('[MASTER] Signing the url ended at', signingEnd); + console.log('[MASTER] Time to sign the request:', signingEnd.getTime() - signingStart.getTime(), 'ms'); + signalingConnectionStarted = new Date(); + console.log('[MASTER] Connecting to KVS Signaling...'); + console.debug('[MASTER] ConnectAsMaster started at', signalingConnectionStarted); + return retVal; + }, + }, systemClockOffset: kinesisVideoClient.config.systemClockOffset, }); @@ -218,7 +239,10 @@ async function startMaster(localView, remoteView, formValues, onStatsReport, onR master.signalingClient.on('open', async () => { const masterRunId = ++master.runId; master.websocketOpened = true; + const signalingConnected = new Date(); + console.debug('[MASTER] ConnectAsMaster completed at', signalingConnected); console.log('[MASTER] Connected to signaling service'); + console.log('[MASTER] Time to connect to signaling:', signalingConnected.getTime() - signalingConnectionStarted.getTime(), 'ms'); if (formValues.showJSSButton) { $('#join-storage-session-button').removeClass('d-none'); } diff --git a/examples/viewer.js b/examples/viewer.js index c67883b..ec22c64 100644 --- a/examples/viewer.js +++ b/examples/viewer.js @@ -52,7 +52,7 @@ let metrics = { endTime: '', tooltip: 'Time duration the viewer was waiting for the master to start (time to start the SDK after the viewer signaling channel was connected)', color: 'yellow', - }, + }, signaling: { name: 'signaling-viewer', startTime: '', @@ -66,7 +66,7 @@ let metrics = { endTime: '', tooltip: 'Time taken to setup a media player on the viewer-side by seeking permissions for mic / camera (if needed), fetch tracks from the same and add them to the peer connection', color: '#9575CD', - }, + }, offAnswerTime: { name: 'sdp-exchange-viewer', startTime: '', @@ -87,7 +87,7 @@ let metrics = { endTime: '', tooltip: 'Time taken for the API call to describeSignalingChannel on the viewer', color: '#EF9A9A', - }, + }, channelEndpoint: { name: 'signaling-viewer-get-signaling-channel-endpoint', startTime: '', @@ -102,6 +102,13 @@ let metrics = { tooltip: 'Time taken for the API call to getIceServerConfig on the viewer', color: '#EF9A9A', }, + signConnectAsViewer: { + name: 'sign-connect-as-viewer', + startTime: '', + endTime: '', + tooltip: 'Time taken to sign the websocket request via connectAsViewer', + color: '#EF9A9A', + }, connectAsViewer: { name: 'signaling-connect-as-viewer', startTime: '', @@ -115,7 +122,7 @@ let metrics = { endTime: '', tooltip: 'Time taken to gather all ice candidates on the viewer', color: '#90CAF9', - }, + }, peerConnection: { name: 'pc-establishment-viewer', startTime: '', @@ -128,8 +135,8 @@ let metrics = { startTime: '', endTime: '', tooltip: 'Time to first frame after the viewer\'s peer connection has been established', - color: '#2196F3', - }, + color: '#2196F3', + }, ttff: { name: 'ttff', startTime: '', @@ -152,7 +159,7 @@ let metrics = { endTime: '', tooltip: 'Time duration the master was waiting for the viewer to start (time to click the button after the master signaling channel was connected)', color: 'yellow', - }, + }, signaling: { name: 'signaling-master', startTime: '', @@ -215,7 +222,7 @@ let metrics = { endTime: '', tooltip: 'Time taken to gather all ice candidates on the master', color: '#90CAF9', - }, + }, peerConnection: { name: 'pc-establishment-master', startTime: '', @@ -348,7 +355,7 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem } metrics.viewer.signaling.startTime = Date.now(); - + // Create KVS client const kinesisVideoClient = new AWS.KinesisVideo({ region: formValues.region, @@ -375,7 +382,7 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem if (formValues.ingestMedia) { console.log('[VIEWER] Determining whether this signaling channel is in media ingestion mode.'); - + metrics.viewer.describeMediaStorageConfiguration.startTime = Date.now(); const mediaStorageConfiguration = await kinesisVideoClient @@ -409,7 +416,7 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem }, }) .promise(); - + metrics.viewer.channelEndpoint.endTime = Date.now(); const endpointsByProtocol = getSignalingChannelEndpointResponse.ResourceEndpointList.reduce((endpoints, endpoint) => { @@ -436,9 +443,9 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem ChannelARN: channelARN, }) .promise(); - + metrics.viewer.iceServerConfig.endTime = Date.now(); - + const iceServers = []; // Don't add stun if user selects TURN only or NAT traversal disabled if (!formValues.natTraversalDisabled && !formValues.forceTURN) { @@ -457,7 +464,6 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem } console.log('[VIEWER] ICE servers:', iceServers); - metrics.viewer.connectAsViewer.startTime = Date.now(); // Create Signaling Client viewer.signalingClient = new KVSWebRTC.SignalingClient({ channelARN, @@ -470,6 +476,26 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem secretAccessKey: formValues.secretAccessKey, sessionToken: formValues.sessionToken, }, + requestSigner: { + getSignedURL: async function(signalingEndpoint, queryParams, date) { + const signer = new KVSWebRTC.SigV4RequestSigner(formValues.region, { + accessKeyId: formValues.accessKeyId, + secretAccessKey: formValues.secretAccessKey, + sessionToken: formValues.sessionToken, + }); + + metrics.viewer.signConnectAsViewer.startTime = Date.now(); + console.debug('[VIEWER] Signing the url started at', new Date(metrics.viewer.signConnectAsViewer.startTime)); + const retVal = await signer.getSignedURL(signalingEndpoint, queryParams, date); + metrics.viewer.signConnectAsViewer.endTime = Date.now(); + console.debug('[VIEWER] Signing the url ended at', new Date(metrics.viewer.signConnectAsViewer.endTime)); + console.log('[VIEWER] Time to sign the request:', metrics.viewer.signConnectAsViewer.endTime - metrics.viewer.signConnectAsViewer.startTime, 'ms'); + metrics.viewer.connectAsViewer.startTime = Date.now(); + console.log('[VIEWER] Connecting to KVS Signaling...'); + console.debug('[VIEWER] ConnectAsViewer started at', new Date(metrics.viewer.connectAsViewer.startTime)); + return retVal; + }, + }, systemClockOffset: kinesisVideoClient.config.systemClockOffset, }); @@ -497,7 +523,7 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem metrics.viewer.iceGathering.endTime = Date.now(); } }; - + viewer.peerConnection.onconnectionstatechange = (event) => { if (viewer.peerConnection.connectionState === 'new' || viewer.peerConnection.connectionState === 'connecting') { metrics.viewer.peerConnection.startTime = Date.now(); @@ -507,7 +533,7 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem metrics.viewer.ttffAfterPc.startTime = metrics.viewer.peerConnection.endTime; } }; - + viewer.peerConnection.oniceconnectionstatechange = (event) => { if (viewer.peerConnection.iceConnectionState === 'connected') { viewer.peerConnection.getStats().then(stats => { @@ -518,9 +544,9 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem }); }); } - }; + }; } - + if (formValues.openDataChannel) { const dataChannelObj = viewer.peerConnection.createDataChannel('kvsDataChannel'); viewer.dataChannel = dataChannelObj; @@ -534,14 +560,14 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem }; // Callback for the data channel created by viewer let onRemoteDataMessageViewer = (message) => { - + remoteMessage.append(`${message.data}\n\n`); if (formValues.enableProfileTimeline) { - // The datachannel first sends a message of the following format with firstMessageFromViewerTs attached, - // to which the master responds back with the same message attaching firstMessageFromMasterTs. - // In response to this, the viewer sends the same message back with secondMessageFromViewerTs and so on until lastMessageFromViewerTs. - // The viewer is responsible for attaching firstMessageFromViewerTs, secondMessageFromViewerTs, lastMessageFromViewerTs. The master is responsible for firstMessageFromMasterTs and secondMessageFromMasterTs. + // The datachannel first sends a message of the following format with firstMessageFromViewerTs attached, + // to which the master responds back with the same message attaching firstMessageFromMasterTs. + // In response to this, the viewer sends the same message back with secondMessageFromViewerTs and so on until lastMessageFromViewerTs. + // The viewer is responsible for attaching firstMessageFromViewerTs, secondMessageFromViewerTs, lastMessageFromViewerTs. The master is responsible for firstMessageFromMasterTs and secondMessageFromMasterTs. // (Master e2e time: secondMessageFromMasterTs - firstMessageFromMasterTs, Viewer e2e time: secondMessageFromViewerTs - firstMessageFromViewerTs) try { let dataChannelMessage = JSON.parse(message.data); @@ -552,55 +578,55 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem dataChannelMessage.lastMessageFromViewerTs = Date.now().toString(); metrics.master.dataChannel.startTime = Number(dataChannelMessage.firstMessageFromMasterTs); metrics.master.dataChannel.endTime = Number(dataChannelMessage.secondMessageFromMasterTs); - + metrics.viewer.dataChannel.startTime = Number(dataChannelMessage.firstMessageFromViewerTs); metrics.viewer.dataChannel.endTime = Number(dataChannelMessage.secondMessageFromViewerTs); } dataChannelMessage.content = 'Message from JS viewer'; dataChannelObj.send(JSON.stringify(dataChannelMessage)); - + } else if (dataChannelMessage.hasOwnProperty('peerConnectionStartTime')) { metrics.master.peerConnection.startTime = dataChannelMessage.peerConnectionStartTime; metrics.master.peerConnection.endTime = dataChannelMessage.peerConnectionEndTime; - + metrics.master.ttffAfterPc.startTime = metrics.master.peerConnection.endTime; - + } else if (dataChannelMessage.hasOwnProperty('signalingStartTime')) { metrics.master.signaling.startTime = dataChannelMessage.signalingStartTime; metrics.master.signaling.endTime = dataChannelMessage.signalingEndTime; - + if (metrics.viewer.ttff.startTime < metrics.master.signaling.startTime) { metrics.viewer.ttff.startTime = metrics.master.signaling.startTime; } - + metrics.master.waitTime.startTime = metrics.master.signaling.endTime; metrics.viewer.waitTime.endTime = metrics.master.signaling.startTime; - + metrics.master.offAnswerTime.startTime = dataChannelMessage.offerReceiptTime; metrics.master.offAnswerTime.endTime = dataChannelMessage.sendAnswerTime; - + metrics.master.describeChannel.startTime = dataChannelMessage.describeChannelStartTime; metrics.master.describeChannel.endTime = dataChannelMessage.describeChannelEndTime; - + metrics.master.channelEndpoint.startTime = dataChannelMessage.getSignalingChannelEndpointStartTime; metrics.master.channelEndpoint.endTime = dataChannelMessage.getSignalingChannelEndpointEndTime; - + metrics.master.iceServerConfig.startTime = dataChannelMessage.getIceServerConfigStartTime; metrics.master.iceServerConfig.endTime = dataChannelMessage.getIceServerConfigEndTime; - + metrics.master.getToken.startTime = dataChannelMessage.getTokenStartTime; metrics.master.getToken.endTime = dataChannelMessage.getTokenEndTime; - + metrics.master.createChannel.startTime = dataChannelMessage.createChannelStartTime; metrics.master.createChannel.endTime = dataChannelMessage.createChannelEndTime; - + metrics.master.connectAsMaster.startTime = dataChannelMessage.connectStartTime; metrics.master.connectAsMaster.endTime = dataChannelMessage.connectEndTime; - + } else if (dataChannelMessage.hasOwnProperty('candidateGatheringStartTime')) { metrics.master.iceGathering.startTime = dataChannelMessage.candidateGatheringStartTime; metrics.master.iceGathering.endTime = dataChannelMessage.candidateGatheringEndTime; - } + } } catch (e) { console.log("Receiving a non-json message"); } @@ -633,12 +659,12 @@ async function startViewer(localView, remoteView, formValues, onStatsReport, rem } viewer.signalingClient.on('open', async () => { - metrics.viewer.connectAsViewer.endTime = Date.now(); metrics.viewer.signaling.endTime = metrics.viewer.connectAsViewer.endTime; metrics.viewer.waitTime.startTime = metrics.viewer.signaling.endTime; - + console.debug('[VIEWER] ConnectAsViewer ended at', new Date(metrics.viewer.connectAsViewer.endTime)); console.log('[VIEWER] Connected to signaling service'); + console.log('[VIEWER] Time to connect to signaling:', metrics.viewer.connectAsViewer.endTime - metrics.viewer.connectAsViewer.startTime, 'ms'); metrics.viewer.setupMediaPlayer.startTime = Date.now(); signalingSetUpTime = metrics.viewer.setupMediaPlayer.startTime - viewerButtonPressed.getTime(); @@ -1100,9 +1126,9 @@ function getCalculatedEpoch(time, diffInMillis, minTime) { } function drawChart() { - const viewerOrder = ['signaling', 'describeChannel', 'describeMediaStorageConfiguration', 'channelEndpoint', 'iceServerConfig', 'connectAsViewer', 'setupMediaPlayer', 'waitTime', + const viewerOrder = ['signaling', 'describeChannel', 'describeMediaStorageConfiguration', 'channelEndpoint', 'iceServerConfig', 'signConnectAsViewer', 'connectAsViewer', 'setupMediaPlayer', 'waitTime', 'offAnswerTime', 'iceGathering', 'peerConnection', 'dataChannel', 'ttffAfterPc', 'ttff']; - const masterOrder = ['signaling', 'describeChannel', 'channelEndpoint', 'iceServerConfig', 'getToken', 'createChannel', 'connectAsMaster', 'waitTime', + const masterOrder = ['signaling', 'describeChannel', 'channelEndpoint', 'iceServerConfig', 'getToken', 'createChannel', 'connectAsMaster', 'waitTime', 'offAnswerTime', 'iceGathering', 'peerConnection', 'dataChannel', 'ttffAfterPc']; const container = document.getElementById('timeline-chart'); const rowHeight = 45; @@ -1129,7 +1155,7 @@ function drawChart() { dataTable.addRow([ metrics.master[key].name, null, getTooltipContent(metrics.master[key].tooltip, duration), startTime, endTime ]); colors.push(metrics.master[key].color); containerHeight += rowHeight; - } + } } }); @@ -1143,7 +1169,7 @@ function drawChart() { dataTable.addRow([ metrics.viewer[key].name, null, getTooltipContent(metrics.viewer[key].tooltip, duration), startTime, endTime ]); colors.push(metrics.viewer[key].color); containerHeight += rowHeight; - } + } } }); @@ -1159,4 +1185,4 @@ function drawChart() { } container.style.height = containerHeight.toString() + 'px'; chart.draw(dataTable, options); -} \ No newline at end of file +}