Bladeren bron

use statistics module to process peer connection statistics

tags/v0.0.2
isymchych 9 jaren geleden
bovenliggende
commit
8c014e8f12
6 gewijzigde bestanden met toevoegingen van 231 en 184 verwijderingen
  1. 43
    2
      JitsiConference.js
  2. 2
    2
      JitsiConferenceEvents.js
  3. 1
    0
      doc/API.md
  4. 126
    150
      modules/statistics/RTPStatsCollector.js
  5. 59
    26
      modules/statistics/statistics.js
  6. 0
    4
      service/statistics/Events.js

+ 43
- 2
JitsiConference.js Bestand weergeven

39
         this.settings);
39
         this.settings);
40
     this.room.updateDeviceAvailability(RTC.getDeviceAvailability());
40
     this.room.updateDeviceAvailability(RTC.getDeviceAvailability());
41
     this.rtc = new RTC(this.room, options);
41
     this.rtc = new RTC(this.room, options);
42
-    this.statistics = new Statistics({
42
+    this.statistics = new Statistics(this.xmpp, {
43
         callStatsID: this.options.config.callStatsID,
43
         callStatsID: this.options.config.callStatsID,
44
         callStatsSecret: this.options.config.callStatsSecret,
44
         callStatsSecret: this.options.config.callStatsSecret,
45
-        disableThirdPartyRequests: this.options.config.disableThirdPartyRequests
45
+        disableThirdPartyRequests: this.options.config.disableThirdPartyRequests,
46
     });
46
     });
47
     setupListeners(this);
47
     setupListeners(this);
48
     JitsiMeetJS._gumFailedHandler.push(function(error) {
48
     JitsiMeetJS._gumFailedHandler.push(function(error) {
1046
 
1046
 
1047
             conference.rtc.setAudioLevel(jid, level);
1047
             conference.rtc.setAudioLevel(jid, level);
1048
         });
1048
         });
1049
+        conference.statistics.addConnectionStatsListener(function (stats) {
1050
+            var ssrc2resolution = stats.resolution;
1051
+
1052
+            var id2resolution = {};
1053
+
1054
+            // preprocess resolutions: group by user id, skip incorrect resolutions etc.
1055
+            Object.keys(ssrc2resolution).forEach(function (ssrc) {
1056
+                var resolution = ssrc2resolution[ssrc];
1057
+
1058
+                if (!resolution.width || !resolution.height ||
1059
+                    resolution.width == -1 || resolution.height == -1) { // it also may be "-1"
1060
+                    return;
1061
+                }
1062
+
1063
+                var jid = conference.room.getJidBySSRC(ssrc);
1064
+                if (!jid) {
1065
+                    return;
1066
+                }
1067
+
1068
+                var id;
1069
+                if (jid === conference.room.session.me) {
1070
+                    id = conference.myUserId();
1071
+                } else {
1072
+                    id = Strophe.getResourceFromJid(jid);
1073
+                }
1074
+
1075
+                if (!id) {
1076
+                    return;
1077
+                }
1078
+
1079
+                // ssrc to resolution map for user id
1080
+                var idResolutions = id2resolution[id] || {};
1081
+                idResolutions[ssrc] = resolution;
1082
+
1083
+                id2resolution[id] = idResolutions;
1084
+            });
1085
+
1086
+            stats.resolution = id2resolution;
1087
+
1088
+            conference.eventEmitter.emit(JitsiConferenceEvents.CONNECTION_STATS, stats);
1089
+        });
1049
         conference.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE,
1090
         conference.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE,
1050
             function () {
1091
             function () {
1051
                 conference.statistics.dispose();
1092
                 conference.statistics.dispose();

+ 2
- 2
JitsiConferenceEvents.js Bestand weergeven

48
      */
48
      */
49
     AVATAR_CHANGED: "conference.avatarChanged",
49
     AVATAR_CHANGED: "conference.avatarChanged",
50
     /**
50
     /**
51
-     * New connection statistics are received.
51
+     * New local connection statistics are received.
52
      */
52
      */
53
-    CONNECTION_STATS_RECEIVED: "conference.connectionStatsReceived",
53
+    CONNECTION_STATS: "conference.connectionStats",
54
     /**
54
     /**
55
      * The Last N set is changed.
55
      * The Last N set is changed.
56
      */
56
      */

+ 1
- 0
doc/API.md Bestand weergeven

98
         - START_MUTED_POLICY_CHANGED - notifies that all new participants will join with muted audio/video stream (parameters - JS object with 2 properties - audio(boolean), video(boolean))
98
         - START_MUTED_POLICY_CHANGED - notifies that all new participants will join with muted audio/video stream (parameters - JS object with 2 properties - audio(boolean), video(boolean))
99
         - STARTED_MUTED - notifies that the local user has started muted
99
         - STARTED_MUTED - notifies that the local user has started muted
100
         - AVAILABLE_DEVICES_CHANGED - notifies that available participant devices changed (camera or microphone was added or removed) (parameters - id(string), devices(JS object with 2 properties - audio(boolean), video(boolean)))
100
         - AVAILABLE_DEVICES_CHANGED - notifies that available participant devices changed (camera or microphone was added or removed) (parameters - id(string), devices(JS object with 2 properties - audio(boolean), video(boolean)))
101
+        - CONNECTION_STATS - New local connection statistics are received. (parameters - stats(object))
101
 
102
 
102
     2. connection
103
     2. connection
103
         - CONNECTION_FAILED - indicates that the server connection failed.
104
         - CONNECTION_FAILED - indicates that the server connection failed.

+ 126
- 150
modules/statistics/RTPStatsCollector.js Bestand weergeven

1
-/* global require, ssrc2jid */
2
-/* jshint -W117 */
1
+/* global require */
2
+/* jshint -W101 */
3
 
3
 
4
 var logger = require("jitsi-meet-logger").getLogger(__filename);
4
 var logger = require("jitsi-meet-logger").getLogger(__filename);
5
 var RTCBrowserType = require("../RTC/RTCBrowserType");
5
 var RTCBrowserType = require("../RTC/RTCBrowserType");
7
 
7
 
8
 /* Whether we support the browser we are running into for logging statistics */
8
 /* Whether we support the browser we are running into for logging statistics */
9
 var browserSupported = RTCBrowserType.isChrome() ||
9
 var browserSupported = RTCBrowserType.isChrome() ||
10
-    RTCBrowserType.isOpera();
10
+        RTCBrowserType.isOpera() || RTCBrowserType.isFirefox();
11
 
11
 
12
 var keyMap = {};
12
 var keyMap = {};
13
 keyMap[RTCBrowserType.RTC_BROWSER_FIREFOX] = {
13
 keyMap[RTCBrowserType.RTC_BROWSER_FIREFOX] = {
110
 {
110
 {
111
     this.ssrc2Loss = {};
111
     this.ssrc2Loss = {};
112
     this.ssrc2AudioLevel = {};
112
     this.ssrc2AudioLevel = {};
113
-    this.ssrc2bitrate = {};
113
+    this.ssrc2bitrate = {
114
+        download: 0,
115
+        upload: 0
116
+    };
114
     this.ssrc2resolution = {};
117
     this.ssrc2resolution = {};
115
 }
118
 }
116
 
119
 
117
 /**
120
 /**
118
- * Sets packets loss rate for given <tt>ssrc</tt> that blong to the peer
121
+ * Sets packets loss rate for given <tt>ssrc</tt> that belong to the peer
119
  * represented by this instance.
122
  * represented by this instance.
120
  * @param lossRate new packet loss rate value to be set.
123
  * @param lossRate new packet loss rate value to be set.
121
  */
124
  */
122
-PeerStats.prototype.setSsrcLoss = function (lossRate)
123
-{
124
-    this.ssrc2Loss = lossRate;
125
+PeerStats.prototype.setSsrcLoss = function (lossRate) {
126
+    this.ssrc2Loss = lossRate || {};
125
 };
127
 };
126
 
128
 
127
 /**
129
 /**
129
  * represented by this instance.
131
  * represented by this instance.
130
  * @param resolution new resolution value to be set.
132
  * @param resolution new resolution value to be set.
131
  */
133
  */
132
-PeerStats.prototype.setSsrcResolution = function (resolution)
133
-{
134
-    if(resolution === null && this.ssrc2resolution[ssrc])
135
-    {
136
-        delete this.ssrc2resolution[ssrc];
137
-    }
138
-    else if(resolution !== null)
139
-        this.ssrc2resolution[ssrc] = resolution;
134
+PeerStats.prototype.setSsrcResolution = function (resolution) {
135
+    this.ssrc2resolution = resolution || {};
140
 };
136
 };
141
 
137
 
142
 /**
138
 /**
143
- * Sets the bit rate for given <tt>ssrc</tt> that blong to the peer
139
+ * Sets the bit rate for given <tt>ssrc</tt> that belong to the peer
144
  * represented by this instance.
140
  * represented by this instance.
145
- * @param ssrc audio or video RTP stream SSRC.
146
  * @param bitrate new bitrate value to be set.
141
  * @param bitrate new bitrate value to be set.
147
  */
142
  */
148
-PeerStats.prototype.setSsrcBitrate = function (ssrc, bitrate)
149
-{
150
-    if(this.ssrc2bitrate[ssrc])
151
-    {
152
-        this.ssrc2bitrate[ssrc].download += bitrate.download;
153
-        this.ssrc2bitrate[ssrc].upload += bitrate.upload;
154
-    }
155
-    else {
156
-        this.ssrc2bitrate[ssrc] = bitrate;
157
-    }
143
+PeerStats.prototype.setSsrcBitrate = function (bitrate) {
144
+    this.ssrc2bitrate.download += bitrate.download;
145
+    this.ssrc2bitrate.upload += bitrate.upload;
146
+};
147
+
148
+/**
149
+ * Resets the bit rate for given <tt>ssrc</tt> that belong to the peer
150
+ * represented by this instance.
151
+ */
152
+PeerStats.prototype.resetSsrcBitrate = function () {
153
+    this.ssrc2bitrate.download = 0;
154
+    this.ssrc2bitrate.upload = 0;
158
 };
155
 };
159
 
156
 
160
 /**
157
 /**
161
  * Sets new audio level(input or output) for given <tt>ssrc</tt> that identifies
158
  * Sets new audio level(input or output) for given <tt>ssrc</tt> that identifies
162
  * the stream which belongs to the peer represented by this instance.
159
  * the stream which belongs to the peer represented by this instance.
163
- * @param ssrc RTP stream SSRC for which current audio level value will be
164
- *        updated.
165
  * @param audioLevel the new audio level value to be set. Value is truncated to
160
  * @param audioLevel the new audio level value to be set. Value is truncated to
166
  *        fit the range from 0 to 1.
161
  *        fit the range from 0 to 1.
167
  */
162
  */
168
-PeerStats.prototype.setSsrcAudioLevel = function (ssrc, audioLevel)
169
-{
163
+PeerStats.prototype.setSsrcAudioLevel = function (audioLevel) {
170
     // Range limit 0 - 1
164
     // Range limit 0 - 1
171
-    this.ssrc2AudioLevel[ssrc] = formatAudioLevel(audioLevel);
165
+    this.ssrc2AudioLevel = formatAudioLevel(audioLevel);
172
 };
166
 };
173
 
167
 
174
 function ConferenceStats() {
168
 function ConferenceStats() {
231
      */
225
      */
232
     this.GATHER_INTERVAL = 15000;
226
     this.GATHER_INTERVAL = 15000;
233
 
227
 
234
-    /**
235
-     * Log stats via the focus once every this many milliseconds.
236
-     */
237
-    this.LOG_INTERVAL = 60000;
238
-
239
     /**
228
     /**
240
      * Gather stats and store them in this.statsToBeLogged.
229
      * Gather stats and store them in this.statsToBeLogged.
241
      */
230
      */
242
     this.gatherStatsIntervalId = null;
231
     this.gatherStatsIntervalId = null;
243
 
232
 
244
-    /**
245
-     * Send the stats already saved in this.statsToBeLogged to be logged via
246
-     * the focus.
247
-     */
248
-    this.logStatsIntervalId = null;
249
-
250
     /**
233
     /**
251
      * Stores the statistics which will be send to the focus to be logged.
234
      * Stores the statistics which will be send to the focus to be logged.
252
      */
235
      */
282
         this.statsIntervalId = null;
265
         this.statsIntervalId = null;
283
     }
266
     }
284
 
267
 
285
-    if(this.logStatsIntervalId)
286
-    {
287
-        clearInterval(this.logStatsIntervalId);
288
-        this.logStatsIntervalId = null;
289
-    }
290
-
291
     if(this.gatherStatsIntervalId)
268
     if(this.gatherStatsIntervalId)
292
     {
269
     {
293
         clearInterval(this.gatherStatsIntervalId);
270
         clearInterval(this.gatherStatsIntervalId);
336
         self.audioLevelsIntervalMilis
313
         self.audioLevelsIntervalMilis
337
     );
314
     );
338
 
315
 
339
-//    if (!this.config.disableStats && browserSupported) {
340
-//        this.statsIntervalId = setInterval(
341
-//            function () {
342
-//                // Interval updates
343
-//                self.peerconnection.getStats(
344
-//                    function (report) {
345
-//                        var results = null;
346
-//                        if (!report || !report.result ||
347
-//                            typeof report.result != 'function') {
348
-//                            //firefox
349
-//                            results = report;
350
-//                        }
351
-//                        else {
352
-//                            //chrome
353
-//                            results = report.result();
354
-//                        }
355
-//                        //logger.error("Got interval report", results);
356
-//                        self.currentStatsReport = results;
357
-//                        try {
358
-//                            self.processStatsReport();
359
-//                        }
360
-//                        catch (e) {
361
-//                            logger.error("Unsupported key:" + e, e);
362
-//                        }
363
-//
364
-//                        self.baselineStatsReport = self.currentStatsReport;
365
-//                    },
366
-//                    self.errorCallback
367
-//                );
368
-//            },
369
-//            self.statsIntervalMilis
370
-//        );
371
-//    }
372
-//
373
-//    if (this.config.logStats && browserSupported) {
374
-//        this.gatherStatsIntervalId = setInterval(
375
-//            function () {
376
-//                self.peerconnection.getStats(
377
-//                    function (report) {
378
-//                        self.addStatsToBeLogged(report.result());
379
-//                    },
380
-//                    function () {
381
-//                    }
382
-//                );
383
-//            },
384
-//            this.GATHER_INTERVAL
385
-//        );
386
-//
387
-//        this.logStatsIntervalId = setInterval(
388
-//            function() { self.logStats(); },
389
-//            this.LOG_INTERVAL);
390
-//    }
316
+    if (!this.config.disableStats && browserSupported) {
317
+        this.statsIntervalId = setInterval(
318
+            function () {
319
+                // Interval updates
320
+                self.peerconnection.getStats(
321
+                    function (report) {
322
+                        var results = null;
323
+                        if (!report || !report.result ||
324
+                            typeof report.result != 'function') {
325
+                            //firefox
326
+                            results = report;
327
+                        }
328
+                        else {
329
+                            //chrome
330
+                            results = report.result();
331
+                        }
332
+                        //logger.error("Got interval report", results);
333
+                        self.currentStatsReport = results;
334
+                        try {
335
+                            self.processStatsReport();
336
+                        }
337
+                        catch (e) {
338
+                            logger.error("Unsupported key:" + e, e);
339
+                        }
340
+
341
+                        self.baselineStatsReport = self.currentStatsReport;
342
+                    },
343
+                    self.errorCallback
344
+                );
345
+            },
346
+            self.statsIntervalMilis
347
+        );
348
+    }
349
+
350
+    // logging statistics does not support firefox
351
+    if (this.config.logStats && (browserSupported && !RTCBrowserType.isFirefox())) {
352
+        this.gatherStatsIntervalId = setInterval(
353
+            function () {
354
+                self.peerconnection.getStats(
355
+                    function (report) {
356
+                        self.addStatsToBeLogged(report.result());
357
+                    },
358
+                    function () {
359
+                    }
360
+                );
361
+            },
362
+            this.GATHER_INTERVAL
363
+        );
364
+    }
391
 };
365
 };
392
 
366
 
393
 /**
367
 /**
399
     var self = this;
373
     var self = this;
400
     var num_records = this.statsToBeLogged.timestamps.length;
374
     var num_records = this.statsToBeLogged.timestamps.length;
401
     this.statsToBeLogged.timestamps.push(new Date().getTime());
375
     this.statsToBeLogged.timestamps.push(new Date().getTime());
402
-    reports.map(function (report) {
376
+    reports.forEach(function (report) {
403
         if (!acceptReport(report.id, report.type))
377
         if (!acceptReport(report.id, report.type))
404
             return;
378
             return;
405
         var stat = self.statsToBeLogged.stats[report.id];
379
         var stat = self.statsToBeLogged.stats[report.id];
407
             stat = self.statsToBeLogged.stats[report.id] = {};
381
             stat = self.statsToBeLogged.stats[report.id] = {};
408
         }
382
         }
409
         stat.type = report.type;
383
         stat.type = report.type;
410
-        report.names().map(function (name) {
384
+        report.names().forEach(function (name) {
411
             if (!acceptStat(report.id, report.type, name))
385
             if (!acceptStat(report.id, report.type, name))
412
                 return;
386
                 return;
413
             var values = stat[name];
387
             var values = stat[name];
422
     });
396
     });
423
 };
397
 };
424
 
398
 
399
+StatsCollector.prototype.getCollectedStats = function () {
400
+    return this.statsToBeLogged;
401
+};
425
 
402
 
426
-//FIXME:
427
-//StatsCollector.prototype.logStats = function () {
428
-//
429
-//    if(!APP.xmpp.sendLogs(this.statsToBeLogged))
430
-//        return;
431
-//    // Reset the stats
432
-//    this.statsToBeLogged.stats = {};
433
-//    this.statsToBeLogged.timestamps = [];
434
-//};
403
+StatsCollector.prototype.clearCollectedStats = function () {
404
+   // Reset the stats
405
+   this.statsToBeLogged.stats = {};
406
+   this.statsToBeLogged.timestamps = [];
407
+};
435
 
408
 
436
 
409
 
437
 /**
410
 /**
551
             lossRate = 0;
524
             lossRate = 0;
552
         var packetsTotal = (packetRate + lossRate);
525
         var packetsTotal = (packetRate + lossRate);
553
 
526
 
554
-        ssrcStats.setSsrcLoss(ssrc,
555
-            {"packetsTotal": packetsTotal,
556
-                "packetsLost": lossRate,
557
-                "isDownloadStream": isDownloadStream});
527
+        ssrcStats.setSsrcLoss({
528
+            packetsTotal: packetsTotal,
529
+            packetsLost: lossRate,
530
+            isDownloadStream: isDownloadStream
531
+        });
558
 
532
 
559
 
533
 
560
         var bytesReceived = 0, bytesSent = 0;
534
         var bytesReceived = 0, bytesSent = 0;
581
             bytesSent = Math.round(((bytesSent * 8) / time) / 1000);
555
             bytesSent = Math.round(((bytesSent * 8) / time) / 1000);
582
         }
556
         }
583
 
557
 
584
-        ssrcStats.setSsrcBitrate(ssrc, {
558
+        ssrcStats.setSsrcBitrate({
585
             "download": bytesReceived,
559
             "download": bytesReceived,
586
-            "upload": bytesSent});
560
+            "upload": bytesSent
561
+        });
587
 
562
 
588
         var resolution = {height: null, width: null};
563
         var resolution = {height: null, width: null};
589
         try {
564
         try {
602
         catch(e){/*not supported*/}
577
         catch(e){/*not supported*/}
603
 
578
 
604
         if (resolution.height && resolution.width) {
579
         if (resolution.height && resolution.width) {
605
-            ssrcStats.setSsrcResolution(ssrc, resolution);
580
+            ssrcStats.setSsrcResolution(resolution);
606
         } else {
581
         } else {
607
-            ssrcStats.setSsrcResolution(ssrc, null);
582
+            ssrcStats.setSsrcResolution(null);
608
         }
583
         }
609
     }
584
     }
610
 
585
 
611
-    var self = this;
612
-    // Jid stats
613
-    var totalPackets = {download: 0, upload: 0};
614
-    var lostPackets = {download: 0, upload: 0};
586
+    // process stats
587
+    var totalPackets = {
588
+        download: 0,
589
+        upload: 0
590
+    };
591
+    var lostPackets = {
592
+        download: 0,
593
+        upload: 0
594
+    };
615
     var bitrateDownload = 0;
595
     var bitrateDownload = 0;
616
     var bitrateUpload = 0;
596
     var bitrateUpload = 0;
617
     var resolutions = {};
597
     var resolutions = {};
618
     Object.keys(this.ssrc2stats).forEach(
598
     Object.keys(this.ssrc2stats).forEach(
619
-        function (jid) {
620
-            Object.keys(self.ssrc2stats[jid].ssrc2Loss).forEach(
621
-                function (ssrc) {
622
-                    var type = "upload";
623
-                    if(self.ssrc2stats[jid].ssrc2Loss[ssrc].isDownloadStream)
624
-                        type = "download";
625
-                    totalPackets[type] +=
626
-                        self.ssrc2stats[jid].ssrc2Loss[ssrc].packetsTotal;
627
-                    lostPackets[type] +=
628
-                        self.ssrc2stats[jid].ssrc2Loss[ssrc].packetsLost;
629
-                }
630
-            );
631
-            Object.keys(self.ssrc2stats[jid].ssrc2bitrate).forEach(
632
-                function (ssrc) {
633
-                    bitrateDownload +=
634
-                        self.ssrc2stats[jid].ssrc2bitrate[ssrc].download;
635
-                    bitrateUpload +=
636
-                        self.ssrc2stats[jid].ssrc2bitrate[ssrc].upload;
637
-
638
-                    delete self.ssrc2stats[jid].ssrc2bitrate[ssrc];
639
-                }
640
-            );
641
-            resolutions[jid] = self.ssrc2stats[jid].ssrc2resolution;
642
-        }
599
+        function (ssrc) {
600
+            var ssrcStats = this.ssrc2stats[ssrc];
601
+
602
+            // process package loss stats
603
+            var ssrc2Loss = ssrcStats.ssrc2Loss;
604
+            var type = ssrc2Loss.isDownloadStream ? "download" : "upload";
605
+            totalPackets[type] += ssrc2Loss.packetsTotal;
606
+            lostPackets[type] += ssrc2Loss.packetLost;
607
+
608
+            // process bitrate stats
609
+            var ssrc2bitrate = ssrcStats.ssrc2bitrate;
610
+            bitrateDownload += ssrc2bitrate.download;
611
+            bitrateUpload += ssrc2bitrate.upload;
612
+
613
+            ssrcStats.resetSsrcBitrate();
614
+
615
+            // collect resolutions
616
+            resolutions[ssrc] = ssrcStats.ssrc2resolution;
617
+        },
618
+        this
643
     );
619
     );
644
 
620
 
645
     this.conferenceStats.bitrate = {"upload": bitrateUpload, "download": bitrateDownload};
621
     this.conferenceStats.bitrate = {"upload": bitrateUpload, "download": bitrateDownload};
718
             // TODO: can't find specs about what this value really is,
694
             // TODO: can't find specs about what this value really is,
719
             // but it seems to vary between 0 and around 32k.
695
             // but it seems to vary between 0 and around 32k.
720
             audioLevel = audioLevel / 32767;
696
             audioLevel = audioLevel / 32767;
721
-            ssrcStats.setSsrcAudioLevel(ssrc, audioLevel);
697
+            ssrcStats.setSsrcAudioLevel(audioLevel);
722
             this.eventEmitter.emit(
698
             this.eventEmitter.emit(
723
                 StatisticsEvents.AUDIO_LEVEL, ssrc, audioLevel);
699
                 StatisticsEvents.AUDIO_LEVEL, ssrc, audioLevel);
724
         }
700
         }

+ 59
- 26
modules/statistics/statistics.js Bestand weergeven

1
-/* global require, APP */
1
+/* global require */
2
 var LocalStats = require("./LocalStatsCollector.js");
2
 var LocalStats = require("./LocalStatsCollector.js");
3
 var RTPStats = require("./RTPStatsCollector.js");
3
 var RTPStats = require("./RTPStatsCollector.js");
4
 var EventEmitter = require("events");
4
 var EventEmitter = require("events");
22
     // have loaded by the time we needed it (i.e. CallStats.init is invoked).
22
     // have loaded by the time we needed it (i.e. CallStats.init is invoked).
23
 }
23
 }
24
 
24
 
25
+
26
+/**
27
+ * Log stats via the focus once every this many milliseconds.
28
+ */
29
+var LOG_INTERVAL = 60000;
30
+
25
 var eventEmitter = new EventEmitter();
31
 var eventEmitter = new EventEmitter();
26
 
32
 
27
-function Statistics(options) {
33
+function Statistics(xmpp, options) {
28
     this.rtpStats = null;
34
     this.rtpStats = null;
29
     this.eventEmitter = new EventEmitter();
35
     this.eventEmitter = new EventEmitter();
36
+    this.xmpp = xmpp;
30
     this.options = options || {};
37
     this.options = options || {};
31
     this.callStatsIntegrationEnabled
38
     this.callStatsIntegrationEnabled
32
         = this.options.callStatsID && this.options.callStatsSecret
39
         = this.options.callStatsID && this.options.callStatsSecret
37
     if(this.callStatsIntegrationEnabled)
44
     if(this.callStatsIntegrationEnabled)
38
         loadCallStatsAPI();
45
         loadCallStatsAPI();
39
     this.callStats = null;
46
     this.callStats = null;
47
+
48
+    /**
49
+     * Send the stats already saved in rtpStats to be logged via
50
+     * the focus.
51
+     */
52
+    this.logStatsIntervalId = null;
40
 }
53
 }
41
 Statistics.audioLevelsEnabled = false;
54
 Statistics.audioLevelsEnabled = false;
42
 
55
 
44
     if(!Statistics.audioLevelsEnabled)
57
     if(!Statistics.audioLevelsEnabled)
45
         return;
58
         return;
46
 
59
 
47
-    if (this.rtpStats) {
48
-        this.rtpStats.stop();
49
-    }
60
+    this.stopRemoteStats();
50
 
61
 
51
     this.rtpStats = new RTPStats(peerconnection, 200, 2000, this.eventEmitter);
62
     this.rtpStats = new RTPStats(peerconnection, 200, 2000, this.eventEmitter);
52
     this.rtpStats.start();
63
     this.rtpStats.start();
53
-}
64
+
65
+    this.logStatsIntervalId = setInterval(function () {
66
+        var stats = this.rtpStats.getCollectedStats();
67
+        if (this.xmpp.sendLogs(stats)) {
68
+            this.rtpStats.clearCollectedStats();
69
+        }
70
+    }.bind(this), LOG_INTERVAL);
71
+};
54
 
72
 
55
 Statistics.localStats = [];
73
 Statistics.localStats = [];
56
 
74
 
60
     var localStats = new LocalStats(stream, 200, callback);
78
     var localStats = new LocalStats(stream, 200, callback);
61
     this.localStats.push(localStats);
79
     this.localStats.push(localStats);
62
     localStats.start();
80
     localStats.start();
63
-}
81
+};
64
 
82
 
65
 Statistics.prototype.addAudioLevelListener = function(listener)
83
 Statistics.prototype.addAudioLevelListener = function(listener)
66
 {
84
 {
67
     if(!Statistics.audioLevelsEnabled)
85
     if(!Statistics.audioLevelsEnabled)
68
         return;
86
         return;
69
     this.eventEmitter.on(StatisticsEvents.AUDIO_LEVEL, listener);
87
     this.eventEmitter.on(StatisticsEvents.AUDIO_LEVEL, listener);
70
-}
88
+};
71
 
89
 
72
 Statistics.prototype.removeAudioLevelListener = function(listener)
90
 Statistics.prototype.removeAudioLevelListener = function(listener)
73
 {
91
 {
74
     if(!Statistics.audioLevelsEnabled)
92
     if(!Statistics.audioLevelsEnabled)
75
         return;
93
         return;
76
     this.eventEmitter.removeListener(StatisticsEvents.AUDIO_LEVEL, listener);
94
     this.eventEmitter.removeListener(StatisticsEvents.AUDIO_LEVEL, listener);
77
-}
95
+};
96
+
97
+Statistics.prototype.addConnectionStatsListener = function (listener) {
98
+    this.eventEmitter.on(StatisticsEvents.CONNECTION_STATS, listener);
99
+};
100
+
101
+Statistics.prototype.removeConnectionStatsListener = function (listener) {
102
+    this.eventEmitter.removeListener(StatisticsEvents.CONNECTION_STATS, listener);
103
+};
78
 
104
 
79
 Statistics.prototype.dispose = function () {
105
 Statistics.prototype.dispose = function () {
80
     if(Statistics.audioLevelsEnabled) {
106
     if(Statistics.audioLevelsEnabled) {
81
         Statistics.stopAllLocalStats();
107
         Statistics.stopAllLocalStats();
82
-        this.stopRemote();
108
+        this.stopRemoteStats();
83
         if(this.eventEmitter)
109
         if(this.eventEmitter)
84
             this.eventEmitter.removeAllListeners();
110
             this.eventEmitter.removeAllListeners();
85
 
111
 
92
         this.callstats.sendTerminateEvent();
118
         this.callstats.sendTerminateEvent();
93
         this.callstats = null;
119
         this.callstats = null;
94
     }
120
     }
95
-}
121
+};
96
 
122
 
97
 
123
 
98
 Statistics.stopAllLocalStats = function () {
124
 Statistics.stopAllLocalStats = function () {
102
     for(var i = 0; i < this.localStats.length; i++)
128
     for(var i = 0; i < this.localStats.length; i++)
103
         this.localStats[i].stop();
129
         this.localStats[i].stop();
104
     this.localStats = [];
130
     this.localStats = [];
105
-}
131
+};
106
 
132
 
107
 Statistics.stopLocalStats = function (stream) {
133
 Statistics.stopLocalStats = function (stream) {
108
     if(!Statistics.audioLevelsEnabled)
134
     if(!Statistics.audioLevelsEnabled)
114
             localStats.stop();
140
             localStats.stop();
115
             break;
141
             break;
116
         }
142
         }
117
-}
143
+};
144
+
145
+Statistics.prototype.stopRemoteStats = function () {
146
+    if (!Statistics.audioLevelsEnabled || !this.rtpStats) {
147
+        return;
148
+    }
149
+
150
+    this.rtpStats.stop();
151
+    this.rtpStats = null;
118
 
152
 
119
-Statistics.prototype.stopRemote = function () {
120
-    if (this.rtpStats && Statistics.audioLevelsEnabled) {
121
-        this.rtpStats.stop();
122
-        this.eventEmitter.emit(StatisticsEvents.STOP);
123
-        this.rtpStats = null;
153
+    if (this.logStatsIntervalId) {
154
+        clearInterval(this.logStatsIntervalId);
155
+        this.logStatsIntervalId = null;
124
     }
156
     }
125
 };
157
 };
126
 
158
 
137
 Statistics.prototype.getPeerSSRCAudioLevel = function (peerJid, ssrc) {
169
 Statistics.prototype.getPeerSSRCAudioLevel = function (peerJid, ssrc) {
138
     if(!Statistics.audioLevelsEnabled)
170
     if(!Statistics.audioLevelsEnabled)
139
         return;
171
         return;
172
+    // FIXME: not used, unknown property jid2stats
140
     var peerStats = this.rtpStats.jid2stats[peerJid];
173
     var peerStats = this.rtpStats.jid2stats[peerJid];
141
 
174
 
142
     return peerStats ? peerStats.ssrc2AudioLevel[ssrc] : null;
175
     return peerStats ? peerStats.ssrc2AudioLevel[ssrc] : null;
155
     if(this.callStatsIntegrationEnabled && !this.callstats) {
188
     if(this.callStatsIntegrationEnabled && !this.callstats) {
156
         this.callstats = new CallStats(session, settings, this.options);
189
         this.callstats = new CallStats(session, settings, this.options);
157
     }
190
     }
158
-}
191
+};
159
 
192
 
160
 /**
193
 /**
161
  * Returns true if the callstats integration is enabled, otherwise returns
194
  * Returns true if the callstats integration is enabled, otherwise returns
166
  */
199
  */
167
 Statistics.prototype.isCallstatsEnabled = function () {
200
 Statistics.prototype.isCallstatsEnabled = function () {
168
     return this.callStatsIntegrationEnabled;
201
     return this.callStatsIntegrationEnabled;
169
-}
202
+};
170
 
203
 
171
 /**
204
 /**
172
  * Notifies CallStats for connection setup errors
205
  * Notifies CallStats for connection setup errors
174
 Statistics.prototype.sendSetupFailedEvent = function () {
207
 Statistics.prototype.sendSetupFailedEvent = function () {
175
     if(this.callStatsIntegrationEnabled && this.callstats)
208
     if(this.callStatsIntegrationEnabled && this.callstats)
176
         this.callstats.sendSetupFailedEvent();
209
         this.callstats.sendSetupFailedEvent();
177
-}
210
+};
178
 
211
 
179
 /**
212
 /**
180
  * Notifies CallStats for mute events
213
  * Notifies CallStats for mute events
184
 Statistics.prototype.sendMuteEvent = function (muted, type) {
217
 Statistics.prototype.sendMuteEvent = function (muted, type) {
185
     if(this.callStatsIntegrationEnabled)
218
     if(this.callStatsIntegrationEnabled)
186
         CallStats.sendMuteEvent(muted, type, this.callstats);
219
         CallStats.sendMuteEvent(muted, type, this.callstats);
187
-}
220
+};
188
 
221
 
189
 /**
222
 /**
190
  * Notifies CallStats that getUserMedia failed.
223
  * Notifies CallStats that getUserMedia failed.
236
 Statistics.prototype.sendSetLocalDescFailed = function (e, pc) {
269
 Statistics.prototype.sendSetLocalDescFailed = function (e, pc) {
237
     if(this.callStatsIntegrationEnabled)
270
     if(this.callStatsIntegrationEnabled)
238
         CallStats.sendSetLocalDescFailed(e, pc, this.callstats);
271
         CallStats.sendSetLocalDescFailed(e, pc, this.callstats);
239
-}
272
+};
240
 
273
 
241
 /**
274
 /**
242
  * Notifies CallStats that peer connection failed to set remote description.
275
  * Notifies CallStats that peer connection failed to set remote description.
247
 Statistics.prototype.sendSetRemoteDescFailed = function (e, pc) {
280
 Statistics.prototype.sendSetRemoteDescFailed = function (e, pc) {
248
     if(this.callStatsIntegrationEnabled)
281
     if(this.callStatsIntegrationEnabled)
249
         CallStats.sendSetRemoteDescFailed(e, pc, this.callstats);
282
         CallStats.sendSetRemoteDescFailed(e, pc, this.callstats);
250
-}
283
+};
251
 
284
 
252
 /**
285
 /**
253
  * Notifies CallStats that peer connection failed to add ICE candidate.
286
  * Notifies CallStats that peer connection failed to add ICE candidate.
258
 Statistics.prototype.sendAddIceCandidateFailed = function (e, pc) {
291
 Statistics.prototype.sendAddIceCandidateFailed = function (e, pc) {
259
     if(this.callStatsIntegrationEnabled)
292
     if(this.callStatsIntegrationEnabled)
260
         CallStats.sendAddIceCandidateFailed(e, pc, this.callstats);
293
         CallStats.sendAddIceCandidateFailed(e, pc, this.callstats);
261
-}
294
+};
262
 
295
 
263
 /**
296
 /**
264
  * Sends the given feedback through CallStats.
297
  * Sends the given feedback through CallStats.
271
 function(overallFeedback, detailedFeedback){
304
 function(overallFeedback, detailedFeedback){
272
     if(this.callStatsIntegrationEnabled && this.callstats)
305
     if(this.callStatsIntegrationEnabled && this.callstats)
273
         this.callstats.sendFeedback(overallFeedback, detailedFeedback);
306
         this.callstats.sendFeedback(overallFeedback, detailedFeedback);
274
-}
307
+};
275
 
308
 
276
 Statistics.LOCAL_JID = require("../../service/statistics/constants").LOCAL_JID;
309
 Statistics.LOCAL_JID = require("../../service/statistics/constants").LOCAL_JID;
277
 
310
 

+ 0
- 4
service/statistics/Events.js Bestand weergeven

7
      * FIXME: needs documentation.
7
      * FIXME: needs documentation.
8
      */
8
      */
9
     AUDIO_LEVEL: "statistics.audioLevel",
9
     AUDIO_LEVEL: "statistics.audioLevel",
10
-    /**
11
-     * FIXME: needs documentation.
12
-     */
13
-    STOP: "statistics.stop"
14
 };
10
 };

Laden…
Annuleren
Opslaan