mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
Offer visual sankey alternatives for Top 10 Downloaders, Worst 10 RTT and Worst 10 Retransmit.
This commit is contained in:
parent
f9e416ba07
commit
699542501c
@ -22,6 +22,8 @@ import {TreeCapacityDash} from "./tree_capacity_dash";
|
|||||||
import {CircuitCapacityDash} from "./circuit_capacity_dash";
|
import {CircuitCapacityDash} from "./circuit_capacity_dash";
|
||||||
import {TopTreeSankey} from "./top_tree_sankey";
|
import {TopTreeSankey} from "./top_tree_sankey";
|
||||||
import {Top10DownloadersVisual} from "./top10_downloads_graphic";
|
import {Top10DownloadersVisual} from "./top10_downloads_graphic";
|
||||||
|
import {Worst10DownloadersVisual} from "./worst10_downloaders_graphic";
|
||||||
|
import {Worst10RetransmitsVisual} from "./worst10_retransmits_graphic";
|
||||||
|
|
||||||
export const DashletMenu = [
|
export const DashletMenu = [
|
||||||
{ name: "Throughput Bits/Second", tag: "throughputBps", size: 3 },
|
{ name: "Throughput Bits/Second", tag: "throughputBps", size: 3 },
|
||||||
@ -33,7 +35,9 @@ export const DashletMenu = [
|
|||||||
{ name: "Top 10 Downloaders", tag: "top10downloaders", size: 6 },
|
{ name: "Top 10 Downloaders", tag: "top10downloaders", size: 6 },
|
||||||
{ name: "Top 10 Downloaders (Visual)", tag: "top10downloadersV", size: 6 },
|
{ name: "Top 10 Downloaders (Visual)", tag: "top10downloadersV", size: 6 },
|
||||||
{ name: "Worst 10 Round-Trip Time", tag: "worst10downloaders", size: 6 },
|
{ name: "Worst 10 Round-Trip Time", tag: "worst10downloaders", size: 6 },
|
||||||
|
{ name: "Worst 10 Round-Trip Time (Visual)", tag: "worst10downloadersV", size: 6 },
|
||||||
{ name: "Worst 10 Retransmits", tag: "worst10retransmits", size: 6 },
|
{ name: "Worst 10 Retransmits", tag: "worst10retransmits", size: 6 },
|
||||||
|
{ name: "Worst 10 Retransmits (Visual)", tag: "worst10retransmitsV", size: 6 },
|
||||||
{ name: "Top 10 Flows (total bytes)", tag: "top10flowsBytes", size: 6 },
|
{ name: "Top 10 Flows (total bytes)", tag: "top10flowsBytes", size: 6 },
|
||||||
{ name: "Top 10 Flows (rate)", tag: "top10flowsRate", size: 6 },
|
{ name: "Top 10 Flows (rate)", tag: "top10flowsRate", size: 6 },
|
||||||
{ name: "Top 10 Endpoints by Country", tag: "top10endpointsCountry", size: 6 },
|
{ name: "Top 10 Endpoints by Country", tag: "top10endpointsCountry", size: 6 },
|
||||||
@ -63,7 +67,9 @@ export function widgetFactory(widgetName, count) {
|
|||||||
case "top10downloaders":widget = new Top10Downloaders(count); break;
|
case "top10downloaders":widget = new Top10Downloaders(count); break;
|
||||||
case "top10downloadersV":widget = new Top10DownloadersVisual(count); break;
|
case "top10downloadersV":widget = new Top10DownloadersVisual(count); break;
|
||||||
case "worst10downloaders":widget = new Worst10Downloaders(count); break;
|
case "worst10downloaders":widget = new Worst10Downloaders(count); break;
|
||||||
|
case "worst10downloadersV":widget = new Worst10DownloadersVisual(count); break;
|
||||||
case "worst10retransmits":widget = new Worst10Retransmits(count); break;
|
case "worst10retransmits":widget = new Worst10Retransmits(count); break;
|
||||||
|
case "worst10retransmitsV":widget = new Worst10RetransmitsVisual(count); break;
|
||||||
case "top10flowsBytes" : widget = new Top10FlowsBytes(count); break;
|
case "top10flowsBytes" : widget = new Top10FlowsBytes(count); break;
|
||||||
case "top10flowsRate" : widget = new Top10FlowsRate(count); break;
|
case "top10flowsRate" : widget = new Top10FlowsRate(count); break;
|
||||||
case "top10endpointsCountry" : widget = new Top10EndpointsByCountry(count); break;
|
case "top10endpointsCountry" : widget = new Top10EndpointsByCountry(count); break;
|
||||||
|
@ -1,40 +1,10 @@
|
|||||||
import {BaseDashlet} from "./base_dashlet";
|
import {BaseDashlet} from "./base_dashlet";
|
||||||
import {RttHistogram} from "../graphs/rtt_histo";
|
|
||||||
import {clearDashDiv, theading, TopNTableFromMsgData, topNTableHeader, topNTableRow} from "../helpers/builders";
|
|
||||||
import {
|
import {
|
||||||
scaleNumber,
|
scaleNumber,
|
||||||
rttCircleSpan,
|
|
||||||
formatThroughput,
|
|
||||||
formatRtt,
|
|
||||||
formatRetransmit,
|
|
||||||
lerpGreenToRedViaOrange, lerpColor
|
lerpGreenToRedViaOrange, lerpColor
|
||||||
} from "../helpers/scaling";
|
} from "../helpers/scaling";
|
||||||
import {redactCell} from "../helpers/redact";
|
|
||||||
import {DashboardGraph} from "../graphs/dashboard_graph";
|
import {DashboardGraph} from "../graphs/dashboard_graph";
|
||||||
|
import {TopNSankey} from "../graphs/top_n_sankey";
|
||||||
class Top10DownloadSankey extends DashboardGraph {
|
|
||||||
constructor(id) {
|
|
||||||
super(id);
|
|
||||||
this.option = {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
nodeAlign: 'left',
|
|
||||||
type: 'sankey',
|
|
||||||
data: [],
|
|
||||||
links: []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
this.option && this.chart.setOption(this.option);
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data, links) {
|
|
||||||
this.option.series[0].data = data;
|
|
||||||
this.option.series[0].links = links;
|
|
||||||
this.chart.hideLoading();
|
|
||||||
this.chart.setOption(this.option);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Top10DownloadersVisual extends BaseDashlet {
|
export class Top10DownloadersVisual extends BaseDashlet {
|
||||||
constructor(slot) {
|
constructor(slot) {
|
||||||
@ -65,60 +35,13 @@ export class Top10DownloadersVisual extends BaseDashlet {
|
|||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
super.setup();
|
super.setup();
|
||||||
this.graph = new Top10DownloadSankey(this.graphDivId());
|
this.graph = new TopNSankey(this.graphDivId());
|
||||||
}
|
}
|
||||||
|
|
||||||
onMessage(msg) {
|
onMessage(msg) {
|
||||||
if (msg.event === "TopDownloads") {
|
if (msg.event === "TopDownloads") {
|
||||||
//console.log(msg);
|
//console.log(msg);
|
||||||
|
this.graph.processMessage(msg);
|
||||||
let nodes = [];
|
|
||||||
let links = [];
|
|
||||||
|
|
||||||
nodes.push({
|
|
||||||
name: "Root",
|
|
||||||
label: "Root",
|
|
||||||
});
|
|
||||||
|
|
||||||
msg.data.forEach((r) => {
|
|
||||||
let label = {
|
|
||||||
fontSize: 9,
|
|
||||||
color: "#999"
|
|
||||||
};
|
|
||||||
|
|
||||||
let name = r.ip_address+ " (" + scaleNumber(r.bits_per_second.down, 0) + ", " + r.tcp_retransmits.down + "/" + r.tcp_retransmits.up + ")";
|
|
||||||
let bytes = r.bits_per_second.down / 8;
|
|
||||||
let bytesAsMegabits = bytes / 1000000;
|
|
||||||
let maxBytes = r.plan.down / 8;
|
|
||||||
let percent = Math.min(100, (bytesAsMegabits / maxBytes) * 100);
|
|
||||||
let capacityColor = lerpGreenToRedViaOrange(100 - percent, 100);
|
|
||||||
|
|
||||||
let rttColor = lerpGreenToRedViaOrange(200 - r.median_tcp_rtt, 200);
|
|
||||||
|
|
||||||
let percentRxmit = Math.min(100, r.tcp_retransmits.down + r.tcp_retransmits.up) / 100;
|
|
||||||
let rxmitColor = lerpColor([0, 255, 0], [255, 0, 0], percentRxmit);
|
|
||||||
|
|
||||||
nodes.push({
|
|
||||||
name: name,
|
|
||||||
label: label,
|
|
||||||
itemStyle: {
|
|
||||||
color: rxmitColor,
|
|
||||||
borderWidth: 4,
|
|
||||||
borderColor: rttColor,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
links.push({
|
|
||||||
source: "Root",
|
|
||||||
target: name,
|
|
||||||
value: r.bits_per_second.down,
|
|
||||||
lineStyle: {
|
|
||||||
color: capacityColor
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
this.graph.update(nodes, links);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
import {BaseDashlet} from "./base_dashlet";
|
||||||
|
import {TopNSankey} from "../graphs/top_n_sankey";
|
||||||
|
|
||||||
|
export class Worst10DownloadersVisual extends BaseDashlet {
|
||||||
|
constructor(slot) {
|
||||||
|
super(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
canBeSlowedDown() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
title() {
|
||||||
|
return "Worst 10 Round-Trip Time";
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip() {
|
||||||
|
return "<h5>Worst 10 Round-Trip Time</h5><p>Worst 10 Downloaders by round-trip time, including IP address, download and upload rates, round-trip time, TCP retransmits, and shaping plan.</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeTo() {
|
||||||
|
return [ "WorstRTT" ];
|
||||||
|
}
|
||||||
|
|
||||||
|
buildContainer() {
|
||||||
|
let base = super.buildContainer();
|
||||||
|
base.appendChild(this.graphDiv());
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
super.setup();
|
||||||
|
this.graph = new TopNSankey(this.graphDivId());
|
||||||
|
}
|
||||||
|
|
||||||
|
onMessage(msg) {
|
||||||
|
if (msg.event === "WorstRTT") {
|
||||||
|
this.graph.processMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
import {BaseDashlet} from "./base_dashlet";
|
||||||
|
import {RttHistogram} from "../graphs/rtt_histo";
|
||||||
|
import {clearDashDiv, theading, TopNTableFromMsgData, topNTableHeader, topNTableRow} from "../helpers/builders";
|
||||||
|
import {scaleNumber, rttCircleSpan, formatRtt, formatThroughput} from "../helpers/scaling";
|
||||||
|
import {redactCell} from "../helpers/redact";
|
||||||
|
import {TopNSankey} from "../graphs/top_n_sankey";
|
||||||
|
|
||||||
|
export class Worst10RetransmitsVisual extends BaseDashlet {
|
||||||
|
constructor(slot) {
|
||||||
|
super(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
canBeSlowedDown() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
title() {
|
||||||
|
return "Worst 10 TCP Re-transmits";
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip() {
|
||||||
|
return "<h5>Worst 10 TCP Re-transmits</h5><p>Worst 10 Downloaders by TCP retransmits, including IP address, download and upload rates, round-trip time, TCP retransmits, and shaping plan.</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeTo() {
|
||||||
|
return [ "WorstRetransmits" ];
|
||||||
|
}
|
||||||
|
|
||||||
|
buildContainer() {
|
||||||
|
let base = super.buildContainer();
|
||||||
|
base.appendChild(this.graphDiv());
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
super.setup();
|
||||||
|
this.graph = new TopNSankey(this.graphDivId());
|
||||||
|
}
|
||||||
|
|
||||||
|
onMessage(msg) {
|
||||||
|
if (msg.event === "WorstRetransmits") {
|
||||||
|
this.graph.processMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
import {DashboardGraph} from "./dashboard_graph";
|
||||||
|
import {lerpColor, lerpGreenToRedViaOrange, scaleNumber} from "../helpers/scaling";
|
||||||
|
|
||||||
|
export class TopNSankey extends DashboardGraph {
|
||||||
|
constructor(id) {
|
||||||
|
super(id);
|
||||||
|
this.option = {
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
nodeAlign: 'left',
|
||||||
|
type: 'sankey',
|
||||||
|
data: [],
|
||||||
|
links: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
this.option && this.chart.setOption(this.option);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(data, links) {
|
||||||
|
this.option.series[0].data = data;
|
||||||
|
this.option.series[0].links = links;
|
||||||
|
this.chart.hideLoading();
|
||||||
|
this.chart.setOption(this.option);
|
||||||
|
}
|
||||||
|
|
||||||
|
processMessage(msg) {
|
||||||
|
let nodes = [];
|
||||||
|
let links = [];
|
||||||
|
|
||||||
|
nodes.push({
|
||||||
|
name: "Root",
|
||||||
|
label: "Root",
|
||||||
|
});
|
||||||
|
|
||||||
|
msg.data.forEach((r) => {
|
||||||
|
let label = {
|
||||||
|
fontSize: 9,
|
||||||
|
color: "#999"
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = r.ip_address+ " (" + scaleNumber(r.bits_per_second.down, 0) + ", " + r.tcp_retransmits.down + "/" + r.tcp_retransmits.up + ")";
|
||||||
|
let bytes = r.bits_per_second.down / 8;
|
||||||
|
let bytesAsMegabits = bytes / 1000000;
|
||||||
|
let maxBytes = r.plan.down / 8;
|
||||||
|
let percent = Math.min(100, (bytesAsMegabits / maxBytes) * 100);
|
||||||
|
let capacityColor = lerpGreenToRedViaOrange(100 - percent, 100);
|
||||||
|
|
||||||
|
let rttColor = lerpGreenToRedViaOrange(200 - r.median_tcp_rtt, 200);
|
||||||
|
|
||||||
|
let percentRxmit = Math.min(100, r.tcp_retransmits.down + r.tcp_retransmits.up) / 100;
|
||||||
|
let rxmitColor = lerpColor([0, 255, 0], [255, 0, 0], percentRxmit);
|
||||||
|
|
||||||
|
nodes.push({
|
||||||
|
name: name,
|
||||||
|
label: label,
|
||||||
|
itemStyle: {
|
||||||
|
color: rxmitColor,
|
||||||
|
borderWidth: 4,
|
||||||
|
borderColor: rttColor,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
links.push({
|
||||||
|
source: "Root",
|
||||||
|
target: name,
|
||||||
|
value: r.bits_per_second.down,
|
||||||
|
lineStyle: {
|
||||||
|
color: capacityColor
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.update(nodes, links);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user