mirror of
https://github.com/LibreQoE/LibreQoS.git
synced 2025-02-25 18:55:32 -06:00
Format
This commit is contained in:
parent
6c7c8d94c9
commit
aed4e042e7
@ -1,15 +1,14 @@
|
||||
//! Provides a sysinfo link for CPU and RAM tracking
|
||||
|
||||
use crate::ui_base::SHOULD_EXIT;
|
||||
use std::sync::atomic::Ordering;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::atomic::{AtomicU32, AtomicU64, AtomicUsize};
|
||||
|
||||
const MAX_CPUS_COUNTED: usize = 128;
|
||||
|
||||
/// Stores overall CPU usage
|
||||
pub static CPU_USAGE: Lazy<[AtomicU32; MAX_CPUS_COUNTED]> =
|
||||
Lazy::new(build_empty_cpu_list);
|
||||
pub static CPU_USAGE: Lazy<[AtomicU32; MAX_CPUS_COUNTED]> = Lazy::new(build_empty_cpu_list);
|
||||
|
||||
/// Total number of CPUs detected
|
||||
pub static NUM_CPUS: AtomicUsize = AtomicUsize::new(0);
|
||||
@ -50,8 +49,8 @@ pub async fn gather_sysinfo() {
|
||||
fn build_empty_cpu_list() -> [AtomicU32; MAX_CPUS_COUNTED] {
|
||||
let mut temp = Vec::with_capacity(MAX_CPUS_COUNTED);
|
||||
for _ in 0..MAX_CPUS_COUNTED {
|
||||
temp.push(AtomicU32::new(0));
|
||||
temp.push(AtomicU32::new(0));
|
||||
}
|
||||
temp.try_into().expect("This should never happen, sizes are constant.")
|
||||
}
|
||||
|
||||
temp.try_into()
|
||||
.expect("This should never happen, sizes are constant.")
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
//! Handles the communication loop with lqosd.
|
||||
|
||||
use std::sync::atomic::Ordering;
|
||||
use lqos_bus::{BusClient, BusRequest, BusResponse};
|
||||
use anyhow::{bail, Result};
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use crate::ui_base::SHOULD_EXIT;
|
||||
use anyhow::{bail, Result};
|
||||
use lqos_bus::{BusClient, BusRequest, BusResponse};
|
||||
use std::sync::atomic::Ordering;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
pub mod cpu_ram;
|
||||
pub mod throughput;
|
||||
|
||||
@ -22,7 +22,7 @@ pub async fn bus_loop() -> Sender<BusCommand> {
|
||||
let (tx, rx) = tokio::sync::mpsc::channel::<BusCommand>(100);
|
||||
|
||||
tokio::spawn(cpu_ram::gather_sysinfo());
|
||||
tokio::spawn(main_loop_wrapper(rx));
|
||||
tokio::spawn(main_loop_wrapper(rx));
|
||||
|
||||
tx
|
||||
}
|
||||
@ -57,7 +57,7 @@ async fn main_loop(mut rx: Receiver<BusCommand>) -> Result<()> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Perform actual bus collection
|
||||
let mut commands: Vec<BusRequest> = Vec::new();
|
||||
|
||||
@ -68,7 +68,7 @@ async fn main_loop(mut rx: Receiver<BusCommand>) -> Result<()> {
|
||||
// Send the requests and process replies
|
||||
for response in bus_client.request(commands).await? {
|
||||
match response {
|
||||
BusResponse::CurrentThroughput{..} => throughput::throughput(&response).await,
|
||||
BusResponse::CurrentThroughput { .. } => throughput::throughput(&response).await,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -82,4 +82,4 @@ async fn main_loop(mut rx: Receiver<BusCommand>) -> Result<()> {
|
||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
use std::sync::Mutex;
|
||||
use lqos_bus::BusResponse;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub static THROUGHPUT_RING: Lazy<Mutex<ThroughputRingbuffer>> = Lazy::new(|| Mutex::new(ThroughputRingbuffer::default()));
|
||||
pub static THROUGHPUT_RING: Lazy<Mutex<ThroughputRingbuffer>> =
|
||||
Lazy::new(|| Mutex::new(ThroughputRingbuffer::default()));
|
||||
const RINGBUFFER_SIZE: usize = 80;
|
||||
pub static CURRENT_THROUGHPUT: Lazy<Mutex<CurrentThroughput>> = Lazy::new(|| Mutex::new(CurrentThroughput::default()));
|
||||
pub static CURRENT_THROUGHPUT: Lazy<Mutex<CurrentThroughput>> =
|
||||
Lazy::new(|| Mutex::new(CurrentThroughput::default()));
|
||||
|
||||
#[derive(Default, Copy, Clone)]
|
||||
pub struct CurrentThroughput {
|
||||
@ -109,6 +111,6 @@ pub async fn throughput(response: &BusResponse) {
|
||||
let mut current = CURRENT_THROUGHPUT.lock().unwrap();
|
||||
current.bits_per_second = *bits_per_second;
|
||||
current.packets_per_second = *packets_per_second;
|
||||
current.shaped_bits_per_second = *shaped_bits_per_second;
|
||||
current.shaped_bits_per_second = *shaped_bits_per_second;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
mod ui_base;
|
||||
mod top_level_ui;
|
||||
mod bus;
|
||||
mod top_level_ui;
|
||||
mod ui_base;
|
||||
use anyhow::Result;
|
||||
use ui_base::UiBase;
|
||||
pub mod widgets;
|
||||
@ -12,9 +12,9 @@ async fn main() -> Result<()> {
|
||||
let bus_commander = bus::bus_loop().await;
|
||||
|
||||
// Initialize the UI
|
||||
let mut ui = UiBase::new(bus_commander.clone())?;
|
||||
let mut ui = UiBase::new(bus_commander.clone())?;
|
||||
ui.event_loop().await?;
|
||||
|
||||
// Return OK
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -5,29 +5,38 @@
|
||||
//! It's designed to be the manager from which specific UI
|
||||
//! components are managed.
|
||||
|
||||
use crate::{bus::BusCommand, widgets::*};
|
||||
use lqos_bus::BusClient;
|
||||
use ratatui::prelude::*;
|
||||
use std::io::Stdout;
|
||||
use crate::widgets::*;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
||||
pub struct TopUi {
|
||||
show_cpus: bool,
|
||||
show_throughput_sparkline: bool,
|
||||
main_widget: MainWidget,
|
||||
}
|
||||
|
||||
impl TopUi {
|
||||
/// Create a new TopUi instance. This will initialize the UI framework.
|
||||
pub fn new() -> Self {
|
||||
TopUi {
|
||||
TopUi {
|
||||
show_cpus: true,
|
||||
show_throughput_sparkline: true,
|
||||
main_widget: MainWidget::Hosts,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_keypress(&mut self, key: char) {
|
||||
pub fn handle_keypress(&mut self, key: char, commander: Sender<BusCommand>) {
|
||||
// Handle Mode Switches
|
||||
match key {
|
||||
'c' => self.show_cpus = !self.show_cpus,
|
||||
'n' => self.show_throughput_sparkline = !self.show_throughput_sparkline,
|
||||
'n' => {
|
||||
self.show_throughput_sparkline = !self.show_throughput_sparkline;
|
||||
commander.send(BusCommand::CollectTotalThroughput(
|
||||
self.show_throughput_sparkline,
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -48,7 +57,7 @@ impl TopUi {
|
||||
let cpu_region = if self.show_cpus {
|
||||
constraints.push(Constraint::Length(1));
|
||||
next_region += 1;
|
||||
next_region-1
|
||||
next_region - 1
|
||||
} else {
|
||||
next_region
|
||||
};
|
||||
@ -56,7 +65,7 @@ impl TopUi {
|
||||
let network_spark_region = if self.show_throughput_sparkline {
|
||||
constraints.push(Constraint::Length(10));
|
||||
next_region += 1;
|
||||
next_region-1
|
||||
next_region - 1
|
||||
} else {
|
||||
next_region
|
||||
};
|
||||
@ -67,10 +76,7 @@ impl TopUi {
|
||||
}
|
||||
constraints.push(Constraint::Fill(1));
|
||||
|
||||
let main_layout = Layout::new(
|
||||
Direction::Vertical,
|
||||
constraints
|
||||
).split(frame.size());
|
||||
let main_layout = Layout::new(Direction::Vertical, constraints).split(frame.size());
|
||||
|
||||
// Add Widgets
|
||||
if self.show_cpus {
|
||||
@ -81,5 +87,8 @@ impl TopUi {
|
||||
let render = nspark.render();
|
||||
frame.render_widget(render, main_layout[network_spark_region]);
|
||||
}
|
||||
|
||||
// And finally the main panel
|
||||
frame.render_widget(self.main_widget.render(), main_layout[next_region]);
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,10 @@ use crossterm::{
|
||||
ExecutableCommand,
|
||||
};
|
||||
use ratatui::{backend::CrosstermBackend, Terminal};
|
||||
use std::{io::stdout, sync::atomic::{AtomicBool, Ordering}};
|
||||
use std::{
|
||||
io::stdout,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
use tokio::{sync::mpsc::Sender, task::yield_now};
|
||||
|
||||
pub static SHOULD_EXIT: AtomicBool = AtomicBool::new(false);
|
||||
@ -66,7 +69,7 @@ impl UiBase {
|
||||
_ => None,
|
||||
};
|
||||
if let Some(c) = char {
|
||||
self.ui.handle_keypress(c);
|
||||
self.ui.handle_keypress(c, self.bus_commander.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,20 @@
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use ratatui::{style::{Color, Style}, text::Span, widgets::{Block, Borders, Widget}};
|
||||
use ratatui::{
|
||||
style::{Color, Style},
|
||||
text::Span,
|
||||
widgets::{Block, Borders, Widget},
|
||||
};
|
||||
|
||||
/// Used to display the CPU usage and RAM usage
|
||||
pub fn cpu_display() -> impl Widget {
|
||||
use crate::bus::cpu_ram::*;
|
||||
let num_cpus = NUM_CPUS.load(Ordering::Relaxed);
|
||||
let cpu_usage = CPU_USAGE.iter().take(num_cpus).map(|x| x.load(Ordering::Relaxed)).collect::<Vec<_>>();
|
||||
let cpu_usage = CPU_USAGE
|
||||
.iter()
|
||||
.take(num_cpus)
|
||||
.map(|x| x.load(Ordering::Relaxed))
|
||||
.collect::<Vec<_>>();
|
||||
let total_ram = TOTAL_RAM.load(Ordering::Relaxed);
|
||||
let used_ram = RAM_USED.load(Ordering::Relaxed);
|
||||
|
||||
@ -22,7 +30,10 @@ pub fn cpu_display() -> impl Widget {
|
||||
|
||||
let mut span_buf = vec![
|
||||
Span::styled(" [ RAM: ", Style::default().fg(Color::Green)),
|
||||
Span::styled(format!("{:.0}% ", ram_percent), Style::default().fg(ram_color)),
|
||||
Span::styled(
|
||||
format!("{:.0}% ", ram_percent),
|
||||
Style::default().fg(ram_color),
|
||||
),
|
||||
Span::styled("CPU: ", Style::default().fg(Color::Green)),
|
||||
];
|
||||
for cpu in cpu_usage {
|
||||
@ -33,9 +44,12 @@ pub fn cpu_display() -> impl Widget {
|
||||
} else {
|
||||
Color::Red
|
||||
};
|
||||
span_buf.push(Span::styled(format!("{}% ", cpu), Style::default().fg(color)));
|
||||
span_buf.push(Span::styled(
|
||||
format!("{}% ", cpu),
|
||||
Style::default().fg(color),
|
||||
));
|
||||
}
|
||||
span_buf.push(Span::styled(" ] ", Style::default().fg(Color::Green)));
|
||||
|
||||
Block::new().borders(Borders::TOP).title(span_buf)
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,15 @@
|
||||
mod cpu;
|
||||
pub use cpu::cpu_display;
|
||||
mod network_sparkline;
|
||||
pub use network_sparkline::*;
|
||||
pub use network_sparkline::*;
|
||||
use ratatui::widgets::Widget;
|
||||
|
||||
pub enum MainWidget {
|
||||
Hosts,
|
||||
}
|
||||
|
||||
impl MainWidget {
|
||||
pub fn render(&self) -> impl Widget + '_ {
|
||||
ratatui::widgets::Block::new()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user