blob: 49f46c39f68b30d955078c101c49ef4479533014 [file] [log] [blame]
/**
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// StatTracker is a helper class to keep track of stats on a RTCPeerConnection
// object. It uses google visualization datatables to keep the recorded samples
// and simplify plugging them into graphs later.
//
// Usage example:
// var tracker = new StatTracker(pc, pollInterval);
// tracker.recordStat("EstimatedSendBitrate",
// "bweforvideo", "googAvailableSendBandwidth");
// ...
// tracker.stop();
// tracker.dataTable(); // returns the recorded values. In this case
// a table with 2 columns { Time, EstimatedSendBitrate } and a row for each
// sample taken until stop() was called.
//
function StatTracker(pc, pollInterval) {
pollInterval = pollInterval || 250;
var dataTable = new google.visualization.DataTable();
var timeColumnIndex = dataTable.addColumn('datetime', 'Time');
var recording = true;
// Set of sampling functions. Functions registered here are called
// once per getStats with the given report and a rowIndex for the
// sample period so they can extract and record the tracked variables.
var samplingFunctions = {};
// Accessor to the current recorded stats.
this.dataTable = function() { return dataTable; }
// recordStat(varName, recordName, statName) adds a samplingFunction that
// records namedItem(recordName).stat(statName) from RTCStatsReport for each
// sample into a column named varName in the dataTable.
this.recordStat = function (varName, recordName, statName) {
var columnIndex = dataTable.addColumn('number', varName);
samplingFunctions[varName] = function (report, rowIndex) {
var sample;
var record = report.namedItem(recordName);
if (record) sample = record.stat(statName);
dataTable.setCell(rowIndex, columnIndex, sample);
}
}
// Stops the polling of stats from the peer connection.
this.stop = function() {
recording = false;
}
// RTCPeerConnection.getStats is asynchronous. In order to avoid having
// too many pending getStats requests going, this code only queues the
// next getStats with setTimeout after the previous one returns, instead
// of using setInterval.
function poll() {
pc.getStats(function (report) {
if (!recording) return;
setTimeout(poll, pollInterval);
var result = report.result();
if (result.length < 1) return;
var rowIndex = dataTable.addRow();
dataTable.setCell(rowIndex, timeColumnIndex, result[0].timestamp);
for (var v in samplingFunctions)
samplingFunctions[v](report, rowIndex);
});
}
setTimeout(poll, pollInterval);
}
/**
* Utility method to perform a full join between data tables from StatTracker.
*/
function mergeDataTable(dataTable1, dataTable2) {
function allColumns(cols) {
var a = [];
for (var i = 1; i < cols; ++i) a.push(i);
return a;
}
return google.visualization.data.join(
dataTable1,
dataTable2,
'full',
[[0, 0]],
allColumns(dataTable1.getNumberOfColumns()),
allColumns(dataTable2.getNumberOfColumns()));
}