mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
Add geo endpoints, ip protocol, ether protocol, worst 10 on retransmits.
This commit is contained in:
parent
85961af1a9
commit
0fecadbc7f
@ -439,6 +439,7 @@ export class Dashboard {
|
|||||||
list.size = DashletMenu.length;
|
list.size = DashletMenu.length;
|
||||||
list.style.width = "100%";
|
list.style.width = "100%";
|
||||||
list.classList.add("listBox");
|
list.classList.add("listBox");
|
||||||
|
list.size = 10;
|
||||||
DashletMenu.forEach((d) => {
|
DashletMenu.forEach((d) => {
|
||||||
let entry = document.createElement("option");
|
let entry = document.createElement("option");
|
||||||
entry.value = d.tag;
|
entry.value = d.tag;
|
||||||
|
@ -8,6 +8,10 @@ import {Top10Downloaders} from "./top10_downloaders";
|
|||||||
import {Worst10Downloaders} from "./worst10_downloaders";
|
import {Worst10Downloaders} from "./worst10_downloaders";
|
||||||
import {Top10FlowsBytes} from "./top10flows_bytes";
|
import {Top10FlowsBytes} from "./top10flows_bytes";
|
||||||
import {Top10FlowsRate} from "./top10flows_rate";
|
import {Top10FlowsRate} from "./top10flows_rate";
|
||||||
|
import {Top10EndpointsByCountry} from "./endpoints_by_country";
|
||||||
|
import {EtherProtocols} from "./ether_protocols";
|
||||||
|
import {IpProtocols} from "./ip_protocols";
|
||||||
|
import {Worst10Retransmits} from "./worst10_retransmits";
|
||||||
|
|
||||||
export const DashletMenu = [
|
export const DashletMenu = [
|
||||||
{ name: "Throughput Bits/Second", tag: "throughputBps", size: 3 },
|
{ name: "Throughput Bits/Second", tag: "throughputBps", size: 3 },
|
||||||
@ -18,8 +22,12 @@ export const DashletMenu = [
|
|||||||
{ name: "Round-Trip Time Histogram", tag: "rttHistogram", size: 6 },
|
{ name: "Round-Trip Time Histogram", tag: "rttHistogram", size: 6 },
|
||||||
{ name: "Top 10 Downloaders", tag: "top10downloaders", size: 6 },
|
{ name: "Top 10 Downloaders", tag: "top10downloaders", 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 Retransmits", tag: "worst10retransmits", 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: "Ether Protocols", tag: "etherProtocols", size: 6 },
|
||||||
|
{ name: "IP Protocols", tag: "ipProtocols", size: 6 },
|
||||||
];
|
];
|
||||||
|
|
||||||
export function widgetFactory(widgetName, count) {
|
export function widgetFactory(widgetName, count) {
|
||||||
@ -33,8 +41,12 @@ export function widgetFactory(widgetName, count) {
|
|||||||
case "rttHistogram": widget = new RttHistoDash(count); break;
|
case "rttHistogram": widget = new RttHistoDash(count); break;
|
||||||
case "top10downloaders":widget = new Top10Downloaders(count); break;
|
case "top10downloaders":widget = new Top10Downloaders(count); break;
|
||||||
case "worst10downloaders":widget = new Worst10Downloaders(count); break;
|
case "worst10downloaders":widget = new Worst10Downloaders(count); break;
|
||||||
|
case "worst10retransmits":widget = new Worst10Retransmits(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 "etherProtocols" : widget = new EtherProtocols(count); break;
|
||||||
|
case "ipProtocols" : widget = new IpProtocols(count); break;
|
||||||
default: {
|
default: {
|
||||||
console.log("I don't know how to construct a widget of type [" + widgetName + "]");
|
console.log("I don't know how to construct a widget of type [" + widgetName + "]");
|
||||||
return null;
|
return null;
|
||||||
|
@ -0,0 +1,79 @@
|
|||||||
|
import {BaseDashlet} from "./base_dashlet";
|
||||||
|
import {theading} from "../helpers/builders";
|
||||||
|
import {scaleNumber, scaleNanos} from "../helpers/scaling";
|
||||||
|
|
||||||
|
export class Top10EndpointsByCountry extends BaseDashlet {
|
||||||
|
constructor(slot) {
|
||||||
|
super(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
title() {
|
||||||
|
return "Endpoints by Country";
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeTo() {
|
||||||
|
return [ "EndpointsByCountry" ];
|
||||||
|
}
|
||||||
|
|
||||||
|
buildContainer() {
|
||||||
|
let base = super.buildContainer();
|
||||||
|
base.style.height = "250px";
|
||||||
|
base.style.overflow = "auto";
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
super.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMessage(msg) {
|
||||||
|
if (msg.event === "EndpointsByCountry") {
|
||||||
|
let target = document.getElementById(this.id);
|
||||||
|
|
||||||
|
let t = document.createElement("table");
|
||||||
|
t.classList.add("table", "table-striped", "tiny");
|
||||||
|
|
||||||
|
let th = document.createElement("thead");
|
||||||
|
th.appendChild(theading("Country"));
|
||||||
|
th.appendChild(theading("DL ⬇️"));
|
||||||
|
th.appendChild(theading("UL ⬆️"));
|
||||||
|
th.appendChild(theading("⬇ RTT"));
|
||||||
|
th.appendChild(theading("️️⬆ RTT"));
|
||||||
|
t.appendChild(th);
|
||||||
|
|
||||||
|
let tbody = document.createElement("tbody");
|
||||||
|
msg.data.forEach((r) => {
|
||||||
|
let row = document.createElement("tr");
|
||||||
|
|
||||||
|
let country = document.createElement("td");
|
||||||
|
country.innerText = r[0];
|
||||||
|
row.appendChild(country);
|
||||||
|
|
||||||
|
let dld = document.createElement("td");
|
||||||
|
dld.innerText = scaleNumber(r[1][0]);
|
||||||
|
row.appendChild(dld);
|
||||||
|
|
||||||
|
let dlu = document.createElement("td");
|
||||||
|
dlu.innerText = scaleNumber(r[1][1]);
|
||||||
|
row.appendChild(dlu);
|
||||||
|
|
||||||
|
let rttd = document.createElement("td");
|
||||||
|
rttd.innerText = scaleNanos(r[2][0]);
|
||||||
|
row.appendChild(rttd);
|
||||||
|
|
||||||
|
let rttu = document.createElement("td");
|
||||||
|
rttu.innerText = scaleNanos(r[2][1]);
|
||||||
|
row.appendChild(rttu);
|
||||||
|
|
||||||
|
t.appendChild(row);
|
||||||
|
});
|
||||||
|
t.appendChild(tbody);
|
||||||
|
|
||||||
|
// Display it
|
||||||
|
while (target.children.length > 1) {
|
||||||
|
target.removeChild(target.lastChild);
|
||||||
|
}
|
||||||
|
target.appendChild(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
import {BaseDashlet} from "./base_dashlet";
|
||||||
|
import {simpleRow, theading} from "../helpers/builders";
|
||||||
|
import {scaleNumber, scaleNanos} from "../helpers/scaling";
|
||||||
|
|
||||||
|
export class EtherProtocols extends BaseDashlet {
|
||||||
|
constructor(slot) {
|
||||||
|
super(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
title() {
|
||||||
|
return "Ethernet Protocols";
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeTo() {
|
||||||
|
return [ "EtherProtocols" ];
|
||||||
|
}
|
||||||
|
|
||||||
|
buildContainer() {
|
||||||
|
let base = super.buildContainer();
|
||||||
|
base.style.height = "250px";
|
||||||
|
base.style.overflow = "auto";
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
super.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMessage(msg) {
|
||||||
|
if (msg.event === "EtherProtocols") {
|
||||||
|
let target = document.getElementById(this.id);
|
||||||
|
|
||||||
|
let t = document.createElement("table");
|
||||||
|
t.classList.add("table", "table-striped", "tiny");
|
||||||
|
|
||||||
|
let th = document.createElement("thead");
|
||||||
|
th.appendChild(theading("Protocol"));
|
||||||
|
th.appendChild(theading("DL ⬇️"));
|
||||||
|
th.appendChild(theading("UL ⬆️"));
|
||||||
|
th.appendChild(theading("Packets ⬇️"));
|
||||||
|
th.appendChild(theading("Packets ⬆️"));
|
||||||
|
th.appendChild(theading("⬇ RTT"));
|
||||||
|
th.appendChild(theading("️️⬆ RTT"));
|
||||||
|
t.appendChild(th);
|
||||||
|
|
||||||
|
let tbody = document.createElement("tbody");
|
||||||
|
let row = document.createElement("tr");
|
||||||
|
row.appendChild(simpleRow("IPv4"));
|
||||||
|
row.appendChild(simpleRow(scaleNumber(msg.data.v4_bytes[0])));
|
||||||
|
row.appendChild(simpleRow(scaleNumber(msg.data.v4_bytes[1])));
|
||||||
|
row.appendChild(simpleRow(scaleNumber(msg.data.v4_packets[0])));
|
||||||
|
row.appendChild(simpleRow(scaleNumber(msg.data.v4_packets[1])));
|
||||||
|
row.appendChild(simpleRow(scaleNanos(msg.data.v4_rtt[0])));
|
||||||
|
row.appendChild(simpleRow(scaleNanos(msg.data.v4_rtt[1])));
|
||||||
|
t.appendChild(row);
|
||||||
|
|
||||||
|
row = document.createElement("tr");
|
||||||
|
row.appendChild(simpleRow("IPv6"));
|
||||||
|
row.appendChild(simpleRow(scaleNumber(msg.data.v6_bytes[0])));
|
||||||
|
row.appendChild(simpleRow(scaleNumber(msg.data.v6_bytes[1])));
|
||||||
|
row.appendChild(simpleRow(scaleNumber(msg.data.v6_packets[0])));
|
||||||
|
row.appendChild(simpleRow(scaleNumber(msg.data.v6_packets[1])));
|
||||||
|
row.appendChild(simpleRow(scaleNanos(msg.data.v6_rtt[0])));
|
||||||
|
row.appendChild(simpleRow(scaleNanos(msg.data.v6_rtt[1])));
|
||||||
|
t.appendChild(row);
|
||||||
|
|
||||||
|
t.appendChild(tbody);
|
||||||
|
|
||||||
|
// Display it
|
||||||
|
while (target.children.length > 1) {
|
||||||
|
target.removeChild(target.lastChild);
|
||||||
|
}
|
||||||
|
target.appendChild(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
import {BaseDashlet} from "./base_dashlet";
|
||||||
|
import {simpleRow, theading} from "../helpers/builders";
|
||||||
|
import {scaleNumber, scaleNanos} from "../helpers/scaling";
|
||||||
|
|
||||||
|
export class IpProtocols extends BaseDashlet {
|
||||||
|
constructor(slot) {
|
||||||
|
super(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
title() {
|
||||||
|
return "IP Protocols";
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeTo() {
|
||||||
|
return [ "IpProtocols" ];
|
||||||
|
}
|
||||||
|
|
||||||
|
buildContainer() {
|
||||||
|
let base = super.buildContainer();
|
||||||
|
base.style.height = "250px";
|
||||||
|
base.style.overflow = "auto";
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
super.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMessage(msg) {
|
||||||
|
if (msg.event === "IpProtocols") {
|
||||||
|
let target = document.getElementById(this.id);
|
||||||
|
|
||||||
|
let t = document.createElement("table");
|
||||||
|
t.classList.add("table", "table-striped", "tiny");
|
||||||
|
|
||||||
|
let th = document.createElement("thead");
|
||||||
|
th.appendChild(theading("Protocol"));
|
||||||
|
th.appendChild(theading("DL ⬇️"));
|
||||||
|
th.appendChild(theading("UL ⬆️"));
|
||||||
|
t.appendChild(th);
|
||||||
|
|
||||||
|
let tbody = document.createElement("tbody");
|
||||||
|
|
||||||
|
msg.data.forEach((r) => {
|
||||||
|
let row = document.createElement("tr");
|
||||||
|
|
||||||
|
row.appendChild(simpleRow(r[0]));
|
||||||
|
row.appendChild(simpleRow(scaleNumber(r[1][0])));
|
||||||
|
row.appendChild(simpleRow(scaleNumber(r[1][1])));
|
||||||
|
|
||||||
|
t.appendChild(row);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
t.appendChild(tbody);
|
||||||
|
|
||||||
|
// Display it
|
||||||
|
while (target.children.length > 1) {
|
||||||
|
target.removeChild(target.lastChild);
|
||||||
|
}
|
||||||
|
target.appendChild(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
import {BaseDashlet} from "./base_dashlet";
|
||||||
|
import {RttHistogram} from "../graphs/rtt_histo";
|
||||||
|
import {theading} from "../helpers/builders";
|
||||||
|
import {scaleNumber, rttCircleSpan} from "../helpers/scaling";
|
||||||
|
|
||||||
|
export class Worst10Retransmits extends BaseDashlet {
|
||||||
|
constructor(slot) {
|
||||||
|
super(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
title() {
|
||||||
|
return "Worst 10 TCP Re-transmits";
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeTo() {
|
||||||
|
return [ "WorstRetransmits" ];
|
||||||
|
}
|
||||||
|
|
||||||
|
buildContainer() {
|
||||||
|
let base = super.buildContainer();
|
||||||
|
base.style.height = "250px";
|
||||||
|
base.style.overflow = "auto";
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
super.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMessage(msg) {
|
||||||
|
if (msg.event === "WorstRetransmits") {
|
||||||
|
let target = document.getElementById(this.id);
|
||||||
|
|
||||||
|
let t = document.createElement("table");
|
||||||
|
t.classList.add("table", "table-striped", "tiny");
|
||||||
|
|
||||||
|
let th = document.createElement("thead");
|
||||||
|
th.appendChild(theading(""));
|
||||||
|
th.appendChild(theading("IP Address/Circuit"));
|
||||||
|
th.appendChild(theading("DL ⬇️"));
|
||||||
|
th.appendChild(theading("UL ⬆️"));
|
||||||
|
th.appendChild(theading("RTT (ms)"));
|
||||||
|
th.appendChild(theading("TCP Retransmits"));
|
||||||
|
th.appendChild(theading("Shaped"));
|
||||||
|
t.appendChild(th);
|
||||||
|
|
||||||
|
let tbody = document.createElement("tbody");
|
||||||
|
msg.data.forEach((r) => {
|
||||||
|
let row = document.createElement("tr");
|
||||||
|
|
||||||
|
let circle = document.createElement("td");
|
||||||
|
circle.appendChild(rttCircleSpan(r.median_tcp_rtt));
|
||||||
|
row.appendChild(circle);
|
||||||
|
|
||||||
|
let ip = document.createElement("td");
|
||||||
|
ip.innerText = r.ip_address;
|
||||||
|
row.append(ip);
|
||||||
|
|
||||||
|
let dl = document.createElement("td");
|
||||||
|
dl.innerText = scaleNumber(r.bits_per_second[0]);
|
||||||
|
row.append(dl);
|
||||||
|
|
||||||
|
let ul = document.createElement("td");
|
||||||
|
ul.innerText = scaleNumber(r.bits_per_second[1]);
|
||||||
|
row.append(ul);
|
||||||
|
|
||||||
|
let rtt = document.createElement("td");
|
||||||
|
rtt.innerText = r.median_tcp_rtt.toFixed(2);
|
||||||
|
row.append(rtt);
|
||||||
|
|
||||||
|
let tcp_xmit = document.createElement("td");
|
||||||
|
tcp_xmit.innerText = r.tcp_retransmits[0] + " / " + r.tcp_retransmits[1];
|
||||||
|
row.append(tcp_xmit);
|
||||||
|
|
||||||
|
let shaped = document.createElement("td");
|
||||||
|
shaped.innerText = r.plan[0] + " / " + r.plan[1];
|
||||||
|
row.append(shaped);
|
||||||
|
|
||||||
|
t.appendChild(row);
|
||||||
|
});
|
||||||
|
t.appendChild(tbody);
|
||||||
|
|
||||||
|
// Display it
|
||||||
|
while (target.children.length > 1) {
|
||||||
|
target.removeChild(target.lastChild);
|
||||||
|
}
|
||||||
|
target.appendChild(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,4 +8,10 @@ export function theading(text) {
|
|||||||
let th = document.createElement("th");
|
let th = document.createElement("th");
|
||||||
th.innerText = text;
|
th.innerText = text;
|
||||||
return th;
|
return th;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function simpleRow(text) {
|
||||||
|
let td = document.createElement("td");
|
||||||
|
td.innerText = text;
|
||||||
|
return td;
|
||||||
}
|
}
|
@ -9,6 +9,10 @@ pub enum PublishedChannels {
|
|||||||
FlowCount,
|
FlowCount,
|
||||||
TopDownloads,
|
TopDownloads,
|
||||||
WorstRTT,
|
WorstRTT,
|
||||||
|
WorstRetransmits,
|
||||||
TopFlowsBytes,
|
TopFlowsBytes,
|
||||||
TopFlowsRate,
|
TopFlowsRate,
|
||||||
|
EndpointsByCountry,
|
||||||
|
EtherProtocols,
|
||||||
|
IpProtocols,
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ mod flow_counter;
|
|||||||
mod top_10;
|
mod top_10;
|
||||||
mod ipstats_conversion;
|
mod ipstats_conversion;
|
||||||
mod top_flows;
|
mod top_flows;
|
||||||
|
mod flow_endpoints;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use crate::node_manager::ws::publish_subscribe::PubSub;
|
use crate::node_manager::ws::publish_subscribe::PubSub;
|
||||||
@ -22,8 +23,12 @@ pub(super) async fn channel_ticker(channels: Arc<PubSub>) {
|
|||||||
flow_counter::flow_count(channels.clone()),
|
flow_counter::flow_count(channels.clone()),
|
||||||
top_10::top_10_downloaders(channels.clone()),
|
top_10::top_10_downloaders(channels.clone()),
|
||||||
top_10::worst_10_downloaders(channels.clone()),
|
top_10::worst_10_downloaders(channels.clone()),
|
||||||
|
top_10::worst_10_retransmit(channels.clone()),
|
||||||
top_flows::top_flows_bytes(channels.clone()),
|
top_flows::top_flows_bytes(channels.clone()),
|
||||||
top_flows::top_flows_rate(channels.clone()),
|
top_flows::top_flows_rate(channels.clone()),
|
||||||
|
flow_endpoints::endpoints_by_country(channels.clone()),
|
||||||
|
flow_endpoints::ether_protocols(channels.clone()),
|
||||||
|
flow_endpoints::ip_protocols(channels.clone()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
64
src/rust/lqosd/src/node_manager/ws/ticker/flow_endpoints.rs
Normal file
64
src/rust/lqosd/src/node_manager/ws/ticker/flow_endpoints.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
use lqos_bus::BusResponse;
|
||||||
|
|
||||||
|
use crate::node_manager::ws::publish_subscribe::PubSub;
|
||||||
|
use crate::node_manager::ws::published_channels::PublishedChannels;
|
||||||
|
use crate::throughput_tracker;
|
||||||
|
|
||||||
|
pub async fn endpoints_by_country(channels: Arc<PubSub>) {
|
||||||
|
if !channels.is_channel_alive(PublishedChannels::EndpointsByCountry).await {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let BusResponse::CurrentEndpointsByCountry(countries) = throughput_tracker::current_endpoints_by_country() {
|
||||||
|
let message = json!(
|
||||||
|
{
|
||||||
|
"event": PublishedChannels::EndpointsByCountry.to_string(),
|
||||||
|
"data": countries,
|
||||||
|
}
|
||||||
|
).to_string();
|
||||||
|
channels.send(PublishedChannels::EndpointsByCountry, message).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn ether_protocols(channels: Arc<PubSub>) {
|
||||||
|
if !channels.is_channel_alive(PublishedChannels::EtherProtocols).await {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let BusResponse::EtherProtocols { v4_bytes, v6_bytes, v4_packets, v6_packets, v4_rtt, v6_rtt } = throughput_tracker::ether_protocol_summary() {
|
||||||
|
let message = json!(
|
||||||
|
{
|
||||||
|
"event": PublishedChannels::EtherProtocols.to_string(),
|
||||||
|
"data": {
|
||||||
|
"v4_bytes": v4_bytes,
|
||||||
|
"v6_bytes": v6_bytes,
|
||||||
|
"v4_packets": v4_packets,
|
||||||
|
"v6_packets": v6_packets,
|
||||||
|
"v4_rtt": v4_rtt,
|
||||||
|
"v6_rtt": v6_rtt,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
).to_string();
|
||||||
|
channels.send(PublishedChannels::EtherProtocols, message).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn ip_protocols(channels: Arc<PubSub>) {
|
||||||
|
if !channels.is_channel_alive(PublishedChannels::IpProtocols).await {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let BusResponse::IpProtocols(ip_data) = throughput_tracker::ip_protocol_summary() {
|
||||||
|
let message = json!(
|
||||||
|
{
|
||||||
|
"event": PublishedChannels::IpProtocols.to_string(),
|
||||||
|
"data": ip_data,
|
||||||
|
}
|
||||||
|
).to_string();
|
||||||
|
channels.send(PublishedChannels::IpProtocols, message).await;
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ use lqos_bus::BusResponse;
|
|||||||
use crate::node_manager::ws::publish_subscribe::PubSub;
|
use crate::node_manager::ws::publish_subscribe::PubSub;
|
||||||
use crate::node_manager::ws::published_channels::PublishedChannels;
|
use crate::node_manager::ws::published_channels::PublishedChannels;
|
||||||
use crate::node_manager::ws::ticker::ipstats_conversion::IpStatsWithPlan;
|
use crate::node_manager::ws::ticker::ipstats_conversion::IpStatsWithPlan;
|
||||||
|
use crate::throughput_tracker;
|
||||||
use crate::throughput_tracker::{top_n, worst_n};
|
use crate::throughput_tracker::{top_n, worst_n};
|
||||||
|
|
||||||
pub async fn top_10_downloaders(channels: Arc<PubSub>) {
|
pub async fn top_10_downloaders(channels: Arc<PubSub>) {
|
||||||
@ -46,4 +47,25 @@ pub async fn worst_10_downloaders(channels: Arc<PubSub>) {
|
|||||||
).to_string();
|
).to_string();
|
||||||
channels.send(PublishedChannels::WorstRTT, message).await;
|
channels.send(PublishedChannels::WorstRTT, message).await;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn worst_10_retransmit(channels: Arc<PubSub>) {
|
||||||
|
if !channels.is_channel_alive(PublishedChannels::WorstRetransmits).await {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let BusResponse::WorstRetransmits(top) = throughput_tracker::worst_n_retransmits(0, 10) {
|
||||||
|
let result: Vec<IpStatsWithPlan> = top
|
||||||
|
.iter()
|
||||||
|
.map(|stat| stat.into())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let message = json!(
|
||||||
|
{
|
||||||
|
"event": PublishedChannels::WorstRetransmits.to_string(),
|
||||||
|
"data": result
|
||||||
|
}
|
||||||
|
).to_string();
|
||||||
|
channels.send(PublishedChannels::WorstRetransmits, message).await;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user