瀏覽代碼

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.
master
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
 /* global __filename, $, Promise */
1
 /* global __filename, $, Promise */
2
 import { Strophe } from 'strophe.js';
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
 import EventEmitter from 'events';
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
 import * as JitsiConferenceErrors from './JitsiConferenceErrors';
8
 import * as JitsiConferenceErrors from './JitsiConferenceErrors';
25
 import JitsiConferenceEventManager from './JitsiConferenceEventManager';
9
 import JitsiConferenceEventManager from './JitsiConferenceEventManager';
26
 import * as JitsiConferenceEvents from './JitsiConferenceEvents';
10
 import * as JitsiConferenceEvents from './JitsiConferenceEvents';
27
-import JitsiDTMFManager from './modules/DTMF/JitsiDTMFManager';
28
 import JitsiParticipant from './JitsiParticipant';
11
 import JitsiParticipant from './JitsiParticipant';
29
 import JitsiTrackError from './JitsiTrackError';
12
 import JitsiTrackError from './JitsiTrackError';
30
 import * as JitsiTrackErrors from './JitsiTrackErrors';
13
 import * as JitsiTrackErrors from './JitsiTrackErrors';
31
 import * as JitsiTrackEvents from './JitsiTrackEvents';
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
 import P2PDominantSpeakerDetection from './modules/P2PDominantSpeakerDetection';
17
 import P2PDominantSpeakerDetection from './modules/P2PDominantSpeakerDetection';
37
 import RTC from './modules/RTC/RTC';
18
 import RTC from './modules/RTC/RTC';
19
+import TalkMutedDetection from './modules/TalkMutedDetection';
38
 import browser from './modules/browser';
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
 import Statistics from './modules/statistics/statistics';
30
 import Statistics from './modules/statistics/statistics';
41
-import TalkMutedDetection from './modules/TalkMutedDetection';
42
 import Transcriber from './modules/transcription/transcriber';
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
 import VideoSIPGW from './modules/videosipgw/VideoSIPGW';
34
 import VideoSIPGW from './modules/videosipgw/VideoSIPGW';
46
 import * as VideoSIPGWConstants from './modules/videosipgw/VideoSIPGWConstants';
35
 import * as VideoSIPGWConstants from './modules/videosipgw/VideoSIPGWConstants';
47
-import * as XMPPEvents from './service/xmpp/XMPPEvents';
48
 import { JITSI_MEET_MUC_TYPE } from './modules/xmpp/ChatRoom';
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
 const logger = getLogger(__filename);
54
 const logger = getLogger(__filename);
54
 
55
 
142
     // the restart.
143
     // the restart.
143
     this.wasStopped = false;
144
     this.wasStopped = false;
144
 
145
 
146
+    // Conference properties, maintained by jicofo.
147
+    this.properties = {};
148
+
145
     /**
149
     /**
146
      * The object which monitors local and remote connection statistics (e.g.
150
      * The object which monitors local and remote connection statistics (e.g.
147
      * sending bitrate) and calculates a number which represents the connection
151
      * sending bitrate) and calculates a number which represents the connection
254
 
258
 
255
     this.room.updateDeviceAvailability(RTC.getDeviceAvailability());
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
     this.rttMonitor = new RttMonitor(config.rttMonitor || {});
265
     this.rttMonitor = new RttMonitor(config.rttMonitor || {});
258
 
266
 
259
     this.e2eping = new E2ePing(
267
     this.e2eping = new E2ePing(
457
             XMPPEvents.CONNECTION_ESTABLISHED,
465
             XMPPEvents.CONNECTION_ESTABLISHED,
458
             this._onIceConnectionEstablished);
466
             this._onIceConnectionEstablished);
459
 
467
 
468
+        room.removeListener(
469
+            XMPPEvents.CONFERENCE_PROPERTIES_CHANGED,
470
+            this._updateProperties);
471
+
460
         this.room = null;
472
         this.room = null;
461
 
473
 
462
         return room.leave().catch(error => {
474
         return room.leave().catch(error => {
1623
             createJingleEvent(ACTION_JINGLE_RESTART, { p2p: false }));
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
     this._maybeClearSITimeout();
1647
     this._maybeClearSITimeout();
1627
     Statistics.sendAnalytics(createJingleEvent(
1648
     Statistics.sendAnalytics(createJingleEvent(
1628
         ACTION_JINGLE_SI_RECEIVED,
1649
         ACTION_JINGLE_SI_RECEIVED,
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
  * Clears the deferred start P2P task if it has been scheduled.
2605
  * Clears the deferred start P2P task if it has been scheduled.
2535
  * @private
2606
  * @private

+ 13
- 0
JitsiConferenceEvents.js 查看文件

127
  */
127
  */
128
 export const LOCK_STATE_CHANGED = 'conference.lock_state_changed';
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
  * New text message was received.
138
  * New text message was received.
132
  */
139
  */
179
  */
186
  */
180
 export const PHONE_NUMBER_CHANGED = 'conference.phoneNumberChanged';
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
  * Indicates that recording state changed.
196
  * Indicates that recording state changed.
184
  */
197
  */

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

278
                     this._maybeUpdateUnmuteTime();
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
             bitrate: this._localStats.bitrate,
452
             bitrate: this._localStats.bitrate,
439
             packetLoss: this._localStats.packetLoss,
453
             packetLoss: this._localStats.packetLoss,
440
             connectionQuality: this._localStats.connectionQuality,
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
         try {
459
         try {
527
             bitrate: data.bitrate,
542
             bitrate: data.bitrate,
528
             packetLoss: data.packetLoss,
543
             packetLoss: data.packetLoss,
529
             connectionQuality: data.connectionQuality,
544
             connectionQuality: data.connectionQuality,
530
-            jvbRTT: data.jvbRTT
545
+            jvbRTT: data.jvbRTT,
546
+            serverRegion: data.serverRegion
531
         };
547
         };
532
 
548
 
533
         this.eventEmitter.emit(
549
         this.eventEmitter.emit(

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

11
 import XMPPEvents from '../../service/xmpp/XMPPEvents';
11
 import XMPPEvents from '../../service/xmpp/XMPPEvents';
12
 
12
 
13
 import Moderator from './moderator';
13
 import Moderator from './moderator';
14
-import Statistics from '../statistics/statistics';
15
 
14
 
16
 const logger = getLogger(__filename);
15
 const logger = getLogger(__filename);
17
 
16
 
625
                 break;
624
                 break;
626
             case 'conference-properties':
625
             case 'conference-properties':
627
                 if (member.isFocus) {
626
                 if (member.isFocus) {
627
+                    const properties = {};
628
+
628
                     for (let j = 0; j < node.children.length; j++) {
629
                     for (let j = 0; j < node.children.length; j++) {
629
                         const { attributes } = node.children[j];
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
                 break;
640
                 break;
656
             case 'transcription-status': {
641
             case 'transcription-status': {

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

5538
       "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
5538
       "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
5539
       "dev": true
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
     "log-symbols": {
5546
     "log-symbols": {
5542
       "version": "2.2.0",
5547
       "version": "2.2.0",
5543
       "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
5548
       "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",

+ 1
- 0
package.json 查看文件

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

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

25
     // person in the conference room.
25
     // person in the conference room.
26
     CALL_ENDED: 'xmpp.callended.jingle',
26
     CALL_ENDED: 'xmpp.callended.jingle',
27
     CHAT_ERROR_RECEIVED: 'xmpp.chat_error_received',
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
     CONFERENCE_SETUP_FAILED: 'xmpp.conference_setup_failed',
32
     CONFERENCE_SETUP_FAILED: 'xmpp.conference_setup_failed',
29
 
33
 
30
     /**
34
     /**

Loading…
取消
儲存