Ver código fonte

feat(JSPC): ICE checks and gathering analytics

Will emit analytics events for ICE gathering and ICE checks duration,
separately for initiator/responder and p2p/jvb connections. Initiator
and responder have to be separated, because the flow and the values have
significant differences.

XMPPEvents.CONNECTION_ESTABLISHED is emitted outside of 'is stable'
condition, because for the JVB connection the signalling state is often
not in 'stable' ('have-remote-offer') state when ICE goes to
'connected'.
master
paweldomas 8 anos atrás
pai
commit
9ab05f801d
1 arquivos alterados com 51 adições e 3 exclusões
  1. 51
    3
      modules/xmpp/JingleSessionPC.js

+ 51
- 3
modules/xmpp/JingleSessionPC.js Ver arquivo

@@ -69,6 +69,26 @@ export default class JingleSessionPC extends JingleSession {
69 69
             options) {
70 70
         super(sid, me, peerjid, connection, mediaConstraints, iceConfig);
71 71
 
72
+        /**
73
+         * Stores result of {@link window.performance.now()} at the time when
74
+         * ICE enters 'checking' state.
75
+         * @type {number|null} null if no value has been stored yet
76
+         * @private
77
+         */
78
+        this._iceCheckingStartedTimestamp = null;
79
+
80
+        /**
81
+         * Stores result of {@link window.performance.now()} at the time when
82
+         * first ICE candidate is spawned by the peerconnection to mark when
83
+         * ICE gathering started. That's, because ICE gathering state changed
84
+         * events are not supported by most of the browsers, so we try something
85
+         * that will work everywhere. It may not be as accurate, but given that
86
+         * 'host' candidate usually comes first, the delay should be minimal.
87
+         * @type {number|null} null if no value has been stored yet
88
+         * @private
89
+         */
90
+        this._gatheringStartedTimestamp = null;
91
+
72 92
         this.lasticecandidate = false;
73 93
         this.closed = false;
74 94
 
@@ -217,8 +237,13 @@ export default class JingleSessionPC extends JingleSession {
217 237
 
218 238
             // XXX this is broken, candidate is not parsed.
219 239
             const candidate = ev.candidate;
240
+            const now = window.performance.now();
220 241
 
221 242
             if (candidate) {
243
+                if (this._gatheringStartedTimestamp === null) {
244
+                    this._gatheringStartedTimestamp = now;
245
+                }
246
+
222 247
                 // Discard candidates of disabled protocols.
223 248
                 let protocol = candidate.protocol;
224 249
 
@@ -234,6 +259,15 @@ export default class JingleSessionPC extends JingleSession {
234 259
                         }
235 260
                     }
236 261
                 }
262
+            } else {
263
+                // End of gathering
264
+                let eventName = this.isP2P ? 'p2p.ice.' : 'ice.';
265
+
266
+                eventName += this.isInitiator ? 'initiator' : 'responder';
267
+                eventName += '.gatheringDuration';
268
+                Statistics.analytics.sendEvent(
269
+                    eventName,
270
+                    { value: now - this._gatheringStartedTimestamp });
237 271
             }
238 272
             this.sendIceCandidate(candidate);
239 273
         };
@@ -290,6 +324,9 @@ export default class JingleSessionPC extends JingleSession {
290 324
                 this,
291 325
                 this.peerconnection.iceConnectionState);
292 326
             switch (this.peerconnection.iceConnectionState) {
327
+            case 'checking':
328
+                this._iceCheckingStartedTimestamp = now;
329
+                break;
293 330
             case 'connected':
294 331
                 // Informs interested parties that the connection has been
295 332
                 // restored.
@@ -297,11 +334,22 @@ export default class JingleSessionPC extends JingleSession {
297 334
                     if (this.isreconnect) {
298 335
                         this.room.eventEmitter.emit(
299 336
                             XMPPEvents.CONNECTION_RESTORED, this);
300
-                    } else if (!this.wasConnected) {
301
-                        this.room.eventEmitter.emit(
302
-                            XMPPEvents.CONNECTION_ESTABLISHED, this);
303 337
                     }
338
+                }
339
+
340
+                if (!this.wasConnected && this.wasstable) {
341
+                    let eventName = this.isP2P ? 'p2p.ice.' : 'ice.';
342
+
343
+                    eventName += this.isInitiator ? 'initiator.' : 'responder.';
344
+                    eventName += 'checksDuration';
345
+                    Statistics.analytics.sendEvent(
346
+                        eventName,
347
+                        {
348
+                            value: now - this._iceCheckingStartedTimestamp
349
+                        });
304 350
                     this.wasConnected = true;
351
+                    this.room.eventEmitter.emit(
352
+                            XMPPEvents.CONNECTION_ESTABLISHED, this);
305 353
                 }
306 354
                 this.isreconnect = false;
307 355
                 break;

Carregando…
Cancelar
Salvar