Kaynağa Gözat

Merge pull request #510 from jitsi/p2p_analytics2

P2P analytics round 2
master
George Politis 8 yıl önce
ebeveyn
işleme
76f7377f06

+ 49
- 0
JitsiConference.js Dosyayı Görüntüle

@@ -14,6 +14,7 @@ import JitsiParticipant from './JitsiParticipant';
14 14
 import JitsiTrackError from './JitsiTrackError';
15 15
 import * as JitsiTrackErrors from './JitsiTrackErrors';
16 16
 import * as JitsiTrackEvents from './JitsiTrackEvents';
17
+import Jvb121EventGenerator from './modules/event/Jvb121EventGenerator';
17 18
 import * as MediaType from './service/RTC/MediaType';
18 19
 import ParticipantConnectionStatusHandler
19 20
     from './modules/connectivity/ParticipantConnectionStatus';
@@ -55,6 +56,10 @@ const logger = getLogger(__filename);
55 56
  * @param {number} [options.config.channelLastN=-1] The requested amount of
56 57
  * videos are going to be delivered after the value is in effect. Set to -1 for
57 58
  * unlimited or all available videos.
59
+ * @param {number} [options.config.forceJVB121Ratio]
60
+ * "Math.random() < forceJVB121Ratio" will determine whether a 2 people
61
+ * conference should be moved to the JVB instead of P2P. The decision is made on
62
+ * the responder side, after ICE succeeds on the P2P connection.
58 63
  * @constructor
59 64
  *
60 65
  * FIXME Make all methods which are called from lib-internal classes
@@ -265,6 +270,12 @@ JitsiConference.prototype._init = function(options = {}) {
265 270
         this.setLastN(options.config.channelLastN);
266 271
     }
267 272
 
273
+    /**
274
+     * Emits {@link JitsiConferenceEvents.JVB121_STATUS}.
275
+     * @type {Jvb121EventGenerator}
276
+     */
277
+    this.jvb121Status = new Jvb121EventGenerator(this);
278
+
268 279
     // creates dominant speaker detection that works only in p2p mode
269 280
     this.p2pDominantSpeakerDetection = new P2PDominantSpeakerDetection(this);
270 281
 };
@@ -1459,6 +1470,18 @@ JitsiConference.prototype.onCallEnded
1459 1470
         // Let the RTC service do any cleanups
1460 1471
         this.rtc.onCallEnded();
1461 1472
     } else if (jingleSession === this.p2pJingleSession) {
1473
+        // It's the responder who decides to enforce JVB mode, so that both
1474
+        // initiator and responder are aware if it was intentional.
1475
+        if (reasonCondition === 'decline' && reasonText === 'force JVB121') {
1476
+            logger.info('In forced JVB 121 mode...');
1477
+            Statistics.analytics.addPermanentProperties({ forceJvb121: true });
1478
+        } else if (reasonCondition === 'connectivity-error'
1479
+            && reasonText === 'ICE FAILED') {
1480
+            // It can happen that the other peer detects ICE failed and
1481
+            // terminates the session, before we get the event on our side.
1482
+            // But we are able to parse the reason and mark it here.
1483
+            Statistics.analytics.addPermanentProperties({ p2pFailed: true });
1484
+        }
1462 1485
         this._stopP2PSession();
1463 1486
     } else {
1464 1487
         logger.error(
@@ -1898,6 +1921,11 @@ JitsiConference.prototype._onIceConnectionFailed = function(session) {
1898 1921
     // We do nothing for the JVB connection, because it's up to the Jicofo to
1899 1922
     // eventually come up with the new offer (at least for the time being).
1900 1923
     if (session.isP2P) {
1924
+        // Add p2pFailed property to analytics to distinguish, between "good"
1925
+        // and "bad" connection
1926
+        Statistics.analytics.addPermanentProperties({ p2pFailed: true });
1927
+
1928
+        // Log analytics event, but only for the initiator to not count it twice
1901 1929
         if (this.p2pJingleSession && this.p2pJingleSession.isInitiator) {
1902 1930
             Statistics.sendEventToAll('p2p.failed');
1903 1931
         }
@@ -2000,12 +2028,26 @@ JitsiConference.prototype._addRemoteTracks = function(logName, remoteTracks) {
2000 2028
  */
2001 2029
 JitsiConference.prototype._onIceConnectionEstablished
2002 2030
 = function(jingleSession) {
2031
+    const forceJVB121Ratio = this.options.config.forceJVB121Ratio;
2032
+
2003 2033
     // We don't care about the JVB case, there's nothing to be done
2004 2034
     if (!jingleSession.isP2P) {
2005 2035
         return;
2006 2036
     } else if (this.p2pJingleSession !== jingleSession) {
2007 2037
         logger.error('CONNECTION_ESTABLISHED - wrong P2P session instance ?!');
2008 2038
 
2039
+        return;
2040
+    } else if (!jingleSession.isInitiator
2041
+        && typeof forceJVB121Ratio === 'number'
2042
+        && Math.random() < forceJVB121Ratio) {
2043
+        logger.info(`Forcing JVB 121 mode (ratio=${forceJVB121Ratio})...`);
2044
+        this._rejectIncomingCall(
2045
+            jingleSession, {
2046
+                reasonTag: 'decline',
2047
+                reasonMsg: 'force JVB121'
2048
+            });
2049
+        Statistics.analytics.addPermanentProperties({ forceJvb121: true });
2050
+
2009 2051
         return;
2010 2052
     }
2011 2053
 
@@ -2118,6 +2160,13 @@ JitsiConference.prototype._setP2PStatus = function(newStatus) {
2118 2160
     if (newStatus) {
2119 2161
         logger.info('Peer to peer connection established!');
2120 2162
 
2163
+        // When we end up in a valid P2P session need to reset the properties
2164
+        // in case they have persisted, after session with another peer.
2165
+        Statistics.analytics.addPermanentProperties({
2166
+            p2pFailed: false,
2167
+            forceJvb121: false
2168
+        });
2169
+
2121 2170
         // Sync up video transfer active in case p2pJingleSession not existed
2122 2171
         // when the lastN value was being adjusted.
2123 2172
         const isVideoActive = this.rtc.getLastN() !== 0;

+ 16
- 0
JitsiConferenceEvents.js Dosyayı Görüntüle

@@ -77,6 +77,22 @@ export const DTMF_SUPPORT_CHANGED = 'conference.dtmfSupportChanged';
77 77
  */
78 78
 export const ENDPOINT_MESSAGE_RECEIVED = 'conference.endpoint_message_received';
79 79
 
80
+/**
81
+ * NOTE This is lib-jitsi-meet internal event and can be removed at any time !
82
+ *
83
+ * Event emitted when conference transits, between one to one and multiparty JVB
84
+ * conference. If the conference switches to P2P it's neither one to one nor
85
+ * a multiparty JVB conference, but P2P (the status argument of this event will
86
+ * be <tt>false</tt>).
87
+ *
88
+ * The first argument is a boolean which carries the previous value and
89
+ * the seconds argument is a boolean with the new status. The event is emitted
90
+ * only if the previous and the new values are different.
91
+ *
92
+ * @type {string}
93
+ */
94
+export const JVB121_STATUS = 'conference.jvb121Status';
95
+
80 96
 /**
81 97
  * You are kicked from the conference.
82 98
  */

+ 55
- 0
modules/event/Jvb121EventGenerator.js Dosyayı Görüntüle

@@ -0,0 +1,55 @@
1
+/* global __filename */
2
+
3
+import { getLogger } from 'jitsi-meet-logger';
4
+import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
5
+
6
+const logger = getLogger(__filename);
7
+
8
+/**
9
+ * Emits {@link JitsiConferenceEvents.JVB121_STATUS} events based on the current
10
+ * P2P status and the conference participants count. See the event description
11
+ * for more info.
12
+ */
13
+export default class Jvb121EventGenerator {
14
+    /**
15
+     * Creates new <tt>Jvb121EventGenerator</tt> for the given conference.
16
+     * @param {JitsiConference} conference
17
+     */
18
+    constructor(conference) {
19
+        this._conference = conference;
20
+
21
+        /**
22
+         * Indicates whether it's a one to one JVB conference (<tt>true</tt>)
23
+         * or a multiparty (<tt>false</tt>). Will be also <tt>false</tt> if
24
+         * the conference is currently in the P2P mode.
25
+         * @type {boolean}
26
+         * @private
27
+         */
28
+        this._jvb121 = true;
29
+
30
+        this._conference.addEventListener(
31
+            JitsiConferenceEvents.USER_JOINED, () => this.evaluateStatus());
32
+        this._conference.addEventListener(
33
+            JitsiConferenceEvents.USER_LEFT, () => this.evaluateStatus());
34
+        this._conference.addEventListener(
35
+            JitsiConferenceEvents.P2P_STATUS, () => this.evaluateStatus());
36
+    }
37
+
38
+    /**
39
+     * Checks whether the JVB121 value should be updated and a new event
40
+     * emitted.
41
+     */
42
+    evaluateStatus() {
43
+        const oldStatus = this._jvb121;
44
+        const newStatus
45
+            = !this._conference.isP2PActive()
46
+                && this._conference.getParticipantCount() <= 2;
47
+
48
+        if (oldStatus !== newStatus) {
49
+            this._jvb121 = newStatus;
50
+            logger.debug(`JVB121 status ${oldStatus} => ${newStatus}`);
51
+            this._conference.eventEmitter.emit(
52
+                JitsiConferenceEvents.JVB121_STATUS, oldStatus, newStatus);
53
+        }
54
+    }
55
+}

+ 138
- 45
modules/statistics/AvgRTPStatsReporter.js Dosyayı Görüntüle

@@ -9,8 +9,55 @@ import RTCBrowserType from '../RTC/RTCBrowserType';
9 9
 import Statistics from './statistics';
10 10
 import * as VideoType from '../../service/RTC/VideoType';
11 11
 
12
+/**
13
+ * All avg RTP stats are currently reported under 1 event name, but under
14
+ * different keys. This constant stores the name of this event.
15
+ * Example structure of "avg.rtp.stats" analytics event:
16
+ *
17
+ * {
18
+ *   "stat_avg_rtt": {
19
+ *     value: 200,
20
+ *     samples: [ 100, 200, 300 ]
21
+ *   },
22
+ *   "stat_avg_packetloss_total": {
23
+ *     value: 10,
24
+ *     samples: [ 5, 10, 15]
25
+ *   },
26
+ *   "p2p_stat_avg_packetloss_total": {
27
+ *     value: 15,
28
+ *     samples: [ 10, 15, 20]
29
+ *   }
30
+ * }
31
+ *
32
+ * Note that the samples array is currently emitted for debug purposes only and
33
+ * can be removed anytime soon from the structure.
34
+ *
35
+ * Also not all values are always present in "avg.rtp.stats", some of the values
36
+ * are obtained and calculated as part of different process/event pipe. For
37
+ * example {@link ConnectionAvgStats} instances are doing the reports for each
38
+ * {@link TraceablePeerConnection} and work independently from the main stats
39
+ * pipe.
40
+ *
41
+ * @type {string}
42
+ */
43
+const AVG_RTP_STATS_EVENT = 'avg.rtp.stats';
44
+
12 45
 const logger = getLogger(__filename);
13 46
 
47
+/**
48
+ * Figures out what prefix should be added to the stat name.
49
+ * @param {boolean} isP2P is it P2P or JVB conference ?
50
+ * @param {number} conferenceSize how many participants are there in
51
+ * the conference (including us)
52
+ * @return {string} "" (for JVB conference) or "p2p_" (for P2P) or "jvb121_"
53
+ * (for JVB 2 participant conference).
54
+ */
55
+function getPrefix(isP2P, conferenceSize) {
56
+    return isP2P
57
+        ? 'p2p_'
58
+        : conferenceSize === 2 ? 'jvb121_' : '';
59
+}
60
+
14 61
 /**
15 62
  * This will calculate an average for one, named stat and submit it to
16 63
  * the analytics module when requested. It automatically counts the samples.
@@ -25,6 +72,7 @@ class AverageStatReport {
25 72
         this.name = name;
26 73
         this.count = 0;
27 74
         this.sum = 0;
75
+        this.samples = [];
28 76
     }
29 77
 
30 78
     /**
@@ -39,6 +87,7 @@ class AverageStatReport {
39 87
                 nextValue);
40 88
         } else if (!isNaN(nextValue)) {
41 89
             this.sum += nextValue;
90
+            this.samples.push(nextValue);
42 91
             this.count += 1;
43 92
         }
44 93
     }
@@ -53,16 +102,19 @@ class AverageStatReport {
53 102
     }
54 103
 
55 104
     /**
56
-     * Calculates an average and submit the report to the analytics module.
57
-     * @param {boolean} isP2P indicates if the report is to be submitted for
58
-     * the P2P connection (when conference is currently in the P2P mode). This
59
-     * will add 'p2p.' prefix to the name of the event. All averages should be
60
-     * cleared when the conference switches, between P2P and JVB modes.
105
+     * Appends the report to the analytics "data" object. The object will be
106
+     * set under <tt>prefix</tt> + {@link this.name} key.
107
+     * @param {Object} report the analytics "data" object
108
+     * @param {string} prefix the prefix string that will be added at
109
+     * the beginning of the key name.
61 110
      */
62
-    report(isP2P) {
63
-        Statistics.analytics.sendEvent(
64
-            `${isP2P ? 'p2p.' : ''}${this.name}`,
65
-            { value: this.calculate() });
111
+    appendReport(report, prefix) {
112
+        const keyName = `${prefix}${this.name}`;
113
+
114
+        report[keyName] = {
115
+            value: this.calculate(),
116
+            samples: this.samples
117
+        };
66 118
     }
67 119
 
68 120
     /**
@@ -70,6 +122,7 @@ class AverageStatReport {
70 122
      * calculated using this instance.
71 123
      */
72 124
     reset() {
125
+        this.samples = [];
73 126
         this.sum = 0;
74 127
         this.count = 0;
75 128
     }
@@ -114,7 +167,7 @@ class ConnectionAvgStats {
114 167
          * Average round trip time reported by the ICE candidate pair.
115 168
          * @type {AverageStatReport}
116 169
          */
117
-        this._avgRTT = new AverageStatReport('stat.avg.rtt');
170
+        this._avgRTT = new AverageStatReport('stat_avg_rtt');
118 171
 
119 172
         /**
120 173
          * Map stores average RTT to the JVB reported by remote participants.
@@ -177,7 +230,11 @@ class ConnectionAvgStats {
177 230
 
178 231
         if (this._sampleIdx >= this._n) {
179 232
             if (RTCBrowserType.supportsRTTStatistics()) {
180
-                this._avgRTT.report(this.isP2P);
233
+                const batchReport = { };
234
+                const confSize = this._conference.getParticipantCount();
235
+                const prefix = getPrefix(this.isP2P, confSize);
236
+
237
+                this._avgRTT.appendReport(batchReport, prefix);
181 238
 
182 239
                 // Report end to end RTT only for JVB
183 240
                 if (!this.isP2P) {
@@ -185,11 +242,14 @@ class ConnectionAvgStats {
185 242
                     const avgLocalRTT = this._avgRTT.calculate();
186 243
 
187 244
                     if (!isNaN(avgLocalRTT) && !isNaN(avgRemoteRTT)) {
188
-                        Statistics.analytics.sendEvent(
189
-                            'stat.avg.end2endrtt',
190
-                            { value: avgLocalRTT + avgRemoteRTT });
245
+                        // eslint-disable-next-line camelcase
246
+                        batchReport[`${prefix}stat_avg_end2endrtt`]
247
+                            = { value: avgLocalRTT + avgRemoteRTT };
191 248
                     }
192 249
                 }
250
+
251
+                Statistics.analytics.sendEvent(
252
+                    AVG_RTP_STATS_EVENT, batchReport);
193 253
             }
194 254
 
195 255
             this._resetAvgStats();
@@ -232,7 +292,7 @@ class ConnectionAvgStats {
232 292
         let rttAvg = this._avgRemoteRTTMap.get(id);
233 293
 
234 294
         if (!rttAvg && validData) {
235
-            rttAvg = new AverageStatReport(`${id}.stat.rtt`);
295
+            rttAvg = new AverageStatReport(`${id}_stat_rtt`);
236 296
             this._avgRemoteRTTMap.set(id, rttAvg);
237 297
         }
238 298
 
@@ -326,7 +386,7 @@ export default class AvgRTPStatsReporter {
326 386
          * @private
327 387
          */
328 388
         this._avgAudioBitrateUp
329
-            = new AverageStatReport('stat.avg.bitrate.audio.upload');
389
+            = new AverageStatReport('stat_avg_bitrate_audio_upload');
330 390
 
331 391
         /**
332 392
          * Average audio download bitrate
@@ -334,7 +394,7 @@ export default class AvgRTPStatsReporter {
334 394
          * @private
335 395
          */
336 396
         this._avgAudioBitrateDown
337
-            = new AverageStatReport('stat.avg.bitrate.audio.download');
397
+            = new AverageStatReport('stat_avg_bitrate_audio_download');
338 398
 
339 399
         /**
340 400
          * Average video upload bitrate
@@ -342,7 +402,7 @@ export default class AvgRTPStatsReporter {
342 402
          * @private
343 403
          */
344 404
         this._avgVideoBitrateUp
345
-            = new AverageStatReport('stat.avg.bitrate.video.upload');
405
+            = new AverageStatReport('stat_avg_bitrate_video_upload');
346 406
 
347 407
         /**
348 408
          * Average video download bitrate
@@ -350,7 +410,7 @@ export default class AvgRTPStatsReporter {
350 410
          * @private
351 411
          */
352 412
         this._avgVideoBitrateDown
353
-            = new AverageStatReport('stat.avg.bitrate.video.download');
413
+            = new AverageStatReport('stat_avg_bitrate_video_download');
354 414
 
355 415
         /**
356 416
          * Average upload bandwidth
@@ -358,7 +418,7 @@ export default class AvgRTPStatsReporter {
358 418
          * @private
359 419
          */
360 420
         this._avgBandwidthUp
361
-            = new AverageStatReport('stat.avg.bandwidth.upload');
421
+            = new AverageStatReport('stat_avg_bandwidth_upload');
362 422
 
363 423
         /**
364 424
          * Average download bandwidth
@@ -366,7 +426,7 @@ export default class AvgRTPStatsReporter {
366 426
          * @private
367 427
          */
368 428
         this._avgBandwidthDown
369
-            = new AverageStatReport('stat.avg.bandwidth.download');
429
+            = new AverageStatReport('stat_avg_bandwidth_download');
370 430
 
371 431
         /**
372 432
          * Average total packet loss
@@ -374,7 +434,7 @@ export default class AvgRTPStatsReporter {
374 434
          * @private
375 435
          */
376 436
         this._avgPacketLossTotal
377
-            = new AverageStatReport('stat.avg.packetloss.total');
437
+            = new AverageStatReport('stat_avg_packetloss_total');
378 438
 
379 439
         /**
380 440
          * Average upload packet loss
@@ -382,7 +442,7 @@ export default class AvgRTPStatsReporter {
382 442
          * @private
383 443
          */
384 444
         this._avgPacketLossUp
385
-            = new AverageStatReport('stat.avg.packetloss.upload');
445
+            = new AverageStatReport('stat_avg_packetloss_upload');
386 446
 
387 447
         /**
388 448
          * Average download packet loss
@@ -390,14 +450,14 @@ export default class AvgRTPStatsReporter {
390 450
          * @private
391 451
          */
392 452
         this._avgPacketLossDown
393
-            = new AverageStatReport('stat.avg.packetloss.download');
453
+            = new AverageStatReport('stat_avg_packetloss_download');
394 454
 
395 455
         /**
396 456
          * Average FPS for remote videos
397 457
          * @type {AverageStatReport}
398 458
          * @private
399 459
          */
400
-        this._avgRemoteFPS = new AverageStatReport('stat.avg.framerate.remote');
460
+        this._avgRemoteFPS = new AverageStatReport('stat_avg_framerate_remote');
401 461
 
402 462
         /**
403 463
          * Average FPS for remote screen streaming videos (reported only if not
@@ -406,14 +466,14 @@ export default class AvgRTPStatsReporter {
406 466
          * @private
407 467
          */
408 468
         this._avgRemoteScreenFPS
409
-            = new AverageStatReport('stat.avg.framerate.screen.remote');
469
+            = new AverageStatReport('stat_avg_framerate_screen_remote');
410 470
 
411 471
         /**
412 472
          * Average FPS for local video (camera)
413 473
          * @type {AverageStatReport}
414 474
          * @private
415 475
          */
416
-        this._avgLocalFPS = new AverageStatReport('stat.avg.framerate.local');
476
+        this._avgLocalFPS = new AverageStatReport('stat_avg_framerate_local');
417 477
 
418 478
         /**
419 479
          * Average FPS for local screen streaming video (reported only if not
@@ -422,7 +482,7 @@ export default class AvgRTPStatsReporter {
422 482
          * @private
423 483
          */
424 484
         this._avgLocalScreenFPS
425
-            = new AverageStatReport('stat.avg.framerate.screen.local');
485
+            = new AverageStatReport('stat_avg_framerate_screen_local');
426 486
 
427 487
         /**
428 488
          * Average connection quality as defined by
@@ -430,7 +490,7 @@ export default class AvgRTPStatsReporter {
430 490
          * @type {AverageStatReport}
431 491
          * @private
432 492
          */
433
-        this._avgCQ = new AverageStatReport('stat.avg.cq');
493
+        this._avgCQ = new AverageStatReport('stat_avg_cq');
434 494
 
435 495
         this._onLocalStatsUpdated = data => this._calculateAvgStats(data);
436 496
         conference.on(
@@ -447,6 +507,19 @@ export default class AvgRTPStatsReporter {
447 507
             ConferenceEvents.P2P_STATUS,
448 508
             this._onP2PStatusChanged);
449 509
 
510
+        this._onJvb121StatusChanged = (oldStatus, newStatus) => {
511
+            // We want to reset only on the transition from false => true,
512
+            // because otherwise those stats are resetted on JVB <=> P2P
513
+            // transition.
514
+            if (newStatus === true) {
515
+                logger.info('Resetting JVB avg RTP stats');
516
+                this._resetAvgJvbStats();
517
+            }
518
+        };
519
+        conference.on(
520
+            ConferenceEvents.JVB121_STATUS,
521
+            this._onJvb121StatusChanged);
522
+
450 523
         this.jvbStatsMonitor
451 524
             = new ConnectionAvgStats(conference, false /* JVB */, n);
452 525
 
@@ -463,9 +536,10 @@ export default class AvgRTPStatsReporter {
463 536
     _calculateAvgStats(data) {
464 537
 
465 538
         const isP2P = this._conference.isP2PActive();
466
-        const peerCount = this._conference.getParticipants().length;
539
+        const confSize = this._conference.getParticipantCount();
540
+        const prefix = getPrefix(isP2P, confSize);
467 541
 
468
-        if (!isP2P && peerCount < 1) {
542
+        if (!isP2P && confSize < 2) {
469 543
 
470 544
             // There's no point in collecting stats for a JVB conference of 1.
471 545
             // That happens for short period of time after everyone leaves
@@ -545,30 +619,34 @@ export default class AvgRTPStatsReporter {
545 619
         this._sampleIdx += 1;
546 620
 
547 621
         if (this._sampleIdx >= this._n) {
548
-            this._avgAudioBitrateUp.report(isP2P);
549
-            this._avgAudioBitrateDown.report(isP2P);
622
+            const batchReport = { };
550 623
 
551
-            this._avgVideoBitrateUp.report(isP2P);
552
-            this._avgVideoBitrateDown.report(isP2P);
624
+            this._avgAudioBitrateUp.appendReport(batchReport, prefix);
625
+            this._avgAudioBitrateDown.appendReport(batchReport, prefix);
626
+
627
+            this._avgVideoBitrateUp.appendReport(batchReport, prefix);
628
+            this._avgVideoBitrateDown.appendReport(batchReport, prefix);
553 629
 
554 630
             if (RTCBrowserType.supportsBandwidthStatistics()) {
555
-                this._avgBandwidthUp.report(isP2P);
556
-                this._avgBandwidthDown.report(isP2P);
631
+                this._avgBandwidthUp.appendReport(batchReport, prefix);
632
+                this._avgBandwidthDown.appendReport(batchReport, prefix);
557 633
             }
558
-            this._avgPacketLossUp.report(isP2P);
559
-            this._avgPacketLossDown.report(isP2P);
560
-            this._avgPacketLossTotal.report(isP2P);
634
+            this._avgPacketLossUp.appendReport(batchReport, prefix);
635
+            this._avgPacketLossDown.appendReport(batchReport, prefix);
636
+            this._avgPacketLossTotal.appendReport(batchReport, prefix);
561 637
 
562
-            this._avgRemoteFPS.report(isP2P);
638
+            this._avgRemoteFPS.appendReport(batchReport, prefix);
563 639
             if (!isNaN(this._avgRemoteScreenFPS.calculate())) {
564
-                this._avgRemoteScreenFPS.report(isP2P);
640
+                this._avgRemoteScreenFPS.appendReport(batchReport, prefix);
565 641
             }
566
-            this._avgLocalFPS.report(isP2P);
642
+            this._avgLocalFPS.appendReport(batchReport, prefix);
567 643
             if (!isNaN(this._avgLocalScreenFPS.calculate())) {
568
-                this._avgLocalScreenFPS.report(isP2P);
644
+                this._avgLocalScreenFPS.appendReport(batchReport, prefix);
569 645
             }
570 646
 
571
-            this._avgCQ.report(isP2P);
647
+            this._avgCQ.appendReport(batchReport, prefix);
648
+
649
+            Statistics.analytics.sendEvent(AVG_RTP_STATS_EVENT, batchReport);
572 650
 
573 651
             this._resetAvgStats();
574 652
         }
@@ -667,6 +745,18 @@ export default class AvgRTPStatsReporter {
667 745
         return peerFpsSum / peerSsrcCount;
668 746
     }
669 747
 
748
+    /**
749
+     * Resets the stats related to JVB connection. Must not be called when in
750
+     * P2P mode, because then the {@link AverageStatReport} instances are
751
+     * tracking P2P stats. Note that this should never happen unless something
752
+     * is wrong with the P2P and JVB121 events.
753
+     * @private
754
+     */
755
+    _resetAvgJvbStats() {
756
+        this._resetAvgStats();
757
+        this.jvbStatsMonitor._resetAvgStats();
758
+    }
759
+
670 760
     /**
671 761
      * Reset cache of all averages and {@link _sampleIdx}.
672 762
      * @private
@@ -705,6 +795,9 @@ export default class AvgRTPStatsReporter {
705 795
         this._conference.off(
706 796
             ConnectionQualityEvents.LOCAL_STATS_UPDATED,
707 797
             this._onLocalStatsUpdated);
798
+        this._conference.off(
799
+            ConferenceEvents.JVB121_STATUS,
800
+            this._onJvb121StatusChanged);
708 801
         this.jvbStatsMonitor.dispose();
709 802
         this.p2pStatsMonitor.dispose();
710 803
     }

+ 14
- 11
modules/xmpp/JingleSessionPC.js Dosyayı Görüntüle

@@ -570,10 +570,7 @@ export default class JingleSessionPC extends JingleSession {
570 570
         // a lot later. See webrtc issue #2340
571 571
         // logger.log('was this the last candidate', this.lasticecandidate);
572 572
         this.connection.sendIQ(
573
-            cand, null, this.newJingleErrorHandler(cand, error => {
574
-                GlobalOnErrorHandler.callErrorHandler(
575
-                    new Error(`Jingle error: ${JSON.stringify(error)}`));
576
-            }), IQ_TIMEOUT);
573
+            cand, null, this.newJingleErrorHandler(cand), IQ_TIMEOUT);
577 574
     }
578 575
 
579 576
     /**
@@ -2063,7 +2060,7 @@ export default class JingleSessionPC extends JingleSession {
2063 2060
      *  reason: {the name of XMPP error reason element or 'timeout' if the
2064 2061
       *          request has timed out within <tt>IQ_TIMEOUT</tt> milliseconds}
2065 2062
      *  source: {request.tree() that provides original request}
2066
-     *  session: {JingleSessionPC instance on which the error occurred}
2063
+     *  session: {this JingleSessionPC.toString()}
2067 2064
      * }
2068 2065
      * @param request Strophe IQ instance which is the request to be dumped into
2069 2066
      *        the error structure
@@ -2072,7 +2069,7 @@ export default class JingleSessionPC extends JingleSession {
2072 2069
      * @returns {function(this:JingleSessionPC)}
2073 2070
      */
2074 2071
     newJingleErrorHandler(request, failureCb) {
2075
-        return function(errResponse) {
2072
+        return errResponse => {
2076 2073
 
2077 2074
             const error = {};
2078 2075
 
@@ -2100,15 +2097,21 @@ export default class JingleSessionPC extends JingleSession {
2100 2097
                 error.source = error.source.outerHTML;
2101 2098
             }
2102 2099
 
2103
-            // Commented to fix JSON.stringify(error) exception for circular
2104
-            // dependancies when we print that error.
2105
-            // FIXME: Maybe we can include part of the session object
2106
-            // error.session = this;
2100
+            error.session = this.toString();
2107 2101
 
2108 2102
             if (failureCb) {
2109 2103
                 failureCb(error);
2104
+            } else if (this.state === JingleSessionState.ENDED
2105
+                        && error.reason === 'item-not-found') {
2106
+                // When remote peer decides to terminate the session, but it
2107
+                // still have few messages on the queue for processing,
2108
+                // it will first send us 'session-terminate' (we enter ENDED)
2109
+                // and then follow with 'item-not-found' for the queued requests
2110
+                // We don't want to have that logged on error level.
2111
+                logger.debug('Jingle error', error);
2110 2112
             } else {
2111
-                logger.error('Jingle error', error);
2113
+                GlobalOnErrorHandler.callErrorHandler(
2114
+                    new Error(`Jingle error: ${JSON.stringify(error)}`));
2112 2115
             }
2113 2116
         };
2114 2117
     }

Loading…
İptal
Kaydet