Bug 1825397 - enhance graph legibility in aobut:webrtc;r=dbaker,jib

Differential Revision: https://phabricator.services.mozilla.com/D174013
This commit is contained in:
Nico Grunbaum 2023-03-29 23:34:36 +00:00
Родитель 3568650420
Коммит 6a86219d86
3 изменённых файлов: 41 добавлений и 15 удалений

Просмотреть файл

@ -735,17 +735,21 @@ function renderRTPStats(rndr, report, hist) {
// Those graphs can be larger to show trends. // Those graphs can be larger to show trends.
const histSecs = gd.getConfig().histSecs; const histSecs = gd.getConfig().histSecs;
const canvas = rndr.elem_canvas({ const canvas = rndr.elem_canvas({
width: (histSecs > 30 ? histSecs / 3 : 15) * 15, width: (histSecs > 30 ? histSecs / 3 : 15) * 20,
height: 100, height: 100,
className: "line-graph", className: "line-graph",
}); });
const graph = new GraphImpl(canvas, canvas.width, canvas.height); const graph = new GraphImpl(canvas, canvas.width, canvas.height);
graph.startTime = () => stat.timestamp - histSecs * 1000; graph.startTime = () => stat.timestamp - histSecs * 1000;
graph.stopTime = () => stat.timestamp; graph.stopTime = () => stat.timestamp;
graph.maxColor = max => if (gd.subKey == "packetsLost") {
gd.subKey == "packetsLost" && max > 0 ? "red" : "grey"; const oldMaxColor = graph.maxColor;
// Get a bit more history for averages graph.maxColor = data => (data.value == 0 ? "red" : oldMaxColor(data));
let dataSet = gd.getDataSetSince(graph.startTime() - histSecs * 200); }
// Get a bit more history for averages (20%)
const dataSet = gd.getDataSetSince(
graph.startTime() - histSecs * 0.2 * 1000
);
graph.drawSparseValues(dataSet, gd.subKey, gd.getConfig()); graph.drawSparseValues(dataSet, gd.subKey, gd.getConfig());
return canvas; return canvas;
}); });
@ -762,8 +766,9 @@ function renderRTPStats(rndr, report, hist) {
]), ]),
] ]
: []; : [];
const mime = stat?.codecStat?.mimeType?.concat(" - ") || "";
const div = renderElements("div", {}, [ const div = renderElements("div", {}, [
rndr.text_h5(`SSRC ${ssrc}`), rndr.text_h5(`${mime}SSRC ${ssrc}`),
rndr.elems_div({}, [rndr.text_h6(stat.type), ...graphsByStat(stat)]), rndr.elems_div({}, [rndr.text_h6(stat.type), ...graphsByStat(stat)]),
...remoteGraphs, ...remoteGraphs,
renderCodecStats(stat), renderCodecStats(stat),

Просмотреть файл

@ -2,6 +2,20 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function compStyle(property) {
return getComputedStyle(window.document.body).getPropertyValue(property);
}
function toHumanReadable(num, fpDecimals) {
const prefixes = [..." kMGTPEYZYRQ"];
const inner = (curr, remainingPrefixes) => {
return Math.abs(curr >= 1000)
? inner(curr / 1000, remainingPrefixes.slice(1, -1))
: [curr.toFixed(fpDecimals), remainingPrefixes[0].trimEnd()];
};
return inner(num, prefixes);
}
class GraphImpl { class GraphImpl {
constructor(canvas, width, height) { constructor(canvas, width, height) {
this.canvas = canvas; this.canvas = canvas;
@ -21,7 +35,7 @@ class GraphImpl {
/** @type {CanvasRenderingContext2D} */ /** @type {CanvasRenderingContext2D} */
drawCtx = {}; drawCtx = {};
// The default background color // The default background color
bgColor = () => "var(--in-content-box-info-background)"; bgColor = () => compStyle("--in-content-page-background");
// The color to use for value graph lines // The color to use for value graph lines
valueLineColor = () => "grey"; valueLineColor = () => "grey";
// The color to use for average graph lines and text // The color to use for average graph lines and text
@ -31,7 +45,7 @@ class GraphImpl {
// The color to use for the min value // The color to use for the min value
minColor = ({ time, value }) => "grey"; minColor = ({ time, value }) => "grey";
// Title color // Title color
titleColor = title => "grey"; titleColor = title => compStyle("--in-content-page-color");
// The color to use for a data point at a time. // The color to use for a data point at a time.
// The destination x coordinate and graph width are also provided. // The destination x coordinate and graph width are also provided.
datumColor = ({ time, value, x, width }) => "red"; datumColor = ({ time, value, x, width }) => "red";
@ -77,6 +91,7 @@ class GraphImpl {
this.height - 1 - (value - rangeMin) * yFactor - 13; this.height - 1 - (value - rangeMin) * yFactor - 13;
const xFactor = width / (1 + stopTime - startTime); const xFactor = width / (1 + stopTime - startTime);
const xPos = ({ time }) => (time - startTime) * xFactor; const xPos = ({ time }) => (time - startTime) * xFactor;
ctx.lineWidth = 1;
ctx.beginPath(); ctx.beginPath();
ctx.strokeStyle = this.valueLineColor(); ctx.strokeStyle = this.valueLineColor();
[...filtered.dataPoints].forEach((datum, index) => { [...filtered.dataPoints].forEach((datum, index) => {
@ -92,6 +107,7 @@ class GraphImpl {
ctx.stroke(); ctx.stroke();
// Rolling average // Rolling average
ctx.lineWidth = 2;
ctx.strokeStyle = this.averageLineColor(); ctx.strokeStyle = this.averageLineColor();
ctx.beginPath(); ctx.beginPath();
const rollingAverage = avgDataSet.dataPoints; const rollingAverage = avgDataSet.dataPoints;
@ -103,12 +119,16 @@ class GraphImpl {
} }
}); });
const fixed = num => num.toFixed(config.fixedPointDecimals); const fixed = num => num.toFixed(config.fixedPointDecimals);
const formatValue = value =>
config.toHuman
? toHumanReadable(value, config.fixedPointDecimals).join("")
: fixed(value);
rollingAverage.slice(-1).forEach(({ value }) => { rollingAverage.slice(-1).forEach(({ value }) => {
ctx.stroke(); ctx.stroke();
ctx.fillStyle = this.averageLineColor(); ctx.fillStyle = this.averageLineColor();
ctx.font = "11px Arial"; ctx.font = "12px Arial";
ctx.textAlign = "left"; ctx.textAlign = "left";
ctx.fillText(fixed(value), 5, this.height - 4); ctx.fillText(formatValue(value), 5, this.height - 4);
}); });
// Draw the title // Draw the title
@ -118,12 +138,12 @@ class GraphImpl {
ctx.textAlign = "left"; ctx.textAlign = "left";
ctx.fillText(`${title}${config.toRate ? "/s" : ""}`, 5, 12); ctx.fillText(`${title}${config.toRate ? "/s" : ""}`, 5, 12);
} }
ctx.font = "11px Arial"; ctx.font = "12px Arial";
ctx.fillStyle = this.maxColor(range.max); ctx.fillStyle = this.maxColor(range.max);
ctx.textAlign = "right"; ctx.textAlign = "right";
ctx.fillText(fixed(range.max), this.width - 5, 12); ctx.fillText(formatValue(range.max), this.width - 5, 12);
ctx.fillStyle = this.minColor(range.min); ctx.fillStyle = this.minColor(range.min);
ctx.fillText(fixed(range.min), this.width - 5, this.height - 4); ctx.fillText(formatValue(range.min), this.width - 5, this.height - 4);
}; };
} }

Просмотреть файл

@ -10,11 +10,12 @@ const CHECK_RTC_STATS_COLLECTION = [
]; ];
const DEFAULT_PROPS = { const DEFAULT_PROPS = {
avgPoints: 5, avgPoints: 10,
histSecs: 15, histSecs: 15,
toRate: false, toRate: false,
noAvg: false, noAvg: false,
fixedPointDecimals: 2, fixedPointDecimals: 2,
toHuman: false,
}; };
const REMOTE_RTP_PROPS = "avgPoints=2;histSecs=90"; const REMOTE_RTP_PROPS = "avgPoints=2;histSecs=90";
@ -29,7 +30,7 @@ const GRAPH_KEYS = [
"outbound-rtp.nackCount", "outbound-rtp.nackCount",
"outbound-rtp.pliCount", "outbound-rtp.pliCount",
"outbound-rtp.firCount", "outbound-rtp.firCount",
`remote-outbound-rtp.bytesSent;toRate;${REMOTE_RTP_PROPS}`, `remote-outbound-rtp.bytesSent;toHuman;toRate;${REMOTE_RTP_PROPS}`,
`remote-outbound-rtp.packetsSent;toRate;${REMOTE_RTP_PROPS}`, `remote-outbound-rtp.packetsSent;toRate;${REMOTE_RTP_PROPS}`,
] ]
.map(k => k.split(".", 2)) .map(k => k.split(".", 2))