Display worst TCP retransmits as a button in the UI.

This commit is contained in:
Herbert Wolverson 2024-03-19 15:39:58 -05:00
parent a4c8093401
commit 280447f79d
7 changed files with 126 additions and 2 deletions

View File

@ -30,6 +30,14 @@ pub enum BusRequest {
end: u32,
},
/// Retrieves the TopN hosts with the worst Retransmits, sorted by Retransmits descending.
GetWorstRetransmits {
/// First row to retrieve (usually 0 unless you are paging)
start: u32,
/// Last row to retrieve (10 for top-10 starting at 0)
end: u32,
},
/// Retrieves the TopN hosts with the best RTT, sorted by RTT descending.
GetBestRtt {
/// First row to retrieve (usually 0 unless you are paging)

View File

@ -43,6 +43,9 @@ pub enum BusResponse {
/// Provides the worst N RTT scores, sorted in descending order.
WorstRtt(Vec<IpStats>),
/// Provides the worst N Retransmit scores, sorted in descending order.
WorstRetransmits(Vec<IpStats>),
/// Provides the best N RTT scores, sorted in descending order.
BestRtt(Vec<IpStats>),

View File

@ -59,6 +59,7 @@ fn rocket() -> _ {
tracker::ram_usage,
tracker::top_10_downloaders,
tracker::worst_10_rtt,
tracker::worst_10_tcp,
tracker::rtt_histogram,
tracker::host_counts,
shaped_devices::all_shaped_devices,

View File

@ -133,6 +133,21 @@ pub async fn worst_10_rtt(_auth: AuthGuard) -> NoCache<MsgPack<Vec<IpStatsWithPl
NoCache::new(MsgPack(Vec::new()))
}
#[get("/api/worst_10_tcp")]
pub async fn worst_10_tcp(_auth: AuthGuard) -> NoCache<MsgPack<Vec<IpStatsWithPlan>>> {
if let Ok(messages) = bus_request(vec![BusRequest::GetWorstRetransmits { start: 0, end: 10 }]).await
{
for msg in messages {
if let BusResponse::WorstRetransmits(stats) = msg {
let result = stats.iter().map(|tt| tt.into()).collect();
return NoCache::new(MsgPack(result));
}
}
}
NoCache::new(MsgPack(Vec::new()))
}
#[get("/api/rtt_histogram")]
pub async fn rtt_histogram(_auth: AuthGuard) -> NoCache<MsgPack<Vec<u32>>> {
if let Ok(messages) = bus_request(vec![BusRequest::RttHistogram]).await

View File

@ -164,8 +164,12 @@
<div class="col-sm-6">
<div class="card bg-light">
<div class="card-body">
<h5 class="card-title"><i class='fa fa-exclamation'></i> Worst 10 RTT</h5>
<h5 class="card-title"><i class='fa fa-exclamation'></i> Worst 10
<button id="btnworstRtt" class="btn btn-small btn-success" href="/top10" onclick="showWorstRtt()">RTT</button>
<button id="btnworstTcp" class="btn btn-small btn-primary" href="/top10" onclick="showWorstTcp()">TCP Retransmits</button>
</h5>
<div id="worstRtt"></div>
<div id="worstTcp" style="display: none;"></div>
</div>
</div>
</div>
@ -319,6 +323,13 @@
});
}
function updateWorstTcp() {
msgPackGet("/api/worst_10_tcp", (tt) => {
//console.log(tt);
updateNTable('#worstTcp', tt);
});
}
function updateTop10Flows() {
$.get("/api/flows/top/10/rate", data => {
let html = "<table class='table table-striped' style='font-size: 8pt'>";
@ -436,6 +447,29 @@
}
let top10view = "circuits";
let worst10view = "rtt";
function changeBottom10(visible) {
const bottom10 = ["worstRtt", "worstTcp"];
for (let i=0; i<bottom10.length; i++) {
$("#" + bottom10[i]).hide();
$("#btn" + bottom10[i]).removeClass("btn-success");
$("#btn" + bottom10[i]).addClass("btn-primary");
}
$("#" + visible).show();
$("#btn" + visible).removeClass("btn-primary");
$("#btn" + visible).addClass("btn-success");
}
function showWorstRtt() {
changeBottom10("worstRtt");
worst10view = "rtt";
}
function showWorstTcp() {
changeBottom10("worstTcp");
worst10view = "tcp";
}
function changeTop10(visible) {
const top10 = ["top10dl", "top10flows", "top10ep", "top10eth", "top10pro"];
@ -495,7 +529,11 @@
if (tickCount % 5 == 0) {
updateHistogram();
updateWorst10();
if (worst10view == "rtt") {
updateWorst10();
} else if (worst10view == "tcp") {
updateWorstTcp();
}
if (top10view == "circuits") {
updateTop10();
} else if (top10view == "flows") {

View File

@ -151,6 +151,9 @@ fn handle_bus_requests(
BusRequest::GetWorstRtt { start, end } => {
throughput_tracker::worst_n(*start, *end)
}
BusRequest::GetWorstRetransmits { start, end } => {
throughput_tracker::worst_n_retransmits(*start, *end)
}
BusRequest::GetBestRtt { start, end } => {
throughput_tracker::best_n(*start, *end)
}

View File

@ -307,6 +307,62 @@ pub fn worst_n(start: u32, end: u32) -> BusResponse {
BusResponse::WorstRtt(result)
}
pub fn worst_n_retransmits(start: u32, end: u32) -> BusResponse {
let mut full_list: Vec<TopList> = {
let tp_cycle = THROUGHPUT_TRACKER
.cycle
.load(std::sync::atomic::Ordering::Relaxed);
THROUGHPUT_TRACKER
.raw_data
.iter()
.filter(|v| !v.key().as_ip().is_loopback())
.filter(|d| retire_check(tp_cycle, d.most_recent_cycle))
.filter(|te| te.median_latency().is_some())
.map(|te| {
(
*te.key(),
te.bytes_per_second,
te.packets_per_second,
te.median_latency().unwrap_or(0.0),
te.tc_handle,
te.circuit_id.as_ref().unwrap_or(&String::new()).clone(),
te.tcp_retransmits,
)
})
.collect()
};
full_list.sort_by(|a, b| {
let total_a = a.6 .0 + a.6 .1;
let total_b = b.6 .0 + b.6 .1;
total_b.cmp(&total_a)
});
let result = full_list
.iter()
.skip(start as usize)
.take((end as usize) - (start as usize))
.map(
|(
ip,
(bytes_dn, bytes_up),
(packets_dn, packets_up),
median_rtt,
tc_handle,
circuit_id,
tcp_retransmits,
)| IpStats {
ip_address: ip.as_ip().to_string(),
circuit_id: circuit_id.clone(),
bits_per_second: (bytes_dn * 8, bytes_up * 8),
packets_per_second: (*packets_dn, *packets_up),
median_tcp_rtt: *median_rtt,
tc_handle: *tc_handle,
tcp_retransmits: *tcp_retransmits,
},
)
.collect();
BusResponse::WorstRetransmits(result)
}
pub fn best_n(start: u32, end: u32) -> BusResponse {
let mut full_list: Vec<TopList> = {
let tp_cycle = THROUGHPUT_TRACKER