Переглянути джерело

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 роки тому
джерело
коміт
9ab05f801d
1 змінених файлів з 51 додано та 3 видалено
  1. 51
    3
      modules/xmpp/JingleSessionPC.js

+ 51
- 3
modules/xmpp/JingleSessionPC.js Переглянути файл

69
             options) {
69
             options) {
70
         super(sid, me, peerjid, connection, mediaConstraints, iceConfig);
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
         this.lasticecandidate = false;
92
         this.lasticecandidate = false;
73
         this.closed = false;
93
         this.closed = false;
74
 
94
 
217
 
237
 
218
             // XXX this is broken, candidate is not parsed.
238
             // XXX this is broken, candidate is not parsed.
219
             const candidate = ev.candidate;
239
             const candidate = ev.candidate;
240
+            const now = window.performance.now();
220
 
241
 
221
             if (candidate) {
242
             if (candidate) {
243
+                if (this._gatheringStartedTimestamp === null) {
244
+                    this._gatheringStartedTimestamp = now;
245
+                }
246
+
222
                 // Discard candidates of disabled protocols.
247
                 // Discard candidates of disabled protocols.
223
                 let protocol = candidate.protocol;
248
                 let protocol = candidate.protocol;
224
 
249
 
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
             this.sendIceCandidate(candidate);
272
             this.sendIceCandidate(candidate);
239
         };
273
         };
290
                 this,
324
                 this,
291
                 this.peerconnection.iceConnectionState);
325
                 this.peerconnection.iceConnectionState);
292
             switch (this.peerconnection.iceConnectionState) {
326
             switch (this.peerconnection.iceConnectionState) {
327
+            case 'checking':
328
+                this._iceCheckingStartedTimestamp = now;
329
+                break;
293
             case 'connected':
330
             case 'connected':
294
                 // Informs interested parties that the connection has been
331
                 // Informs interested parties that the connection has been
295
                 // restored.
332
                 // restored.
297
                     if (this.isreconnect) {
334
                     if (this.isreconnect) {
298
                         this.room.eventEmitter.emit(
335
                         this.room.eventEmitter.emit(
299
                             XMPPEvents.CONNECTION_RESTORED, this);
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
                     this.wasConnected = true;
350
                     this.wasConnected = true;
351
+                    this.room.eventEmitter.emit(
352
+                            XMPPEvents.CONNECTION_ESTABLISHED, this);
305
                 }
353
                 }
306
                 this.isreconnect = false;
354
                 this.isreconnect = false;
307
                 break;
355
                 break;

Завантаження…
Відмінити
Зберегти