Home | History | Annotate | Download | only in loopback_test
      1 /**
      2  * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
      3  *
      4  * Use of this source code is governed by a BSD-style license
      5  * that can be found in the LICENSE file in the root of the source
      6  * tree. An additional intellectual property rights grant can be found
      7  * in the file PATENTS.  All contributing project authors may
      8  * be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 // StatTracker is a helper class to keep track of stats on a RTCPeerConnection
     12 // object. It uses google visualization datatables to keep the recorded samples
     13 // and simplify plugging them into graphs later.
     14 //
     15 // Usage example:
     16 //   var tracker = new StatTracker(pc, pollInterval);
     17 //   tracker.recordStat("EstimatedSendBitrate",
     18 //                      "bweforvideo", "googAvailableSendBandwidth");
     19 //   ...
     20 //   tracker.stop();
     21 //   tracker.dataTable(); // returns the recorded values. In this case
     22 //   a table with 2 columns { Time, EstimatedSendBitrate } and a row for each
     23 //   sample taken until stop() was called.
     24 //
     25 function StatTracker(pc, pollInterval) {
     26   pollInterval = pollInterval || 250;
     27 
     28   var dataTable = new google.visualization.DataTable();
     29   var timeColumnIndex = dataTable.addColumn('datetime', 'Time');
     30   var recording = true;
     31 
     32   // Set of sampling functions. Functions registered here are called
     33   // once per getStats with the given report and a rowIndex for the
     34   // sample period so they can extract and record the tracked variables.
     35   var samplingFunctions = {};
     36 
     37   // Accessor to the current recorded stats.
     38   this.dataTable = function() { return dataTable; }
     39 
     40   // recordStat(varName, recordName, statName) adds a samplingFunction that
     41   // records namedItem(recordName).stat(statName) from RTCStatsReport for each
     42   // sample into a column named varName in the dataTable.
     43   this.recordStat = function (varName, recordName, statName) {
     44     var columnIndex = dataTable.addColumn('number', varName);
     45     samplingFunctions[varName] = function (report, rowIndex) {
     46       var sample;
     47       var record = report.namedItem(recordName);
     48       if (record) sample = record.stat(statName);
     49       dataTable.setCell(rowIndex, columnIndex, sample);
     50     }
     51   }
     52 
     53   // Stops the polling of stats from the peer connection.
     54   this.stop = function() {
     55     recording = false;
     56   }
     57 
     58   // RTCPeerConnection.getStats is asynchronous. In order to avoid having
     59   // too many pending getStats requests going, this code only queues the
     60   // next getStats with setTimeout after the previous one returns, instead
     61   // of using setInterval.
     62   function poll() {
     63     pc.getStats(function (report) {
     64       if (!recording) return;
     65       setTimeout(poll, pollInterval);
     66       var result = report.result();
     67       if (result.length < 1) return;
     68 
     69       var rowIndex = dataTable.addRow();
     70       dataTable.setCell(rowIndex, timeColumnIndex, result[0].timestamp);
     71       for (var v in samplingFunctions)
     72         samplingFunctions[v](report, rowIndex);
     73     });
     74   }
     75   setTimeout(poll, pollInterval);
     76 }
     77 
     78 /**
     79  * Utility method to perform a full join between data tables from StatTracker.
     80  */
     81 function mergeDataTable(dataTable1, dataTable2) {
     82   function allColumns(cols) {
     83     var a = [];
     84     for (var i = 1; i < cols; ++i) a.push(i);
     85     return a;
     86   }
     87   return google.visualization.data.join(
     88       dataTable1,
     89       dataTable2,
     90       'full',
     91       [[0, 0]],
     92       allColumns(dataTable1.getNumberOfColumns()),
     93       allColumns(dataTable2.getNumberOfColumns()));
     94 }
     95