Squish JSON into MsgPack for most common queries, resulting in a big reduction in bandwidth usage.

This commit is contained in:
Herbert Wolverson 2023-03-08 21:08:38 +00:00
parent b1091a94aa
commit 6575517040
15 changed files with 143 additions and 95 deletions

View File

@ -87,6 +87,7 @@ fn rocket() -> _ {
static_pages::bootsrap_css,
static_pages::plotly_js,
static_pages::jquery_js,
static_pages::msgpack_js,
static_pages::bootsrap_js,
static_pages::tinylogo,
static_pages::favicon,

View File

@ -4,7 +4,7 @@ use lqos_bus::{bus_request, BusRequest, BusResponse};
use lqos_config::NetworkJsonTransport;
use rocket::{
fs::NamedFile,
serde::{json::Json, Serialize},
serde::{json::Json, Serialize, msgpack::MsgPack},
};
use crate::{cache_control::NoCache, tracker::SHAPED_DEVICES};
@ -19,7 +19,7 @@ pub async fn tree_page<'a>() -> NoCache<Option<NamedFile>> {
#[get("/api/network_tree/<parent>")]
pub async fn tree_entry(
parent: usize,
) -> NoCache<Json<Vec<(usize, NetworkJsonTransport)>>> {
) -> NoCache<MsgPack<Vec<(usize, NetworkJsonTransport)>>> {
let responses =
bus_request(vec![BusRequest::GetNetworkMap { parent }]).await.unwrap();
let result = match &responses[0] {
@ -27,19 +27,19 @@ pub async fn tree_entry(
_ => Vec::new(),
};
NoCache::new(Json(result))
NoCache::new(MsgPack(result))
}
#[get("/api/network_tree_summary")]
pub async fn network_tree_summary(
) -> NoCache<Json<Vec<(usize, NetworkJsonTransport)>>> {
) -> NoCache<MsgPack<Vec<(usize, NetworkJsonTransport)>>> {
let responses =
bus_request(vec![BusRequest::TopMapQueues(4)]).await.unwrap();
let result = match &responses[0] {
BusResponse::NetworkMap(nodes) => nodes.to_owned(),
_ => Vec::new(),
};
NoCache::new(Json(result))
NoCache::new(MsgPack(result))
}
#[derive(Serialize, Clone)]
@ -54,7 +54,7 @@ pub struct CircuitThroughput {
#[get("/api/tree_clients/<parent>")]
pub async fn tree_clients(
parent: String,
) -> NoCache<Json<Vec<CircuitThroughput>>> {
) -> NoCache<MsgPack<Vec<CircuitThroughput>>> {
let mut result = Vec::new();
for msg in
bus_request(vec![BusRequest::GetHostCounter]).await.unwrap().iter()
@ -82,7 +82,7 @@ pub async fn tree_clients(
}
}
}
NoCache::new(Json(result))
NoCache::new(MsgPack(result))
}
#[post("/api/node_names", data = "<nodes>")]

View File

@ -104,6 +104,11 @@ pub async fn jquery_js<'a>() -> LongCache<Option<NamedFile>> {
LongCache::new(NamedFile::open("static/vendor/jquery.min.js").await.ok())
}
#[get("/vendor/msgpack.min.js")]
pub async fn msgpack_js<'a>() -> LongCache<Option<NamedFile>> {
LongCache::new(NamedFile::open("static/vendor/msgpack.min.js").await.ok())
}
#[get("/vendor/bootstrap.bundle.min.js")]
pub async fn bootsrap_js<'a>() -> LongCache<Option<NamedFile>> {
LongCache::new(

View File

@ -9,7 +9,7 @@ use crate::{auth_guard::AuthGuard, cache_control::NoCache};
pub use cache::SHAPED_DEVICES;
pub use cache_manager::update_tracking;
use lqos_bus::{bus_request, BusRequest, BusResponse, IpStats, TcHandle};
use rocket::serde::{json::Json, Deserialize, Serialize};
use rocket::serde::{Deserialize, Serialize, msgpack::MsgPack};
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(crate = "rocket::serde")]
@ -69,7 +69,7 @@ pub struct ThroughputPerSecond {
#[get("/api/current_throughput")]
pub async fn current_throughput(
_auth: AuthGuard,
) -> Json<ThroughputPerSecond> {
) -> NoCache<MsgPack<ThroughputPerSecond>> {
let mut result = ThroughputPerSecond::default();
if let Ok(messages) =
bus_request(vec![BusRequest::GetCurrentThroughput]).await
@ -87,74 +87,74 @@ pub async fn current_throughput(
}
}
}
Json(result)
NoCache::new(MsgPack(result))
}
#[get("/api/cpu")]
pub fn cpu_usage(_auth: AuthGuard) -> Json<Vec<u32>> {
pub fn cpu_usage(_auth: AuthGuard) -> NoCache<MsgPack<Vec<u32>>> {
let usage: Vec<u32> = CPU_USAGE
.iter()
.take(NUM_CPUS.load(std::sync::atomic::Ordering::Relaxed))
.map(|cpu| cpu.load(std::sync::atomic::Ordering::Relaxed))
.collect();
Json(usage)
NoCache::new(MsgPack(usage))
}
#[get("/api/ram")]
pub fn ram_usage(_auth: AuthGuard) -> Json<Vec<u64>> {
pub fn ram_usage(_auth: AuthGuard) -> NoCache<MsgPack<Vec<u64>>> {
let ram_usage = RAM_USED.load(std::sync::atomic::Ordering::Relaxed);
let total_ram = TOTAL_RAM.load(std::sync::atomic::Ordering::Relaxed);
Json(vec![ram_usage, total_ram])
NoCache::new(MsgPack(vec![ram_usage, total_ram]))
}
#[get("/api/top_10_downloaders")]
pub async fn top_10_downloaders(_auth: AuthGuard) -> NoCache<Json<Vec<IpStatsWithPlan>>> {
pub async fn top_10_downloaders(_auth: AuthGuard) -> NoCache<MsgPack<Vec<IpStatsWithPlan>>> {
if let Ok(messages) = bus_request(vec![BusRequest::GetTopNDownloaders { start: 0, end: 10 }]).await
{
for msg in messages {
if let BusResponse::TopDownloaders(stats) = msg {
let result = stats.iter().map(|tt| tt.into()).collect();
return NoCache::new(Json(result));
return NoCache::new(MsgPack(result));
}
}
}
NoCache::new(Json(Vec::new()))
NoCache::new(MsgPack(Vec::new()))
}
#[get("/api/worst_10_rtt")]
pub async fn worst_10_rtt(_auth: AuthGuard) -> NoCache<Json<Vec<IpStatsWithPlan>>> {
pub async fn worst_10_rtt(_auth: AuthGuard) -> NoCache<MsgPack<Vec<IpStatsWithPlan>>> {
if let Ok(messages) = bus_request(vec![BusRequest::GetWorstRtt { start: 0, end: 10 }]).await
{
for msg in messages {
if let BusResponse::WorstRtt(stats) = msg {
let result = stats.iter().map(|tt| tt.into()).collect();
return NoCache::new(Json(result));
return NoCache::new(MsgPack(result));
}
}
}
NoCache::new(Json(Vec::new()))
NoCache::new(MsgPack(Vec::new()))
}
#[get("/api/rtt_histogram")]
pub async fn rtt_histogram(_auth: AuthGuard) -> NoCache<Json<Vec<u32>>> {
pub async fn rtt_histogram(_auth: AuthGuard) -> NoCache<MsgPack<Vec<u32>>> {
if let Ok(messages) = bus_request(vec![BusRequest::RttHistogram]).await
{
for msg in messages {
if let BusResponse::RttHistogram(stats) = msg {
let result = stats;
return NoCache::new(Json(result));
return NoCache::new(MsgPack(result));
}
}
}
NoCache::new(Json(Vec::new()))
NoCache::new(MsgPack(Vec::new()))
}
#[get("/api/host_counts")]
pub async fn host_counts(_auth: AuthGuard) -> NoCache<Json<(u32, u32)>> {
pub async fn host_counts(_auth: AuthGuard) -> NoCache<MsgPack<(u32, u32)>> {
let mut host_counts = (0, 0);
if let Ok(messages) = bus_request(vec![BusRequest::AllUnknownIps]).await {
for msg in messages {
@ -182,5 +182,5 @@ pub async fn host_counts(_auth: AuthGuard) -> NoCache<Json<(u32, u32)>> {
let n_devices = SHAPED_DEVICES.read().unwrap().devices.len();
let unknown = host_counts.0 - host_counts.1;
NoCache::new(Json((n_devices as u32, unknown)))
NoCache::new(MsgPack((n_devices as u32, unknown)))
}

View File

@ -9,7 +9,7 @@
<title>LibreQoS - Local Node Manager</title>
<script src="/lqos.js"></script>
<script src="/vendor/plotly-2.16.1.min.js"></script>
<script src="/vendor/jquery.min.js"></script>
<script src="/vendor/jquery.min.js"></script><script src="/vendor/msgpack.min.js"></script>
<script defer src="/vendor/bootstrap.bundle.min.js"></script>
</head>
<body class="bg-secondary">

View File

@ -9,7 +9,7 @@
<title>LibreQoS - Local Node Manager</title>
<script src="/lqos.js"></script>
<script src="/vendor/plotly-2.16.1.min.js"></script>
<script src="/vendor/jquery.min.js"></script>
<script src="/vendor/jquery.min.js"></script><script src="/vendor/msgpack.min.js"></script>
<script defer src="/vendor/bootstrap.bundle.min.js"></script>
</head>
<body class="bg-secondary">

View File

@ -9,7 +9,7 @@
<title>LibreQoS - Local Node Manager</title>
<script src="/lqos.js"></script>
<script src="/vendor/plotly-2.16.1.min.js"></script>
<script src="/vendor/jquery.min.js"></script>
<script src="/vendor/jquery.min.js"></script><script src="/vendor/msgpack.min.js"></script>
<script defer src="vendor/bootstrap.bundle.min.js"></script>
</head>
<body class="bg-secondary">

View File

@ -9,7 +9,7 @@
<title>LibreQoS - Local Node Manager</title>
<script src="/lqos.js"></script>
<script src="/vendor/plotly-2.16.1.min.js"></script>
<script src="/vendor/jquery.min.js"></script>
<script src="/vendor/jquery.min.js"></script><script src="/vendor/msgpack.min.js"></script>
<script defer src="/vendor/bootstrap.bundle.min.js"></script>
</head>
<body class="bg-secondary">

View File

@ -1,3 +1,41 @@
function msgPackGet(url, success) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer";
xhr.onload = () => {
var data = xhr.response;
let decoded = msgpack.decode(new Uint8Array(data));
success(decoded);
};
xhr.send(null);
}
const NetTrans = {
"name": 0,
"max_throughput": 1,
"current_throughput": 2,
"rtts": 3,
"parents": 4,
"immediate_parent": 5
}
const Circuit = {
"id" : 0,
"name" : 1,
"traffic": 2,
"limit": 3,
}
const IpStats = {
"ip_address": 0,
"bits_per_second": 1,
"packets_per_second": 2,
"median_tcp_rtt": 3,
"tc_handle": 4,
"circuit_id": 5,
"plan": 6,
}
function metaverse_color_ramp(n) {
if (n <= 9) {
return "#32b08c";
@ -65,7 +103,7 @@ function css_getclass(name) {
}
function updateHostCounts() {
$.get("/api/host_counts", (hc) => {
msgPackGet("/api/host_counts", (hc) => {
$("#shapedCount").text(hc[0]);
$("#unshapedCount").text(hc[1]);
setTimeout(updateHostCounts, 5000);

View File

@ -10,7 +10,7 @@
<title>LibreQoS - Local Node Manager</title>
<script src="/lqos.js"></script>
<script src="/vendor/plotly-2.16.1.min.js"></script>
<script src="/vendor/jquery.min.js"></script>
<script src="/vendor/jquery.min.js"></script><script src="/vendor/msgpack.min.js"></script>
<script defer src="/vendor/bootstrap.bundle.min.js"></script>
</head>
@ -171,15 +171,18 @@
var throughput = new MultiRingBuffer(300);
function updateCurrentThroughput() {
$.get("/api/current_throughput", (tp) => {
$("#ppsDown").text(scaleNumber(tp.packets_per_second[0]));
$("#ppsUp").text(scaleNumber(tp.packets_per_second[1]));
$("#bpsDown").text(scaleNumber(tp.bits_per_second[0]));
$("#bpsUp").text(scaleNumber(tp.bits_per_second[1]));
msgPackGet("/api/current_throughput", (tp) => {
const bits = 0;
const packets = 1;
const shaped = 2;
$("#ppsDown").text(scaleNumber(tp[packets][0]));
$("#ppsUp").text(scaleNumber(tp[packets][1]));
$("#bpsDown").text(scaleNumber(tp[bits][0]));
$("#bpsUp").text(scaleNumber(tp[bits][1]));
throughput.push("pps", tp.packets_per_second[0], tp.packets_per_second[1]);
throughput.push("total", tp.bits_per_second[0], tp.bits_per_second[1]);
throughput.push("shaped", tp.shaped_bits_per_second[0], tp.shaped_bits_per_second[1]);
throughput.push("pps", tp[1][0], tp[packets][1]);
throughput.push("total", tp[bits][0], tp[bits][1]);
throughput.push("shaped", tp[shaped][0], tp[shaped][1]);
throughput.plotTotalThroughput("tpGraph");
});
}
@ -187,17 +190,17 @@
var funnelData = new MultiRingBuffer(300);
function updateSiteFunnel() {
$.get("/api/network_tree_summary/", (data) => {
msgPackGet("/api/network_tree_summary/", (data) => {
let table = "<table class='table' style='font-size: 8pt;'>";
for (let i = 0; i < data.length; ++i) {
let name = data[i][1].name;
let name = data[i][1][NetTrans.name];
if (name.length > 20) {
name = name.substring(0, 20) + "...";
}
table += "<tr>";
table += "<td class='redact'>" + redactText(name) + "</td>";
table += "<td>" + scaleNumber(data[i][1].current_throughput[0] * 8) + "</td>";
table += "<td>" + scaleNumber(data[i][1].current_throughput[1] * 8) + "</td>";
table += "<td>" + scaleNumber(data[i][1][NetTrans.current_throughput][0] * 8) + "</td>";
table += "<td>" + scaleNumber(data[i][1][NetTrans.current_throughput][1] * 8) + "</td>";
table += "</tr>";
}
table += "</table>";
@ -206,7 +209,7 @@
}
function updateCpu() {
$.get("/api/cpu", (cpu) => {
msgPackGet("/api/cpu", (cpu) => {
let graph = document.getElementById("cpu");
let x = [];
let y = [];
@ -227,7 +230,7 @@
}
function updateRam() {
$.get("/api/ram", (ram) => {
msgPackGet("/api/ram", (ram) => {
let graph = document.getElementById("ram");
let data = [{
values: [ram[0], ram[1] - ram[0]],
@ -242,18 +245,18 @@
let html = "<table class='table'>";
html += "<thead><th>IP Address</th><th>DL ⬇️</th><th>UL ⬆️</th><th>RTT (ms)</th><th>Shaped</th></thead>";
for (let i = 0; i < tt.length; i++) {
let color = color_ramp(tt[i].median_tcp_rtt);
let color = color_ramp(tt[i][IpStats.median_tcp_rtt]);
html += "<tr style='background-color: " + color + "'>";
if (tt[i].circuit_id != "") {
html += "<td><a class='redact' href='/circuit_queue?id=" + encodeURI(tt[i].circuit_id) + "'>" + redactText(tt[i].ip_address) + "</td>";
if (tt[i][IpStats.circuit_id] != "") {
html += "<td><a class='redact' href='/circuit_queue?id=" + encodeURI(tt[i][IpStats.circuit_id]) + "'>" + redactText(tt[i][IpStats.ip_address]) + "</td>";
} else {
html += "<td><span class='redact'>" + redactText(tt[i].ip_address) + "</span></td>";
html += "<td><span class='redact'>" + redactText(tt[i][IpStats.ip_address]) + "</span></td>";
}
html += "<td>" + scaleNumber(tt[i].bits_per_second[0]) + "</td>";
html += "<td>" + scaleNumber(tt[i].bits_per_second[1]) + "</td>";
html += "<td>" + tt[i].median_tcp_rtt.toFixed(2) + "</td>";
html += "<td>" + scaleNumber(tt[i][IpStats.bits_per_second][0]) + "</td>";
html += "<td>" + scaleNumber(tt[i][IpStats.bits_per_second][1]) + "</td>";
html += "<td>" + tt[i][IpStats.median_tcp_rtt].toFixed(2) + "</td>";
if (tt[i].tc_handle != 0) {
html += "<td><i class='fa fa-check-circle'></i> (" + tt[i].plan[0] + "/" + tt[i].plan[1] + ")</td>";
html += "<td><i class='fa fa-check-circle'></i> (" + tt[i][IpStats.plan][0] + "/" + tt[i][IpStats.plan][1] + ")</td>";
} else {
//html += "<td><a class='btn btn-small btn-success' href='/shaped-add?ip=" + tt[i].ip_address + "'>Add Shaper</a></td>";
html += "<td>Not Shaped</td>"
@ -265,13 +268,13 @@
}
function updateTop10() {
$.get("/api/top_10_downloaders", (tt) => {
msgPackGet("/api/top_10_downloaders", (tt) => {
updateNTable('#top10dl', tt);
});
}
function updateWorst10() {
$.get("/api/worst_10_rtt", (tt) => {
msgPackGet("/api/worst_10_rtt", (tt) => {
updateNTable('#worstRtt', tt);
});
}
@ -279,7 +282,7 @@
var rttGraph = new RttHistogram();
function updateHistogram() {
$.get("/api/rtt_histogram", (rtt) => {
msgPackGet("/api/rtt_histogram", (rtt) => {
rttGraph.clear();
for (let i = 0; i < rtt.length; i++) {
rttGraph.pushBand(i, rtt[i]);

View File

@ -9,7 +9,7 @@
<title>LibreQoS - Local Node Manager</title>
<script src="/lqos.js"></script>
<script src="/vendor/plotly-2.16.1.min.js"></script>
<script src="/vendor/jquery.min.js"></script>
<script src="/vendor/jquery.min.js"></script><script src="/vendor/msgpack.min.js"></script>
<script defer src="/vendor/bootstrap.bundle.min.js"></script>
</head>
<body class="bg-secondary">

View File

@ -9,7 +9,7 @@
<title>LibreQoS - Local Node Manager</title>
<script src="/lqos.js"></script>
<script src="/vendor/plotly-2.16.1.min.js"></script>
<script src="/vendor/jquery.min.js"></script>
<script src="/vendor/jquery.min.js"></script><script src="/vendor/msgpack.min.js"></script>
<script defer src="/vendor/bootstrap.bundle.min.js"></script>
</head>
<body class="bg-secondary">

View File

@ -10,7 +10,7 @@
<title>LibreQoS - Local Node Manager</title>
<script src="/lqos.js"></script>
<script src="/vendor/plotly-2.16.1.min.js"></script>
<script src="/vendor/jquery.min.js"></script>
<script src="/vendor/jquery.min.js"></script><script src="/vendor/msgpack.min.js"></script>
<script defer src="/vendor/bootstrap.bundle.min.js"></script>
</head>
@ -30,7 +30,6 @@
<li class="nav-item">
<a class="nav-link" aria-current="page" href="/"><i class="fa fa-home"></i> Dashboard</a>
</li>
<li class="nav-item" id="currentLogin"></li>
<li class="nav-item">
<a class="nav-link active" href="/tree?parent=0"><i class="fa fa-globe"></i> Tree</a>
</li>
@ -46,6 +45,7 @@
</div>
<ul class="navbar-nav ms-auto">
<li class="nav-item" id="currentLogin"></li>
<li class="nav-item">
<a class="nav-link" href="#" id="startTest"><i class="fa fa-flag-checkered"></i> Run Bandwidth
Test</a>
@ -143,26 +143,26 @@
}
function getClients(rootName) {
$.get("/api/tree_clients/" + encodeURI(rootName), (data) => {
msgPackGet("/api/tree_clients/" + encodeURI(rootName), (data) => {
let tbl = "<table class='table table-striped'>";
tbl += "<thead><th>Circuit</th><th>Limit</th><th>⬇️ DL</th><th>⬆️ UL</th></thead>";
for (let i = 0; i < data.length; ++i) {
let nodeDL = scaleNumber(data[i].limit[0] * 1000000);
let nodeUL = scaleNumber(data[i].limit[1] * 1000000);
let nodeDL = scaleNumber(data[i][Circuit.limit][0] * 1000000);
let nodeUL = scaleNumber(data[i][Circuit.limit[1]] * 1000000);
if (nodeDL == "0") nodeDL = "Unlimited";
if (nodeUL == "0") nodeUL = "Unlimited";
tbl += "<tr>";
let displayName = data[i].name;
let displayName = data[i][Circuit.name];
if (displayName.length > 30) displayName = displayName.substring(0, 30) + "...";
tbl += "<td class='redact'><a href='/circuit_queue?id=" + encodeURI(data[i].id) + "'>" + redactText(displayName) + "</a></td>";
tbl += "<td class='redact'><a href='/circuit_queue?id=" + encodeURI(data[i][Circuit.id]) + "'>" + redactText(displayName) + "</a></td>";
tbl += "<td>" + nodeDL + " / " + nodeUL + "</td>";
let upbg = bgColor(data[i].traffic[1], data[i].limit[1]);
let dnbg = bgColor(data[i].traffic[0], data[0].limit[1]);
tbl += "<td style='background-color: " + dnbg + "'>" + scaleNumber(data[i].traffic[0] * 8) + "</td>";
tbl += "<td style='background-color: " + upbg + "'>" + scaleNumber(data[i].traffic[1] * 8) + "</td>";
let upbg = bgColor(data[i][Circuit.traffic][1], data[i][Circuit.limit][1]);
let dnbg = bgColor(data[i][Circuit.traffic][0], data[0][Circuit.limit][1]);
tbl += "<td style='background-color: " + dnbg + "'>" + scaleNumber(data[i][Circuit.traffic][0] * 8) + "</td>";
tbl += "<td style='background-color: " + upbg + "'>" + scaleNumber(data[i][Circuit.traffic][1] * 8) + "</td>";
buffers.push(nodeName, data[i].traffic[0] * 8, data[i].traffic[1] * 8);
buffers.push(nodeName, data[i][Circuit.traffic][0] * 8, data[i][Circuit.traffic][1] * 8);
}
tbl += "</table>";
$("#clientList").html(tbl);
@ -172,15 +172,15 @@
let filled_root = false;
function getTree() {
$.get("/api/network_tree/" + node, (data) => {
msgPackGet("/api/network_tree/" + node, (data) => {
rtt_histo.clear();
//console.log(data);
// Setup "this node"
let rootName = data[0][1].name;
let rootName = data[0][1][NetTrans.name];
if (!filled_root) {
$("#nodeName").text(redactText(rootName));
let nodeDL = scaleNumber(data[0][1].max_throughput[0] * 1000000);
let nodeUL = scaleNumber(data[0][1].max_throughput[1] * 1000000);
let nodeDL = scaleNumber(data[0][1][NetTrans.max_throughput][0] * 1000000);
let nodeUL = scaleNumber(data[0][1][NetTrans.max_throughput][1] * 1000000);
if (nodeDL == "0") nodeDL = "Unlimited";
if (nodeUL == "0") nodeUL = "Unlimited";
$("#nodeDL").text(nodeDL);
@ -189,17 +189,16 @@
$.ajax({
type: "POST",
url: "/api/node_names",
data: JSON.stringify(data[0][1].parents),
data: JSON.stringify(data[0][1][NetTrans.parents]),
success: (nodeNames) => {
console.log(nodeNames);
let breadcrumbs = "<nav aria-label='breadcrumb'>";
breadcrumbs += "<ol class='breadcrumb'>";
for (let i=0; i<data[0][1].parents.length; ++i) {
let bcid = data[0][1].parents[i];
for (let i=0; i<data[0][1][NetTrans.parents].length; ++i) {
let bcid = data[0][1][NetTrans.parents][i];
if (bcid != node) {
let n = nodeNames.find(e => e[0] == data[0][1].parents[i])[1];
let n = nodeNames.find(e => e[0] == data[0][1][NetTrans.parents][i])[1];
breadcrumbs += "<li class='breadcrumb-item redact'>";
breadcrumbs += "<a href='/tree?parent=" + data[0][1].parents[i] + "'>";
breadcrumbs += "<a href='/tree?parent=" + data[0][1][NetTrans.parents][i] + "'>";
breadcrumbs += redactText(n);
breadcrumbs += "</a></li>";
}
@ -218,38 +217,38 @@
getClients(rootName);
// Throughput graph
buffers.push(rootName, data[0][1].current_throughput[0] * 8, data[0][1].current_throughput[1] * 8);
buffers.push(rootName, data[0][1][NetTrans.current_throughput][0] * 8, data[0][1][NetTrans.current_throughput][1] * 8);
// Build the table & update node buffers
let tbl = "<table class='table table-striped'>";
tbl += "<thead><th>Site</th><th>Limit</th><th>⬇️ DL</th><th>⬆️ UL</th><th>RTT Latency</th></thead>";
for (let i = 1; i < data.length; ++i) {
let nodeName = data[i][1].name;
let nodeName = data[i][1][NetTrans.name];
buffers.push(nodeName, data[i][1].current_throughput[0] * 8, data[i][1].current_throughput[1] * 8);
buffers.push(nodeName, data[i][1][NetTrans.current_throughput][0] * 8, data[i][1][NetTrans.current_throughput][1] * 8);
tbl += "<tr>";
tbl += "<td class='redact'><a href='/tree?parent=" + encodeURI(data[i][0]) + "'>" + redactText(nodeName) + "</a></td>";
if (data[i][1].max_throughput[0] == 0 && data[i][1].max_throughput[1] == 0) {
if (data[i][1][NetTrans.max_throughput][0] == 0 && data[i][1][NetTrans.max_throughput][1] == 0) {
tbl += "<td>No Limit</td>";
} else {
let down = scaleNumber(data[i][1].max_throughput[0] * 1000000);
let up = scaleNumber(data[i][1].max_throughput[1] * 1000000);
let down = scaleNumber(data[i][1][NetTrans.max_throughput][0] * 1000000);
let up = scaleNumber(data[i][1][NetTrans.max_throughput][1] * 1000000);
tbl += "<td>" + down + " / " + up + "</td>";
}
let down = scaleNumber(data[i][1].current_throughput[0] * 8);
let up = scaleNumber(data[i][1].current_throughput[1] * 8);
let dbg = bgColor(data[i][1].current_throughput[0], data[i][1].max_throughput[0]);
let ubg = bgColor(data[i][1].current_throughput[0], data[i][1].max_throughput[0]);
let down = scaleNumber(data[i][1][NetTrans.current_throughput][0] * 8);
let up = scaleNumber(data[i][1][NetTrans.current_throughput][1] * 8);
let dbg = bgColor(data[i][1][NetTrans.current_throughput][0], data[i][1][NetTrans.max_throughput][0]);
let ubg = bgColor(data[i][1][NetTrans.current_throughput][0], data[i][1][NetTrans.max_throughput][0]);
tbl += "<td style='background-color: " + dbg + "'>" + down + "</td>";
tbl += "<td style='background-color: " + ubg + "'>" + up + "</td>";
let rtt = "-";
if (data[i][1].rtts.length > 0) {
if (data[i][1][NetTrans.rtts].length > 0) {
let sum = 0;
for (let j = 0; j < data[i][1].rtts.length; ++j) {
sum += data[i][1].rtts[j];
for (let j = 0; j < data[i][1][NetTrans.rtts].length; ++j) {
sum += data[i][1][NetTrans.rtts][j];
}
sum /= data[i][1].rtts.length;
sum /= data[i][1][NetTrans.rtts].length;
rtt = sum.toFixed(2) + " ms";
rtt_histo.push(sum);
}

View File

@ -9,7 +9,7 @@
<title>LibreQoS - Local Node Manager</title>
<script src="/lqos.js"></script>
<script src="/vendor/plotly-2.16.1.min.js"></script>
<script src="/vendor/jquery.min.js"></script>
<script src="/vendor/jquery.min.js"></script><script src="/vendor/msgpack.min.js"></script>
<script defer src="/vendor/bootstrap.bundle.min.js"></script>
</head>
<body class="bg-secondary">

File diff suppressed because one or more lines are too long