瀏覽代碼

Exports additional statistics through ConnectionQuality (#813)

* feat: Read the server region from Jingle and broadcast it with statistics.

* feat: Adds the bridge count to local "statistics", refactors conference-properties.

* fix: Emits the conference properties with the event, small fixes.

* ref: Orders the imports alphabetically.

As described by @virtuacoplenny:
[T]he ordering is based on import path, not import name, with different
file depths being grouped together, node modules being grouped together
at the top.

* fix: Keeps JitsiConference#properties always defined.

* fix: Does not fire an event when the argument is undefined.
release-8443
bgrozev 7 年之前
父節點
當前提交
1ac6df97e3
共有 7 個檔案被更改,包括 151 行新增56 行删除
  1. 103
    32
      JitsiConference.js
  2. 13
    0
      JitsiConferenceEvents.js
  3. 18
    2
      modules/connectivity/ConnectionQuality.js
  4. 7
    22
      modules/xmpp/ChatRoom.js
  5. 5
    0
      package-lock.json
  6. 1
    0
      package.json
  7. 4
    0
      service/xmpp/XMPPEvents.js

+ 103
- 32
JitsiConference.js 查看文件

@@ -1,54 +1,55 @@
1 1
 /* global __filename, $, Promise */
2 2
 import { Strophe } from 'strophe.js';
3 3
 
4
-import {
5
-    ACTION_JINGLE_RESTART,
6
-    ACTION_JINGLE_SI_RECEIVED,
7
-    ACTION_JINGLE_SI_TIMEOUT,
8
-    ACTION_JINGLE_TERMINATE,
9
-    ACTION_P2P_ESTABLISHED,
10
-    ACTION_P2P_FAILED,
11
-    ACTION_P2P_SWITCH_TO_JVB,
12
-    ICE_ESTABLISHMENT_DURATION_DIFF,
13
-    createJingleEvent,
14
-    createP2PEvent
15
-} from './service/statistics/AnalyticsEvents';
16
-import AvgRTPStatsReporter from './modules/statistics/AvgRTPStatsReporter';
17
-import ComponentsVersions from './modules/version/ComponentsVersions';
18
-import ConnectionQuality from './modules/connectivity/ConnectionQuality';
19
-import E2ePing from './modules/e2eping/e2eping';
20
-import { getLogger } from 'jitsi-meet-logger';
21
-import GlobalOnErrorHandler from './modules/util/GlobalOnErrorHandler';
22 4
 import EventEmitter from 'events';
23
-import authenticateAndUpgradeRole from './authenticateAndUpgradeRole';
5
+import { getLogger } from 'jitsi-meet-logger';
6
+import isEqual from 'lodash.isequal';
7
+
24 8
 import * as JitsiConferenceErrors from './JitsiConferenceErrors';
25 9
 import JitsiConferenceEventManager from './JitsiConferenceEventManager';
26 10
 import * as JitsiConferenceEvents from './JitsiConferenceEvents';
27
-import JitsiDTMFManager from './modules/DTMF/JitsiDTMFManager';
28 11
 import JitsiParticipant from './JitsiParticipant';
29 12
 import JitsiTrackError from './JitsiTrackError';
30 13
 import * as JitsiTrackErrors from './JitsiTrackErrors';
31 14
 import * as JitsiTrackEvents from './JitsiTrackEvents';
32
-import Jvb121EventGenerator from './modules/event/Jvb121EventGenerator';
33
-import * as MediaType from './service/RTC/MediaType';
34
-import ParticipantConnectionStatusHandler
35
-    from './modules/connectivity/ParticipantConnectionStatus';
15
+import authenticateAndUpgradeRole from './authenticateAndUpgradeRole';
16
+import JitsiDTMFManager from './modules/DTMF/JitsiDTMFManager';
36 17
 import P2PDominantSpeakerDetection from './modules/P2PDominantSpeakerDetection';
37 18
 import RTC from './modules/RTC/RTC';
19
+import TalkMutedDetection from './modules/TalkMutedDetection';
38 20
 import browser from './modules/browser';
39
-import * as RTCEvents from './service/RTC/RTCEvents';
21
+import ConnectionQuality from './modules/connectivity/ConnectionQuality';
22
+import ParticipantConnectionStatusHandler
23
+    from './modules/connectivity/ParticipantConnectionStatus';
24
+import E2ePing from './modules/e2eping/e2eping';
25
+import Jvb121EventGenerator from './modules/event/Jvb121EventGenerator';
26
+import RecordingManager from './modules/recording/RecordingManager';
27
+import RttMonitor from './modules/rttmonitor/rttmonitor';
28
+import AvgRTPStatsReporter from './modules/statistics/AvgRTPStatsReporter';
29
+import SpeakerStatsCollector from './modules/statistics/SpeakerStatsCollector';
40 30
 import Statistics from './modules/statistics/statistics';
41
-import TalkMutedDetection from './modules/TalkMutedDetection';
42 31
 import Transcriber from './modules/transcription/transcriber';
43
-import VideoType from './service/RTC/VideoType';
44
-import RecordingManager from './modules/recording/RecordingManager';
32
+import GlobalOnErrorHandler from './modules/util/GlobalOnErrorHandler';
33
+import ComponentsVersions from './modules/version/ComponentsVersions';
45 34
 import VideoSIPGW from './modules/videosipgw/VideoSIPGW';
46 35
 import * as VideoSIPGWConstants from './modules/videosipgw/VideoSIPGWConstants';
47
-import * as XMPPEvents from './service/xmpp/XMPPEvents';
48 36
 import { JITSI_MEET_MUC_TYPE } from './modules/xmpp/ChatRoom';
49
-import RttMonitor from './modules/rttmonitor/rttmonitor';
50
-
51
-import SpeakerStatsCollector from './modules/statistics/SpeakerStatsCollector';
37
+import * as MediaType from './service/RTC/MediaType';
38
+import * as RTCEvents from './service/RTC/RTCEvents';
39
+import VideoType from './service/RTC/VideoType';
40
+import {
41
+    ACTION_JINGLE_RESTART,
42
+    ACTION_JINGLE_SI_RECEIVED,
43
+    ACTION_JINGLE_SI_TIMEOUT,
44
+    ACTION_JINGLE_TERMINATE,
45
+    ACTION_P2P_ESTABLISHED,
46
+    ACTION_P2P_FAILED,
47
+    ACTION_P2P_SWITCH_TO_JVB,
48
+    ICE_ESTABLISHMENT_DURATION_DIFF,
49
+    createJingleEvent,
50
+    createP2PEvent
51
+} from './service/statistics/AnalyticsEvents';
52
+import * as XMPPEvents from './service/xmpp/XMPPEvents';
52 53
 
53 54
 const logger = getLogger(__filename);
54 55
 
@@ -142,6 +143,9 @@ export default function JitsiConference(options) {
142 143
     // the restart.
143 144
     this.wasStopped = false;
144 145
 
146
+    // Conference properties, maintained by jicofo.
147
+    this.properties = {};
148
+
145 149
     /**
146 150
      * The object which monitors local and remote connection statistics (e.g.
147 151
      * sending bitrate) and calculates a number which represents the connection
@@ -254,6 +258,10 @@ JitsiConference.prototype._init = function(options = {}) {
254 258
 
255 259
     this.room.updateDeviceAvailability(RTC.getDeviceAvailability());
256 260
 
261
+    this._updateProperties = this._updateProperties.bind(this);
262
+    this.room.addListener(XMPPEvents.CONFERENCE_PROPERTIES_CHANGED,
263
+        this._updateProperties);
264
+
257 265
     this.rttMonitor = new RttMonitor(config.rttMonitor || {});
258 266
 
259 267
     this.e2eping = new E2ePing(
@@ -457,6 +465,10 @@ JitsiConference.prototype.leave = function() {
457 465
             XMPPEvents.CONNECTION_ESTABLISHED,
458 466
             this._onIceConnectionEstablished);
459 467
 
468
+        room.removeListener(
469
+            XMPPEvents.CONFERENCE_PROPERTIES_CHANGED,
470
+            this._updateProperties);
471
+
460 472
         this.room = null;
461 473
 
462 474
         return room.leave().catch(error => {
@@ -1623,6 +1635,15 @@ JitsiConference.prototype._acceptJvbIncomingCall = function(
1623 1635
             createJingleEvent(ACTION_JINGLE_RESTART, { p2p: false }));
1624 1636
     }
1625 1637
 
1638
+    const serverRegion
1639
+        = $(jingleOffer)
1640
+            .find('>server-region[xmlns="http://jitsi.org/protocol/focus"]')
1641
+            .attr('region');
1642
+
1643
+    this.eventEmitter.emit(
1644
+        JitsiConferenceEvents.SERVER_REGION_CHANGED,
1645
+        serverRegion);
1646
+
1626 1647
     this._maybeClearSITimeout();
1627 1648
     Statistics.sendAnalytics(createJingleEvent(
1628 1649
         ACTION_JINGLE_SI_RECEIVED,
@@ -2530,6 +2551,56 @@ JitsiConference.prototype._onIceConnectionEstablished = function(
2530 2551
 
2531 2552
 };
2532 2553
 
2554
+/**
2555
+ * Called when the chat room reads a new list of properties from jicofo's
2556
+ * presence. The properties may have changed, but they don't have to.
2557
+ *
2558
+ * @param {Object} properties - The properties keyed by the property name
2559
+ * ('key').
2560
+ * @private
2561
+ */
2562
+JitsiConference.prototype._updateProperties = function(properties = {}) {
2563
+    const changed = isEqual(properties, this.properties);
2564
+
2565
+    this.properties = properties;
2566
+    if (changed) {
2567
+        this.eventEmitter.emit(
2568
+            JitsiConferenceEvents.PROPERTIES_CHANGED,
2569
+            this.properties);
2570
+
2571
+        // Some of the properties need to be added to analytics events.
2572
+        const analyticsKeys = [
2573
+
2574
+            // The number of jitsi-videobridge instances currently used for the
2575
+            // conference.
2576
+            'bridge-count',
2577
+
2578
+            // The conference creation time (set by jicofo).
2579
+            'created-ms',
2580
+            'octo-enabled'
2581
+        ];
2582
+
2583
+        analyticsKeys.forEach(key => {
2584
+            if (this.properties[key]
2585
+                && this.properties[key].value !== undefined) {
2586
+                Statistics.analytics.addPermanentProperties({
2587
+                    [key.replace('-', '_')]: properties[key].value
2588
+                });
2589
+            }
2590
+        });
2591
+    }
2592
+};
2593
+
2594
+/**
2595
+ * Gets a conference property with a given key.
2596
+ *
2597
+ * @param {string} key - The key.
2598
+ * @returns {*} The value
2599
+ */
2600
+JitsiConference.prototype.getProperty = function(key) {
2601
+    return this.properties[key];
2602
+};
2603
+
2533 2604
 /**
2534 2605
  * Clears the deferred start P2P task if it has been scheduled.
2535 2606
  * @private

+ 13
- 0
JitsiConferenceEvents.js 查看文件

@@ -127,6 +127,13 @@ export const LAST_N_ENDPOINTS_CHANGED = 'conference.lastNEndpointsChanged';
127 127
  */
128 128
 export const LOCK_STATE_CHANGED = 'conference.lock_state_changed';
129 129
 
130
+/**
131
+ * Indicates that the region of the media server (jitsi-videobridge) that we
132
+ * are connected to changed (or was initially set).
133
+ * @type {string} the region.
134
+ */
135
+export const SERVER_REGION_CHANGED = 'conference.server_region_changed';
136
+
130 137
 /**
131 138
  * New text message was received.
132 139
  */
@@ -179,6 +186,12 @@ export const P2P_STATUS = 'conference.p2pStatus';
179 186
  */
180 187
 export const PHONE_NUMBER_CHANGED = 'conference.phoneNumberChanged';
181 188
 
189
+/**
190
+ * The conference properties changed.
191
+ * @type {string}
192
+ */
193
+export const PROPERTIES_CHANGED = 'conference.propertiesChanged';
194
+
182 195
 /**
183 196
  * Indicates that recording state changed.
184 197
  */

+ 18
- 2
modules/connectivity/ConnectionQuality.js 查看文件

@@ -278,6 +278,20 @@ export default class ConnectionQuality {
278 278
                     this._maybeUpdateUnmuteTime();
279 279
                 }
280 280
             });
281
+
282
+        conference.on(
283
+            ConferenceEvents.SERVER_REGION_CHANGED,
284
+            serverRegion => {
285
+                this._localStats.serverRegion = serverRegion;
286
+            });
287
+
288
+        conference.on(
289
+            ConferenceEvents.PROPERTIES_CHANGED,
290
+            properties => {
291
+                this._localStats.bridgeCount
292
+                    = Number((properties || {})['bridge-count']);
293
+            }
294
+        );
281 295
     }
282 296
 
283 297
     /**
@@ -438,7 +452,8 @@ export default class ConnectionQuality {
438 452
             bitrate: this._localStats.bitrate,
439 453
             packetLoss: this._localStats.packetLoss,
440 454
             connectionQuality: this._localStats.connectionQuality,
441
-            jvbRTT: this._localStats.jvbRTT
455
+            jvbRTT: this._localStats.jvbRTT,
456
+            serverRegion: this._localStats.serverRegion
442 457
         };
443 458
 
444 459
         try {
@@ -527,7 +542,8 @@ export default class ConnectionQuality {
527 542
             bitrate: data.bitrate,
528 543
             packetLoss: data.packetLoss,
529 544
             connectionQuality: data.connectionQuality,
530
-            jvbRTT: data.jvbRTT
545
+            jvbRTT: data.jvbRTT,
546
+            serverRegion: data.serverRegion
531 547
         };
532 548
 
533 549
         this.eventEmitter.emit(

+ 7
- 22
modules/xmpp/ChatRoom.js 查看文件

@@ -11,7 +11,6 @@ import * as MediaType from '../../service/RTC/MediaType';
11 11
 import XMPPEvents from '../../service/xmpp/XMPPEvents';
12 12
 
13 13
 import Moderator from './moderator';
14
-import Statistics from '../statistics/statistics';
15 14
 
16 15
 const logger = getLogger(__filename);
17 16
 
@@ -625,32 +624,18 @@ export default class ChatRoom extends Listenable {
625 624
                 break;
626 625
             case 'conference-properties':
627 626
                 if (member.isFocus) {
627
+                    const properties = {};
628
+
628 629
                     for (let j = 0; j < node.children.length; j++) {
629 630
                         const { attributes } = node.children[j];
630 631
 
631
-                        if (!attributes) {
632
-                            break;
632
+                        if (attributes && attributes.key) {
633
+                            properties[attributes.key] = attributes.value;
633 634
                         }
634
-
635
-                        const { key, value } = attributes;
636
-
637
-                        /* eslint-disable no-fallthrough */
638
-                        switch (key) {
639
-
640
-                        // The number of jitsi-videobridge instances currently
641
-                        // used for the conference.
642
-                        case 'bridge-count':
643
-
644
-                        // The conference creation time (set by jicofo).
645
-                        case 'created-ms':
646
-                        case 'octo-enabled':
647
-                            Statistics.analytics.addPermanentProperties({
648
-                                [key.replace('-', '_')]: value
649
-                            });
650
-                            break;
651
-                        }
652
-                        /* eslint-enable no-fallthrough */
653 635
                     }
636
+
637
+                    this.eventEmitter.emit(
638
+                        XMPPEvents.CONFERENCE_PROPERTIES_CHANGED, properties);
654 639
                 }
655 640
                 break;
656 641
             case 'transcription-status': {

+ 5
- 0
package-lock.json 查看文件

@@ -5538,6 +5538,11 @@
5538 5538
       "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
5539 5539
       "dev": true
5540 5540
     },
5541
+    "lodash.isequal": {
5542
+      "version": "4.5.0",
5543
+      "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
5544
+      "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
5545
+    },
5541 5546
     "log-symbols": {
5542 5547
       "version": "2.2.0",
5543 5548
       "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",

+ 1
- 0
package.json 查看文件

@@ -22,6 +22,7 @@
22 22
     "current-executing-script": "0.1.3",
23 23
     "jitsi-meet-logger": "github:jitsi/jitsi-meet-logger#6fff754a77a56ab52499f3559105a15886942a1e",
24 24
     "js-utils": "github:jitsi/js-utils#d4b78721b754a15c2588b7b0c621a9fff6fa1363",
25
+    "lodash.isequal": "4.5.0",
25 26
     "react-native-callstats": "3.53.4",
26 27
     "sdp-transform": "2.3.0",
27 28
     "strophe.js": "1.2.15",

+ 4
- 0
service/xmpp/XMPPEvents.js 查看文件

@@ -25,6 +25,10 @@ const XMPPEvents = {
25 25
     // person in the conference room.
26 26
     CALL_ENDED: 'xmpp.callended.jingle',
27 27
     CHAT_ERROR_RECEIVED: 'xmpp.chat_error_received',
28
+
29
+    // The conference properties (as advertised by jicofo) have changed
30
+    CONFERENCE_PROPERTIES_CHANGED: 'xmpp.conference_properties_changed',
31
+
28 32
     CONFERENCE_SETUP_FAILED: 'xmpp.conference_setup_failed',
29 33
 
30 34
     /**

Loading…
取消
儲存