Fix calling tools JS
This commit is contained in:
parent
5f0080a7d7
commit
29eb07c159
23 changed files with 27 additions and 23 deletions
219
js/calling-tools/stats_table.js
Normal file
219
js/calling-tools/stats_table.js
Normal file
|
@ -0,0 +1,219 @@
|
|||
// Derived from Chromium WebRTC Internals Dashboard - see Acknowledgements for full license details
|
||||
|
||||
import {$} from './util.js';
|
||||
|
||||
import {generateStatsLabel} from './stats_helper.js';
|
||||
|
||||
/**
|
||||
* Maintains the stats table.
|
||||
*/
|
||||
export class StatsTable {
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
* Adds |report| to the stats table of |peerConnectionElement|.
|
||||
*
|
||||
* @param {!Element} peerConnectionElement The root element.
|
||||
* @param {!Object} report The object containing stats, which is the object
|
||||
* containing timestamp and values, which is an array of strings, whose
|
||||
* even index entry is the name of the stat, and the odd index entry is
|
||||
* the value.
|
||||
*/
|
||||
addStatsReport(peerConnectionElement, report) {
|
||||
const statsTable = this.ensureStatsTable_(peerConnectionElement, report);
|
||||
|
||||
// Update the label since information may have changed.
|
||||
statsTable.parentElement.firstElementChild.innerText =
|
||||
generateStatsLabel(report);
|
||||
|
||||
if (report.stats) {
|
||||
this.addStatsToTable_(
|
||||
statsTable, report.stats.timestamp, report.stats.values);
|
||||
}
|
||||
}
|
||||
|
||||
clearStatsLists(peerConnectionElement) {
|
||||
const containerId = peerConnectionElement.id + '-table-container';
|
||||
// Disable getElementById restriction here, since |containerId| is not
|
||||
// always a valid selector.
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
const container = document.getElementById(containerId);
|
||||
if (container) {
|
||||
peerConnectionElement.removeChild(container);
|
||||
this.ensureStatsTableContainer_(peerConnectionElement);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the DIV container for the stats tables is created as a child of
|
||||
* |peerConnectionElement|.
|
||||
*
|
||||
* @param {!Element} peerConnectionElement The root element.
|
||||
* @return {!Element} The stats table container.
|
||||
* @private
|
||||
*/
|
||||
ensureStatsTableContainer_(peerConnectionElement) {
|
||||
const containerId = peerConnectionElement.id + '-table-container';
|
||||
// Disable getElementById restriction here, since |containerId| is not
|
||||
// always a valid selector.
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
let container = document.getElementById(containerId);
|
||||
if (!container) {
|
||||
container = document.createElement('div');
|
||||
container.id = containerId;
|
||||
container.className = 'stats-table-container';
|
||||
const head = document.createElement('div');
|
||||
head.textContent = 'Stats Tables';
|
||||
container.appendChild(head);
|
||||
const label = document.createElement('label');
|
||||
label.innerText = 'Filter statistics by type including ';
|
||||
container.appendChild(label);
|
||||
const input = document.createElement('input');
|
||||
input.placeholder = 'separate multiple values by `,`';
|
||||
input.size = 25;
|
||||
input.oninput = (e) => this.filterStats(e, container);
|
||||
container.appendChild(input);
|
||||
peerConnectionElement.appendChild(container);
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the stats table for track specified by |report| of PeerConnection
|
||||
* |peerConnectionElement| is created.
|
||||
*
|
||||
* @param {!Element} peerConnectionElement The root element.
|
||||
* @param {!Object} report The object containing stats, which is the object
|
||||
* containing timestamp and values, which is an array of strings, whose
|
||||
* even index entry is the name of the stat, and the odd index entry is
|
||||
* the value.
|
||||
* @return {!Element} The stats table element.
|
||||
* @private
|
||||
*/
|
||||
ensureStatsTable_(peerConnectionElement, report) {
|
||||
const tableId = peerConnectionElement.id + '-table-' + report.id;
|
||||
// Disable getElementById restriction here, since |tableId| is not
|
||||
// always a valid selector.
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
let table = document.getElementById(tableId);
|
||||
if (!table) {
|
||||
const container = this.ensureStatsTableContainer_(peerConnectionElement);
|
||||
const details = document.createElement('details');
|
||||
details.attributes['data-statsType'] = report.type;
|
||||
container.appendChild(details);
|
||||
|
||||
const summary = document.createElement('summary');
|
||||
summary.textContent = generateStatsLabel(report);
|
||||
details.appendChild(summary);
|
||||
|
||||
table = document.createElement('table');
|
||||
details.appendChild(table);
|
||||
table.id = tableId;
|
||||
table.border = 1;
|
||||
|
||||
table.appendChild($('trth-template').content.cloneNode(true));
|
||||
table.rows[0].cells[0].textContent = 'Statistics ' + report.id;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update |statsTable| with |time| and |statsData|.
|
||||
*
|
||||
* @param {!Element} statsTable Which table to update.
|
||||
* @param {number} time The number of milliseconds since epoch.
|
||||
* @param {Array<string>} statsData An array of stats name and value pairs.
|
||||
* @private
|
||||
*/
|
||||
addStatsToTable_(statsTable, time, statsData) {
|
||||
const definedMetrics = new Set();
|
||||
for (let i = 0; i < statsData.length - 1; i = i + 2) {
|
||||
definedMetrics.add(statsData[i]);
|
||||
}
|
||||
// For any previously reported metric that is no longer defined, replace its
|
||||
// now obsolete value with the magic string "(removed)".
|
||||
const metricsContainer = statsTable.firstChild;
|
||||
for (let i = 0; i < metricsContainer.children.length; ++i) {
|
||||
const metricElement = metricsContainer.children[i];
|
||||
// `metricElement` IDs have the format `bla-bla-bla-bla-${metricName}`.
|
||||
let metricName =
|
||||
metricElement.id.substring(metricElement.id.lastIndexOf('-') + 1);
|
||||
if (metricName.endsWith(']')) {
|
||||
// Computed metrics may contain the '-' character (e.g.
|
||||
// `DifferenceCalculator` based metrics) in which case `metricName` will
|
||||
// not have been parsed correctly. Instead look for starting '['.
|
||||
metricName =
|
||||
metricElement.id.substring(metricElement.id.indexOf('['));
|
||||
}
|
||||
if (metricName && metricName != 'timestamp' &&
|
||||
!definedMetrics.has(metricName)) {
|
||||
this.updateStatsTableRow_(statsTable, metricName, '(removed)');
|
||||
}
|
||||
}
|
||||
// Add or update all "metric: value" that have a defined value.
|
||||
const date = new Date(time);
|
||||
this.updateStatsTableRow_(statsTable, 'timestamp', date.toLocaleString());
|
||||
for (let i = 0; i < statsData.length - 1; i = i + 2) {
|
||||
this.updateStatsTableRow_(statsTable, statsData[i], statsData[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the value column of the stats row of |rowName| to |value|.
|
||||
* A new row is created is this is the first report of this stats.
|
||||
*
|
||||
* @param {!Element} statsTable Which table to update.
|
||||
* @param {string} rowName The name of the row to update.
|
||||
* @param {string} value The new value to set.
|
||||
* @private
|
||||
*/
|
||||
updateStatsTableRow_(statsTable, rowName, value) {
|
||||
const trId = statsTable.id + '-' + rowName;
|
||||
// Disable getElementById restriction here, since |trId| is not always
|
||||
// a valid selector.
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
let trElement = document.getElementById(trId);
|
||||
const activeConnectionClass = 'stats-table-active-connection';
|
||||
if (!trElement) {
|
||||
trElement = document.createElement('tr');
|
||||
trElement.id = trId;
|
||||
statsTable.firstChild.appendChild(trElement);
|
||||
const item = $('td2-template').content.cloneNode(true);
|
||||
item.querySelector('td').textContent = rowName;
|
||||
trElement.appendChild(item);
|
||||
}
|
||||
trElement.cells[1].textContent = value;
|
||||
|
||||
// Highlights the table for the active connection.
|
||||
if (rowName === 'googActiveConnection') {
|
||||
if (value === true) {
|
||||
statsTable.parentElement.classList.add(activeConnectionClass);
|
||||
} else {
|
||||
statsTable.parentElement.classList.remove(activeConnectionClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a filter to the stats table
|
||||
* @param event InputEvent from the filter input field.
|
||||
* @param container stats table container element.
|
||||
* @private
|
||||
*/
|
||||
filterStats(event, container) {
|
||||
const filter = event.target.value;
|
||||
const filters = filter.split(',');
|
||||
container.childNodes.forEach(node => {
|
||||
if (node.nodeName !== 'DETAILS') {
|
||||
return;
|
||||
}
|
||||
const statsType = node.attributes['data-statsType'];
|
||||
if (!filter || filters.includes(statsType) ||
|
||||
filters.find(f => statsType.includes(f))) {
|
||||
node.style.display = 'block';
|
||||
} else {
|
||||
node.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue