mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
Add a table helper type to make it easier to display data. Migrate the flows view to the new system.
This commit is contained in:
parent
205066b54d
commit
2cc5973ce7
@ -1,4 +1,5 @@
|
||||
mod stats_ringbuffer;
|
||||
mod table_helper;
|
||||
mod cpu;
|
||||
pub use cpu::cpu_display;
|
||||
mod network_sparkline;
|
||||
|
67
src/rust/lqtop/src/widgets/table_helper.rs
Normal file
67
src/rust/lqtop/src/widgets/table_helper.rs
Normal file
@ -0,0 +1,67 @@
|
||||
use ratatui::{style::{Color, Style}, text::Text, widgets::{Block, Borders, Cell, Row, Table}};
|
||||
|
||||
/// A helper for building Ratatui tables
|
||||
pub struct TableHelper<const N_COLS: usize> {
|
||||
headers: [String; N_COLS],
|
||||
rows: Vec<[String; N_COLS]>,
|
||||
}
|
||||
|
||||
impl <const N: usize> TableHelper<N> {
|
||||
pub fn new<S: ToString>(raw_headers: [S; N]) -> Self {
|
||||
const ARRAY_REPEAT_VALUE: String = String::new();
|
||||
let mut headers = [ARRAY_REPEAT_VALUE; N];
|
||||
for i in 0..N {
|
||||
headers[i] = raw_headers[i].to_string();
|
||||
}
|
||||
|
||||
let headers = headers.try_into().unwrap();
|
||||
Self {
|
||||
headers,
|
||||
rows: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_row(&mut self, row: [String; N]) {
|
||||
self.rows.push(row);
|
||||
}
|
||||
|
||||
pub fn to_table(&self) -> Table {
|
||||
let header_cells: Vec<_> = self.headers.
|
||||
iter()
|
||||
.map(|h| Cell::from(Text::from(h.clone())))
|
||||
.collect();
|
||||
|
||||
let rows: Vec<_> = self.rows
|
||||
.iter()
|
||||
.map(|row| {
|
||||
let cells = row.iter()
|
||||
.map(|cell| Cell::from(Text::from(cell.clone())))
|
||||
.collect::<Vec<Cell>>();
|
||||
Row::new(cells)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut widths = [0u16; N];
|
||||
for (i, heading) in self.headers.iter().enumerate() {
|
||||
widths[i] = (heading.len() + 2) as u16;
|
||||
}
|
||||
for row in self.rows.iter() {
|
||||
for (j, cell) in row.iter().enumerate() {
|
||||
if cell.len() + 2 > widths[j] as usize {
|
||||
widths[j] = (cell.len() + 2) as u16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Table::new(rows, widths)
|
||||
.header(Row::new(header_cells).style(Style::default().fg(Color::White).bg(Color::Blue)))
|
||||
}
|
||||
|
||||
pub fn to_block(&self) -> Table {
|
||||
let block = Block::default()
|
||||
//.title("Top Downloaders")
|
||||
.borders(Borders::NONE)
|
||||
.style(Style::default().fg(Color::Green));
|
||||
self.to_table().block(block)
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
use super::TopWidget;
|
||||
use super::{table_helper::TableHelper, TopWidget};
|
||||
use lqos_bus::{BusResponse, FlowbeeSummaryData};
|
||||
use lqos_utils::packet_scale::scale_bits;
|
||||
use ratatui::{prelude::*, widgets::*};
|
||||
use ratatui::prelude::*;
|
||||
|
||||
pub struct TopFlows {
|
||||
bus_link: tokio::sync::mpsc::Sender<crate::bus::BusMessage>,
|
||||
@ -37,52 +37,29 @@ impl TopWidget for TopFlows {
|
||||
}
|
||||
|
||||
fn render_to_frame(&mut self, frame: &mut Frame) {
|
||||
let block = Block::default()
|
||||
//.title("Top Downloaders")
|
||||
.borders(Borders::NONE)
|
||||
.style(Style::default().fg(Color::Green));
|
||||
|
||||
let mut rows = Vec::new();
|
||||
|
||||
let mut t = TableHelper::new([
|
||||
"Src IP",
|
||||
"Dst IP",
|
||||
"Type",
|
||||
"Upload",
|
||||
"Download",
|
||||
"Retransmits",
|
||||
"RTT (ms)",
|
||||
"ASN",
|
||||
]);
|
||||
for flow in self.flows.iter() {
|
||||
rows.push(
|
||||
Row::new(vec![
|
||||
Cell::from(Text::from(flow.local_ip.to_string())),
|
||||
Cell::from(Text::from(flow.remote_ip.to_string())),
|
||||
Cell::from(Text::from(flow.analysis.to_string())),
|
||||
Cell::from(Text::from(scale_bits(flow.bytes_sent[0]))),
|
||||
Cell::from(Text::from(scale_bits(flow.bytes_sent[1]))),
|
||||
Cell::from(Text::from(format!(
|
||||
"{}/{}",
|
||||
flow.tcp_retransmits[0], flow.tcp_retransmits[1]
|
||||
))),
|
||||
Cell::from(Text::from(format!(
|
||||
"{:.1}/{:.1}",
|
||||
flow.rtt_nanos[0] as f64 / 1000000.,
|
||||
flow.tcp_retransmits[1] as f64 / 1000000.
|
||||
))),
|
||||
Cell::from(Text::from(flow.remote_asn_name.to_string())),
|
||||
])
|
||||
.style(style::Style::default().fg(Color::White)),
|
||||
);
|
||||
t.add_row([
|
||||
flow.local_ip.to_string(),
|
||||
flow.remote_ip.to_string(),
|
||||
flow.analysis.to_string(),
|
||||
scale_bits(flow.bytes_sent[0]),
|
||||
scale_bits(flow.bytes_sent[1]),
|
||||
format!("{}/{}", flow.tcp_retransmits[0], flow.tcp_retransmits[1]),
|
||||
format!("{:.1}/{:.1}", flow.rtt_nanos[0] as f64 / 1000000., flow.tcp_retransmits[1] as f64 / 1000000.),
|
||||
flow.remote_asn_name.to_string(),
|
||||
]);
|
||||
}
|
||||
|
||||
let header = Row::new(vec![
|
||||
Cell::from(Text::from("Src IP")),
|
||||
Cell::from(Text::from("Dst IP")),
|
||||
Cell::from(Text::from("Type")),
|
||||
Cell::from(Text::from("Upload")),
|
||||
Cell::from(Text::from("Download")),
|
||||
Cell::from(Text::from("Retransmits")),
|
||||
Cell::from(Text::from("RTT (ms)")),
|
||||
Cell::from(Text::from("ASN")),
|
||||
])
|
||||
.style(style::Style::default().fg(Color::Yellow).bg(Color::Blue));
|
||||
|
||||
let table = Table::new(rows, [15, 15, 20, 14, 14, 10, 15, 20])
|
||||
.block(block)
|
||||
.header(header);
|
||||
|
||||
let table = t.to_block();
|
||||
frame.render_widget(table, self.size);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user