| /** | |
| * 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())); | |
| } |