mirror of
				https://github.com/ClementTsang/bottom.git
				synced 2025-10-31 19:24:37 +01:00 
			
		
		
		
	Reworked network again; will use this to change all widgets
This commit is contained in:
		
							parent
							
								
									fe99b99d0a
								
							
						
					
					
						commit
						13f6dfc529
					
				
							
								
								
									
										32
									
								
								src/app.rs
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								src/app.rs
									
									
									
									
									
								
							| @ -1,7 +1,10 @@ | ||||
| pub mod data_collection; | ||||
| use data_collection::{processes, temperature}; | ||||
| pub mod data_harvester; | ||||
| use data_harvester::{processes, temperature}; | ||||
| use std::time::Instant; | ||||
| 
 | ||||
| pub mod data_janitor; | ||||
| use data_janitor::*; | ||||
| 
 | ||||
| use crate::{canvas, constants, data_conversion::ConvertedProcessData, utils::error::Result}; | ||||
| 
 | ||||
| mod process_killer; | ||||
| @ -30,6 +33,23 @@ lazy_static! { | ||||
| 		regex::Regex::new(".*"); | ||||
| } | ||||
| 
 | ||||
| /// AppConfigFields is meant to cover basic fields that would normally be set
 | ||||
| /// by config files or launch options.  Don't need to be mutable (set and forget).
 | ||||
| pub struct AppConfigFields { | ||||
| 	pub update_rate_in_milliseconds: u64, | ||||
| 	pub temperature_type: temperature::TemperatureType, | ||||
| 	pub use_dot: bool, | ||||
| } | ||||
| 
 | ||||
| /// AppScrollWidgetState deals with fields for a scrollable app's current state.
 | ||||
| pub struct AppScrollWidgetState { | ||||
| 	pub widget_scroll_position: i64, | ||||
| } | ||||
| 
 | ||||
| /// AppSearchState only deals with the search's state.
 | ||||
| pub struct AppSearchState {} | ||||
| 
 | ||||
| // TODO: [OPT] Group like fields together... this is kinda gross to step through
 | ||||
| pub struct App { | ||||
| 	// Sorting
 | ||||
| 	pub process_sorting_type: processes::ProcessSorting, | ||||
| @ -49,7 +69,7 @@ pub struct App { | ||||
| 	pub update_rate_in_milliseconds: u64, | ||||
| 	pub show_average_cpu: bool, | ||||
| 	pub current_application_position: ApplicationPosition, | ||||
| 	pub data: data_collection::Data, | ||||
| 	pub data: data_harvester::Data, | ||||
| 	awaiting_second_char: bool, | ||||
| 	second_char: char, | ||||
| 	pub use_dot: bool, | ||||
| @ -63,12 +83,13 @@ pub struct App { | ||||
| 	last_key_press: Instant, | ||||
| 	pub canvas_data: canvas::CanvasData, | ||||
| 	enable_grouping: bool, | ||||
| 	enable_searching: bool, // TODO: [OPT] group together?
 | ||||
| 	enable_searching: bool, | ||||
| 	current_search_query: String, | ||||
| 	searching_pid: bool, | ||||
| 	pub use_simple: bool, | ||||
| 	current_regex: std::result::Result<regex::Regex, regex::Error>, | ||||
| 	current_cursor_position: usize, | ||||
| 	pub data_collection: DataCollection, | ||||
| } | ||||
| 
 | ||||
| impl App { | ||||
| @ -94,7 +115,7 @@ impl App { | ||||
| 			previous_disk_position: 0, | ||||
| 			previous_temp_position: 0, | ||||
| 			previous_cpu_table_position: 0, | ||||
| 			data: data_collection::Data::default(), | ||||
| 			data: data_harvester::Data::default(), | ||||
| 			awaiting_second_char: false, | ||||
| 			second_char: ' ', | ||||
| 			use_dot, | ||||
| @ -114,6 +135,7 @@ impl App { | ||||
| 			use_simple: false, | ||||
| 			current_regex: BASE_REGEX.clone(), //TODO: [OPT] seems like a thing we can switch to lifetimes to avoid cloning
 | ||||
| 			current_cursor_position: 0, | ||||
| 			data_collection: DataCollection::default(), | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -1,86 +0,0 @@ | ||||
| use futures::StreamExt; | ||||
| use heim::net; | ||||
| use heim::units::information::byte; | ||||
| use std::time::Instant; | ||||
| use sysinfo::{NetworkExt, System, SystemExt}; | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct NetworkJoinPoint { | ||||
| 	pub rx: f64, | ||||
| 	pub tx: f64, | ||||
| 	pub time_offset_milliseconds: f64, | ||||
| } | ||||
| 
 | ||||
| type NetworkDataGroup = (Instant, (NetworkData, Option<Vec<NetworkJoinPoint>>)); | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct NetworkStorage { | ||||
| 	pub data_points: Vec<NetworkDataGroup>, | ||||
| 	pub rx: u64, | ||||
| 	pub tx: u64, | ||||
| 	pub total_rx: u64, | ||||
| 	pub total_tx: u64, | ||||
| 	pub last_collection_time: Instant, | ||||
| } | ||||
| 
 | ||||
| impl Default for NetworkStorage { | ||||
| 	fn default() -> Self { | ||||
| 		NetworkStorage { | ||||
| 			data_points: Vec::default(), | ||||
| 			rx: 0, | ||||
| 			tx: 0, | ||||
| 			total_rx: 0, | ||||
| 			total_tx: 0, | ||||
| 			last_collection_time: Instant::now(), | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| impl NetworkStorage { | ||||
| 	pub fn first_run(&mut self) { | ||||
| 		self.data_points = Vec::default(); | ||||
| 		self.rx = 0; | ||||
| 		self.tx = 0; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| /// Note all values are in bytes...
 | ||||
| pub struct NetworkData { | ||||
| 	pub rx: u64, | ||||
| 	pub tx: u64, | ||||
| } | ||||
| 
 | ||||
| pub async fn get_network_data( | ||||
| 	sys: &System, prev_net_access_time: &Instant, prev_net_rx: &mut u64, prev_net_tx: &mut u64, | ||||
| 	curr_time: &Instant, | ||||
| ) -> NetworkData { | ||||
| 	// FIXME: [WIN] Track current total bytes... also is this accurate?
 | ||||
| 	if cfg!(target_os = "windows") { | ||||
| 		let network_data = sys.get_network(); | ||||
| 		NetworkData { | ||||
| 			rx: network_data.get_income(), | ||||
| 			tx: network_data.get_outcome(), | ||||
| 		} | ||||
| 	} else { | ||||
| 		let mut io_data = net::io_counters(); | ||||
| 		let mut net_rx: u64 = 0; | ||||
| 		let mut net_tx: u64 = 0; | ||||
| 
 | ||||
| 		while let Some(io) = io_data.next().await { | ||||
| 			if let Ok(io) = io { | ||||
| 				net_rx += io.bytes_recv().get::<byte>(); | ||||
| 				net_tx += io.bytes_sent().get::<byte>(); | ||||
| 			} | ||||
| 		} | ||||
| 		let elapsed_time = curr_time | ||||
| 			.duration_since(*prev_net_access_time) | ||||
| 			.as_secs_f64(); | ||||
| 
 | ||||
| 		let rx = ((net_rx - *prev_net_rx) as f64 / elapsed_time) as u64; | ||||
| 		let tx = ((net_tx - *prev_net_tx) as f64 / elapsed_time) as u64; | ||||
| 
 | ||||
| 		*prev_net_rx = net_rx; | ||||
| 		*prev_net_tx = net_tx; | ||||
| 		NetworkData { rx, tx } | ||||
| 	} | ||||
| } | ||||
| @ -23,39 +23,52 @@ fn push_if_valid<T: std::clone::Clone>(result: &Result<T>, vector_to_push: &mut | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug, Default)] | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct Data { | ||||
| 	pub list_of_cpu_packages: Vec<cpu::CPUPackage>, | ||||
| 	pub list_of_io: Vec<disks::IOPackage>, | ||||
| 	pub list_of_physical_io: Vec<disks::IOPackage>, | ||||
| 	pub memory: Vec<mem::MemData>, | ||||
| 	pub swap: Vec<mem::MemData>, | ||||
| 	pub list_of_temperature_sensor: Vec<temperature::TempData>, | ||||
| 	pub network: network::NetworkStorage, | ||||
| 	pub network: network::NetworkHarvest, | ||||
| 	pub list_of_processes: Vec<processes::ProcessData>, | ||||
| 	pub grouped_list_of_processes: Option<Vec<processes::ProcessData>>, | ||||
| 	pub list_of_disks: Vec<disks::DiskData>, | ||||
| 	pub last_collection_time: Instant, | ||||
| } | ||||
| 
 | ||||
| impl Default for Data { | ||||
| 	fn default() -> Self { | ||||
| 		Data { | ||||
| 			list_of_cpu_packages: Vec::default(), | ||||
| 			list_of_io: Vec::default(), | ||||
| 			memory: Vec::default(), | ||||
| 			swap: Vec::default(), | ||||
| 			list_of_temperature_sensor: Vec::default(), | ||||
| 			list_of_processes: Vec::default(), | ||||
| 			grouped_list_of_processes: None, | ||||
| 			list_of_disks: Vec::default(), | ||||
| 			network: network::NetworkHarvest::default(), | ||||
| 			last_collection_time: Instant::now(), | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| impl Data { | ||||
| 	pub fn first_run_cleanup(&mut self) { | ||||
| 		self.list_of_cpu_packages = Vec::new(); | ||||
| 		self.list_of_io = Vec::new(); | ||||
| 		self.list_of_physical_io = Vec::new(); | ||||
| 		self.memory = Vec::new(); | ||||
| 		self.swap = Vec::new(); | ||||
| 		self.list_of_temperature_sensor = Vec::new(); | ||||
| 		self.list_of_processes = Vec::new(); | ||||
| 		self.grouped_list_of_processes = None; | ||||
| 		self.list_of_disks = Vec::new(); | ||||
| 
 | ||||
| 		self.network.first_run(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub struct DataState { | ||||
| 	pub data: Data, | ||||
| 	first_run: bool, | ||||
| 	sys: System, | ||||
| 	stale_max_seconds: u64, | ||||
| 	prev_pid_stats: HashMap<String, (f64, Instant)>, | ||||
| @ -70,7 +83,6 @@ impl Default for DataState { | ||||
| 	fn default() -> Self { | ||||
| 		DataState { | ||||
| 			data: Data::default(), | ||||
| 			first_run: true, | ||||
| 			sys: System::new(), | ||||
| 			stale_max_seconds: constants::STALE_MAX_MILLISECONDS / 1000, | ||||
| 			prev_pid_stats: HashMap::new(), | ||||
| @ -108,57 +120,15 @@ impl DataState { | ||||
| 		let current_instant = std::time::Instant::now(); | ||||
| 
 | ||||
| 		// Network
 | ||||
| 		let new_network_data = network::get_network_data( | ||||
| 		self.data.network = network::get_network_data( | ||||
| 			&self.sys, | ||||
| 			&self.data.network.last_collection_time, | ||||
| 			&self.data.last_collection_time, | ||||
| 			&mut self.data.network.total_rx, | ||||
| 			&mut self.data.network.total_tx, | ||||
| 			¤t_instant, | ||||
| 		) | ||||
| 		.await; | ||||
| 
 | ||||
| 		let joining_points: Option<Vec<network::NetworkJoinPoint>> = | ||||
| 			if !self.data.network.data_points.is_empty() { | ||||
| 				if let Some(last_entry) = self.data.network.data_points.last() { | ||||
| 					// If not empty, inject joining points
 | ||||
| 					let prev_data = &last_entry.1; | ||||
| 					let rx_diff = new_network_data.rx as f64 - prev_data.0.rx as f64; | ||||
| 					let tx_diff = new_network_data.tx as f64 - prev_data.0.tx as f64; | ||||
| 					let time_gap = current_instant | ||||
| 						.duration_since(self.data.network.last_collection_time) | ||||
| 						.as_millis() as f64; | ||||
| 
 | ||||
| 					let mut new_joining_points = Vec::new(); | ||||
| 
 | ||||
| 					let num_points = 50; | ||||
| 					for idx in (0..num_points).rev() { | ||||
| 						new_joining_points.push(network::NetworkJoinPoint { | ||||
| 							rx: prev_data.0.rx as f64 | ||||
| 								+ rx_diff / num_points as f64 * (num_points - idx) as f64, | ||||
| 							tx: prev_data.0.tx as f64 | ||||
| 								+ tx_diff / num_points as f64 * (num_points - idx) as f64, | ||||
| 							time_offset_milliseconds: time_gap / num_points as f64 * idx as f64, | ||||
| 						}); | ||||
| 					} | ||||
| 					Some(new_joining_points) | ||||
| 				} else { | ||||
| 					None | ||||
| 				} | ||||
| 			} else { | ||||
| 				None | ||||
| 			}; | ||||
| 
 | ||||
| 		// Set values
 | ||||
| 		self.data.network.rx = new_network_data.rx; | ||||
| 		self.data.network.tx = new_network_data.tx; | ||||
| 		self.data.network.last_collection_time = current_instant; | ||||
| 
 | ||||
| 		// Add new point
 | ||||
| 		self.data | ||||
| 			.network | ||||
| 			.data_points | ||||
| 			.push((current_instant, (new_network_data, joining_points))); | ||||
| 
 | ||||
| 		// What we want to do: For timed data, if there is an error, just do not add.  For other data, just don't update!
 | ||||
| 		push_if_valid( | ||||
| 			&cpu::get_cpu_data_list(&self.sys, ¤t_instant), | ||||
| @ -198,10 +168,7 @@ impl DataState { | ||||
| 			&mut self.data.list_of_temperature_sensor, | ||||
| 		); | ||||
| 
 | ||||
| 		if self.first_run { | ||||
| 			self.data.first_run_cleanup(); | ||||
| 			self.first_run = false; | ||||
| 		} | ||||
| 		self.data.last_collection_time = current_instant; | ||||
| 
 | ||||
| 		// Filter out stale timed entries
 | ||||
| 		let clean_instant = Instant::now(); | ||||
							
								
								
									
										55
									
								
								src/app/data_harvester/network.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/app/data_harvester/network.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| use futures::StreamExt; | ||||
| use heim::net; | ||||
| use heim::units::information::byte; | ||||
| use std::time::Instant; | ||||
| use sysinfo::{NetworkExt, System, SystemExt}; | ||||
| 
 | ||||
| #[derive(Default, Clone, Debug)] | ||||
| pub struct NetworkHarvest { | ||||
| 	pub rx: u64, | ||||
| 	pub tx: u64, | ||||
| 	pub total_rx: u64, | ||||
| 	pub total_tx: u64, | ||||
| } | ||||
| 
 | ||||
| pub async fn get_network_data( | ||||
| 	sys: &System, prev_net_access_time: &Instant, prev_net_rx: &mut u64, prev_net_tx: &mut u64, | ||||
| 	curr_time: &Instant, | ||||
| ) -> NetworkHarvest { | ||||
| 	// FIXME: [WIN] Track current total bytes... also is this accurate?
 | ||||
| 	if cfg!(target_os = "windows") { | ||||
| 		let network_data = sys.get_network(); | ||||
| 		NetworkHarvest { | ||||
| 			rx: network_data.get_income(), | ||||
| 			tx: network_data.get_outcome(), | ||||
| 			total_rx: 0, | ||||
| 			total_tx: 0, | ||||
| 		} | ||||
| 	} else { | ||||
| 		let mut io_data = net::io_counters(); | ||||
| 		let mut total_rx: u64 = 0; | ||||
| 		let mut total_tx: u64 = 0; | ||||
| 
 | ||||
| 		while let Some(io) = io_data.next().await { | ||||
| 			if let Ok(io) = io { | ||||
| 				total_rx += io.bytes_recv().get::<byte>(); | ||||
| 				total_tx += io.bytes_sent().get::<byte>(); | ||||
| 			} | ||||
| 		} | ||||
| 		let elapsed_time = curr_time | ||||
| 			.duration_since(*prev_net_access_time) | ||||
| 			.as_secs_f64(); | ||||
| 
 | ||||
| 		let rx = ((total_rx - *prev_net_rx) as f64 / elapsed_time) as u64; | ||||
| 		let tx = ((total_tx - *prev_net_tx) as f64 / elapsed_time) as u64; | ||||
| 
 | ||||
| 		*prev_net_rx = total_rx; | ||||
| 		*prev_net_tx = total_tx; | ||||
| 		NetworkHarvest { | ||||
| 			rx, | ||||
| 			tx, | ||||
| 			total_rx, | ||||
| 			total_tx, | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										120
									
								
								src/app/data_janitor.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/app/data_janitor.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,120 @@ | ||||
| use crate::{data_harvester::network, data_harvester::Data}; | ||||
| /// In charge of cleaning and managing data.  I couldn't think of a better
 | ||||
| /// name for the file.
 | ||||
| use std::time::Instant; | ||||
| use std::vec::Vec; | ||||
| 
 | ||||
| pub type TimeOffset = f64; | ||||
| pub type Value = f64; | ||||
| pub type JoinedDataPoints = (Value, Vec<(TimeOffset, Value)>); | ||||
| 
 | ||||
| #[derive(Debug, Default)] | ||||
| pub struct TimedData { | ||||
| 	pub rx_data: JoinedDataPoints, | ||||
| 	pub tx_data: JoinedDataPoints, | ||||
| 	pub cpu_data: JoinedDataPoints, | ||||
| 	pub mem_data: JoinedDataPoints, | ||||
| 	pub swap_data: JoinedDataPoints, | ||||
| } | ||||
| 
 | ||||
| /// AppCollection represents the pooled data stored within the main app
 | ||||
| /// thread.  Basically stores a (occasionally cleaned) record of the data
 | ||||
| /// collected, and what is needed to convert into a displayable form.
 | ||||
| ///
 | ||||
| /// If the app is *frozen* - that is, we do not want to *display* any changing
 | ||||
| /// data, keep updating this, don't convert to canvas displayable data!
 | ||||
| ///
 | ||||
| /// Note that with this method, the *app* thread is responsible for cleaning -
 | ||||
| /// not the data collector.
 | ||||
| #[derive(Debug)] | ||||
| pub struct DataCollection { | ||||
| 	pub current_instant: Instant, | ||||
| 	pub timed_data_vec: Vec<(Instant, TimedData)>, | ||||
| 	pub network_harvest: network::NetworkHarvest, | ||||
| 	// pub process_data: ProcessData,
 | ||||
| 	// pub disk_data: DiskData,
 | ||||
| 	// pub temp_data: TempData,
 | ||||
| } | ||||
| 
 | ||||
| impl Default for DataCollection { | ||||
| 	fn default() -> Self { | ||||
| 		DataCollection { | ||||
| 			current_instant: Instant::now(), | ||||
| 			timed_data_vec: Vec::default(), | ||||
| 			network_harvest: network::NetworkHarvest::default(), | ||||
| 			// process_data: ProcessData::default(),
 | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| impl DataCollection { | ||||
| 	pub fn clean_data(&mut self) {} | ||||
| 
 | ||||
| 	pub fn eat_data(&mut self, harvested_data: &Data) { | ||||
| 		let harvested_time = harvested_data.last_collection_time; | ||||
| 		let mut new_entry = TimedData::default(); | ||||
| 
 | ||||
| 		// RX
 | ||||
| 		let rx_joining_pts = if let Some((time, last_pt)) = self.timed_data_vec.last() { | ||||
| 			generate_joining_points( | ||||
| 				&time, | ||||
| 				last_pt.rx_data.0, | ||||
| 				&harvested_time, | ||||
| 				harvested_data.network.rx as f64, | ||||
| 			) | ||||
| 		} else { | ||||
| 			Vec::new() | ||||
| 		}; | ||||
| 		let rx_pt = (harvested_data.network.rx as f64, rx_joining_pts); | ||||
| 		new_entry.rx_data = rx_pt; | ||||
| 
 | ||||
| 		// TX
 | ||||
| 		let tx_joining_pts = if let Some((time, last_pt)) = self.timed_data_vec.last() { | ||||
| 			generate_joining_points( | ||||
| 				&time, | ||||
| 				last_pt.tx_data.0, | ||||
| 				&harvested_time, | ||||
| 				harvested_data.network.tx as f64, | ||||
| 			) | ||||
| 		} else { | ||||
| 			Vec::new() | ||||
| 		}; | ||||
| 		let tx_pt = (harvested_data.network.tx as f64, tx_joining_pts); | ||||
| 		new_entry.tx_data = tx_pt; | ||||
| 
 | ||||
| 		// Copy over data
 | ||||
| 		self.network_harvest = harvested_data.network.clone(); | ||||
| 
 | ||||
| 		// And we're done eating.
 | ||||
| 		self.current_instant = harvested_time; | ||||
| 		self.timed_data_vec.push((harvested_time, new_entry)); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn generate_joining_points( | ||||
| 	start_x: &Instant, start_y: f64, end_x: &Instant, end_y: f64, | ||||
| ) -> Vec<(TimeOffset, Value)> { | ||||
| 	let mut points: Vec<(TimeOffset, Value)> = Vec::new(); | ||||
| 
 | ||||
| 	// Convert time floats first:
 | ||||
| 	let time_difference = (*end_x).duration_since(*start_x).as_millis() as f64; | ||||
| 	let value_difference = end_y - start_y; | ||||
| 
 | ||||
| 	// Let's generate... about this many points!
 | ||||
| 	let num_points = std::cmp::min( | ||||
| 		std::cmp::max( | ||||
| 			(value_difference.abs() / (time_difference + 0.0001) * 1000.0) as u64, | ||||
| 			100, | ||||
| 		), | ||||
| 		1000, | ||||
| 	); | ||||
| 
 | ||||
| 	for itx in 0..num_points { | ||||
| 		points.push(( | ||||
| 			time_difference - (itx as f64 / num_points as f64 * time_difference), | ||||
| 			start_y + (itx as f64 / num_points as f64 * value_difference), | ||||
| 		)); | ||||
| 	} | ||||
| 
 | ||||
| 	points | ||||
| } | ||||
| @ -334,7 +334,6 @@ pub fn draw_data<B: backend::Backend>( | ||||
| 						} else { | ||||
| 							5 | ||||
| 						}; | ||||
| 						debug!("Req: {}", required); | ||||
| 						let remaining = bottom_chunks[0].height - required; | ||||
| 						[Constraint::Length(remaining), Constraint::Length(required)] | ||||
| 					} | ||||
| @ -665,7 +664,7 @@ fn draw_network_graph<B: backend::Backend>(f: &mut Frame<B>, app_state: &app::Ap | ||||
| 
 | ||||
| 	let x_axis: Axis<String> = Axis::default() | ||||
| 		.style(Style::default().fg(GRAPH_COLOUR)) | ||||
| 		.bounds([0.0, 600_000.0]); | ||||
| 		.bounds([0.0, 60_000.0]); | ||||
| 	let y_axis = Axis::default() | ||||
| 		.style(Style::default().fg(GRAPH_COLOUR)) | ||||
| 		.bounds([-0.5, 30_f64]) | ||||
| @ -1035,7 +1034,7 @@ fn draw_processes_table<B: backend::Backend>( | ||||
| 		) | ||||
| 	}); | ||||
| 
 | ||||
| 	use app::data_collection::processes::ProcessSorting; | ||||
| 	use app::data_harvester::processes::ProcessSorting; | ||||
| 	let mut pid_or_name = if app_state.is_grouped() { | ||||
| 		"Count" | ||||
| 	} else { | ||||
|  | ||||
| @ -2,12 +2,14 @@ | ||||
| //! can actually handle.
 | ||||
| 
 | ||||
| use crate::{ | ||||
| 	app::data_collection, | ||||
| 	app::data_harvester, | ||||
| 	app::data_janitor, | ||||
| 	constants, | ||||
| 	utils::gen_util::{get_exact_byte_values, get_simple_byte_values}, | ||||
| }; | ||||
| use constants::*; | ||||
| use regex::Regex; | ||||
| use std::time::Instant; | ||||
| 
 | ||||
| #[derive(Default, Debug)] | ||||
| pub struct ConvertedNetworkData { | ||||
| @ -55,7 +57,7 @@ impl From<&CpuPoint> for (f64, f64) { | ||||
| } | ||||
| 
 | ||||
| pub fn update_temp_row( | ||||
| 	app_data: &data_collection::Data, temp_type: &data_collection::temperature::TemperatureType, | ||||
| 	app_data: &data_harvester::Data, temp_type: &data_harvester::temperature::TemperatureType, | ||||
| ) -> Vec<Vec<String>> { | ||||
| 	let mut sensor_vector: Vec<Vec<String>> = Vec::new(); | ||||
| 
 | ||||
| @ -67,9 +69,9 @@ pub fn update_temp_row( | ||||
| 				sensor.component_name.to_string(), | ||||
| 				(sensor.temperature.ceil() as u64).to_string() | ||||
| 					+ match temp_type { | ||||
| 						data_collection::temperature::TemperatureType::Celsius => "C", | ||||
| 						data_collection::temperature::TemperatureType::Kelvin => "K", | ||||
| 						data_collection::temperature::TemperatureType::Fahrenheit => "F", | ||||
| 						data_harvester::temperature::TemperatureType::Celsius => "C", | ||||
| 						data_harvester::temperature::TemperatureType::Kelvin => "K", | ||||
| 						data_harvester::temperature::TemperatureType::Fahrenheit => "F", | ||||
| 					}, | ||||
| 			]); | ||||
| 		} | ||||
| @ -78,7 +80,7 @@ pub fn update_temp_row( | ||||
| 	sensor_vector | ||||
| } | ||||
| 
 | ||||
| pub fn update_disk_row(app_data: &data_collection::Data) -> Vec<Vec<String>> { | ||||
| pub fn update_disk_row(app_data: &data_harvester::Data) -> Vec<Vec<String>> { | ||||
| 	let mut disk_vector: Vec<Vec<String>> = Vec::new(); | ||||
| 	for disk in &app_data.list_of_disks { | ||||
| 		let io_activity = { | ||||
| @ -141,7 +143,7 @@ pub fn update_disk_row(app_data: &data_collection::Data) -> Vec<Vec<String>> { | ||||
| } | ||||
| 
 | ||||
| pub fn simple_update_process_row( | ||||
| 	app_data: &data_collection::Data, matching_string: &str, use_pid: bool, | ||||
| 	app_data: &data_harvester::Data, matching_string: &str, use_pid: bool, | ||||
| ) -> (Vec<ConvertedProcessData>, Vec<ConvertedProcessData>) { | ||||
| 	let process_vector: Vec<ConvertedProcessData> = app_data | ||||
| 		.list_of_processes | ||||
| @ -183,7 +185,7 @@ pub fn simple_update_process_row( | ||||
| } | ||||
| 
 | ||||
| pub fn regex_update_process_row( | ||||
| 	app_data: &data_collection::Data, regex_matcher: &std::result::Result<Regex, regex::Error>, | ||||
| 	app_data: &data_harvester::Data, regex_matcher: &std::result::Result<Regex, regex::Error>, | ||||
| 	use_pid: bool, | ||||
| ) -> (Vec<ConvertedProcessData>, Vec<ConvertedProcessData>) { | ||||
| 	let process_vector: Vec<ConvertedProcessData> = app_data | ||||
| @ -226,7 +228,7 @@ pub fn regex_update_process_row( | ||||
| } | ||||
| 
 | ||||
| fn return_mapped_process( | ||||
| 	process: &data_collection::processes::ProcessData, app_data: &data_collection::Data, | ||||
| 	process: &data_harvester::processes::ProcessData, app_data: &data_harvester::Data, | ||||
| ) -> ConvertedProcessData { | ||||
| 	ConvertedProcessData { | ||||
| 		pid: process.pid, | ||||
| @ -251,7 +253,7 @@ fn return_mapped_process( | ||||
| } | ||||
| 
 | ||||
| pub fn update_cpu_data_points( | ||||
| 	show_avg_cpu: bool, app_data: &data_collection::Data, | ||||
| 	show_avg_cpu: bool, app_data: &data_harvester::Data, | ||||
| ) -> Vec<ConvertedCpuData> { | ||||
| 	let mut cpu_data_vector: Vec<ConvertedCpuData> = Vec::new(); | ||||
| 	let mut cpu_collection: Vec<Vec<CpuPoint>> = Vec::new(); | ||||
| @ -264,7 +266,7 @@ pub fn update_cpu_data_points( | ||||
| 			let mut this_cpu_data: Vec<CpuPoint> = Vec::new(); | ||||
| 
 | ||||
| 			for data in &app_data.list_of_cpu_packages { | ||||
| 				let current_time = std::time::Instant::now(); | ||||
| 				let current_time = Instant::now(); | ||||
| 				let current_cpu_usage = data.cpu_vec[cpu_num].cpu_usage; | ||||
| 
 | ||||
| 				let new_entry = CpuPoint { | ||||
| @ -329,15 +331,15 @@ pub fn update_cpu_data_points( | ||||
| 	cpu_data_vector | ||||
| } | ||||
| 
 | ||||
| pub fn update_mem_data_points(app_data: &data_collection::Data) -> Vec<(f64, f64)> { | ||||
| pub fn update_mem_data_points(app_data: &data_harvester::Data) -> Vec<(f64, f64)> { | ||||
| 	convert_mem_data(&app_data.memory) | ||||
| } | ||||
| 
 | ||||
| pub fn update_swap_data_points(app_data: &data_collection::Data) -> Vec<(f64, f64)> { | ||||
| pub fn update_swap_data_points(app_data: &data_harvester::Data) -> Vec<(f64, f64)> { | ||||
| 	convert_mem_data(&app_data.swap) | ||||
| } | ||||
| 
 | ||||
| pub fn update_mem_data_values(app_data: &data_collection::Data) -> Vec<(u64, u64)> { | ||||
| pub fn update_mem_data_values(app_data: &data_harvester::Data) -> Vec<(u64, u64)> { | ||||
| 	let mut result: Vec<(u64, u64)> = Vec::new(); | ||||
| 	result.push(get_most_recent_mem_values(&app_data.memory)); | ||||
| 	result.push(get_most_recent_mem_values(&app_data.swap)); | ||||
| @ -345,7 +347,7 @@ pub fn update_mem_data_values(app_data: &data_collection::Data) -> Vec<(u64, u64 | ||||
| 	result | ||||
| } | ||||
| 
 | ||||
| fn get_most_recent_mem_values(mem_data: &[data_collection::mem::MemData]) -> (u64, u64) { | ||||
| fn get_most_recent_mem_values(mem_data: &[data_harvester::mem::MemData]) -> (u64, u64) { | ||||
| 	let mut result: (u64, u64) = (0, 0); | ||||
| 
 | ||||
| 	if !mem_data.is_empty() { | ||||
| @ -358,7 +360,7 @@ fn get_most_recent_mem_values(mem_data: &[data_collection::mem::MemData]) -> (u6 | ||||
| 	result | ||||
| } | ||||
| 
 | ||||
| fn convert_mem_data(mem_data: &[data_collection::mem::MemData]) -> Vec<(f64, f64)> { | ||||
| fn convert_mem_data(mem_data: &[data_harvester::mem::MemData]) -> Vec<(f64, f64)> { | ||||
| 	let mut result: Vec<(f64, f64)> = Vec::new(); | ||||
| 
 | ||||
| 	for data in mem_data { | ||||
| @ -394,67 +396,45 @@ fn convert_mem_data(mem_data: &[data_collection::mem::MemData]) -> Vec<(f64, f64 | ||||
| 	result | ||||
| } | ||||
| 
 | ||||
| pub fn update_network_data_points(app_data: &data_collection::Data) -> ConvertedNetworkData { | ||||
| 	convert_network_data_points(&app_data.network) | ||||
| } | ||||
| 
 | ||||
| pub fn convert_network_data_points( | ||||
| 	network_data: &data_collection::network::NetworkStorage, | ||||
| 	current_data: &data_janitor::DataCollection, | ||||
| ) -> ConvertedNetworkData { | ||||
| 	let mut rx: Vec<(f64, f64)> = Vec::new(); | ||||
| 	let mut tx: Vec<(f64, f64)> = Vec::new(); | ||||
| 
 | ||||
| 	let current_time = network_data.last_collection_time; | ||||
| 	for (time, data) in &network_data.data_points { | ||||
| 		let time_from_start: f64 = ((TIME_STARTS_FROM as f64 | ||||
| 	let current_time = current_data.current_instant; | ||||
| 	for (time, data) in ¤t_data.timed_data_vec { | ||||
| 		let time_from_start: f64 = (TIME_STARTS_FROM as f64 | ||||
| 			- current_time.duration_since(*time).as_millis() as f64) | ||||
| 			* 10_f64) | ||||
| 			.floor(); | ||||
| 
 | ||||
| 		// Insert in joiner points
 | ||||
| 		if let Some(joiners) = &data.1 { | ||||
| 			for joiner in joiners { | ||||
| 				let offset_time = time_from_start - joiner.time_offset_milliseconds as f64 * 10_f64; | ||||
| 				rx.push(( | ||||
| 					offset_time, | ||||
| 					if joiner.rx > 0.0 { | ||||
| 						(joiner.rx).log(2.0) | ||||
| 					} else { | ||||
| 						0.0 | ||||
| 					}, | ||||
| 				)); | ||||
| 
 | ||||
| 				tx.push(( | ||||
| 					offset_time, | ||||
| 					if joiner.tx > 0.0 { | ||||
| 						(joiner.tx).log(2.0) | ||||
| 					} else { | ||||
| 						0.0 | ||||
| 					}, | ||||
| 				)); | ||||
| 			} | ||||
| 		//Insert joiner points
 | ||||
| 		for &(joiner_offset, joiner_val) in &data.rx_data.1 { | ||||
| 			let offset_time = time_from_start - joiner_offset as f64; | ||||
| 			rx.push(( | ||||
| 				offset_time, | ||||
| 				if joiner_val > 0.0 { | ||||
| 					(joiner_val).log(2.0) | ||||
| 				} else { | ||||
| 					0.0 | ||||
| 				}, | ||||
| 			)); | ||||
| 		} | ||||
| 
 | ||||
| 		// Insert in main points
 | ||||
| 		let rx_data = ( | ||||
| 			time_from_start, | ||||
| 			if data.0.rx > 0 { | ||||
| 				(data.0.rx as f64).log(2.0) | ||||
| 			} else { | ||||
| 				0.0 | ||||
| 			}, | ||||
| 		); | ||||
| 		let tx_data = ( | ||||
| 			time_from_start, | ||||
| 			if data.0.tx > 0 { | ||||
| 				(data.0.tx as f64).log(2.0) | ||||
| 			} else { | ||||
| 				0.0 | ||||
| 			}, | ||||
| 		); | ||||
| 		for &(joiner_offset, joiner_val) in &data.tx_data.1 { | ||||
| 			let offset_time = time_from_start - joiner_offset as f64; | ||||
| 			tx.push(( | ||||
| 				offset_time, | ||||
| 				if joiner_val > 0.0 { | ||||
| 					(joiner_val).log(2.0) | ||||
| 				} else { | ||||
| 					0.0 | ||||
| 				}, | ||||
| 			)); | ||||
| 		} | ||||
| 
 | ||||
| 		rx.push(rx_data); | ||||
| 		tx.push(tx_data); | ||||
| 		rx.push((time_from_start, data.rx_data.0)); | ||||
| 		tx.push((time_from_start, data.tx_data.0)); | ||||
| 	} | ||||
| 
 | ||||
| 	let total_rx_converted_result: (f64, String); | ||||
| @ -462,8 +442,8 @@ pub fn convert_network_data_points( | ||||
| 	let total_tx_converted_result: (f64, String); | ||||
| 	let tx_converted_result: (f64, String); | ||||
| 
 | ||||
| 	rx_converted_result = get_exact_byte_values(network_data.rx, false); | ||||
| 	total_rx_converted_result = get_exact_byte_values(network_data.total_rx, false); | ||||
| 	rx_converted_result = get_exact_byte_values(current_data.network_harvest.rx, false); | ||||
| 	total_rx_converted_result = get_exact_byte_values(current_data.network_harvest.total_rx, false); | ||||
| 	let rx_display = format!("{:.*}{}", 1, rx_converted_result.0, rx_converted_result.1); | ||||
| 	let total_rx_display = if cfg!(not(target_os = "windows")) { | ||||
| 		format!( | ||||
| @ -474,8 +454,8 @@ pub fn convert_network_data_points( | ||||
| 		"N/A".to_string() | ||||
| 	}; | ||||
| 
 | ||||
| 	tx_converted_result = get_exact_byte_values(network_data.tx, false); | ||||
| 	total_tx_converted_result = get_exact_byte_values(network_data.total_tx, false); | ||||
| 	tx_converted_result = get_exact_byte_values(current_data.network_harvest.tx, false); | ||||
| 	total_tx_converted_result = get_exact_byte_values(current_data.network_harvest.total_tx, false); | ||||
| 	let tx_display = format!("{:.*}{}", 1, tx_converted_result.0, tx_converted_result.1); | ||||
| 	let total_tx_display = if cfg!(not(target_os = "windows")) { | ||||
| 		format!( | ||||
|  | ||||
							
								
								
									
										43
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								src/main.rs
									
									
									
									
									
								
							| @ -35,8 +35,8 @@ mod canvas; | ||||
| mod constants; | ||||
| mod data_conversion; | ||||
| 
 | ||||
| use app::data_collection; | ||||
| use app::data_collection::processes::ProcessData; | ||||
| use app::data_harvester; | ||||
| use app::data_harvester::processes::ProcessData; | ||||
| use constants::TICK_RATE_IN_MILLISECONDS; | ||||
| use data_conversion::*; | ||||
| use std::collections::BTreeMap; | ||||
| @ -45,7 +45,7 @@ use utils::error::{self, BottomError}; | ||||
| enum Event<I, J> { | ||||
| 	KeyInput(I), | ||||
| 	MouseInput(J), | ||||
| 	Update(Box<data_collection::Data>), | ||||
| 	Update(Box<data_harvester::Data>), | ||||
| } | ||||
| 
 | ||||
| enum ResetEvent { | ||||
| @ -104,11 +104,11 @@ fn main() -> error::Result<()> { | ||||
| 
 | ||||
| 	// Set other settings
 | ||||
| 	let temperature_type = if matches.is_present("FAHRENHEIT") { | ||||
| 		data_collection::temperature::TemperatureType::Fahrenheit | ||||
| 		data_harvester::temperature::TemperatureType::Fahrenheit | ||||
| 	} else if matches.is_present("KELVIN") { | ||||
| 		data_collection::temperature::TemperatureType::Kelvin | ||||
| 		data_harvester::temperature::TemperatureType::Kelvin | ||||
| 	} else { | ||||
| 		data_collection::temperature::TemperatureType::Celsius | ||||
| 		data_harvester::temperature::TemperatureType::Celsius | ||||
| 	}; | ||||
| 	let show_average_cpu = matches.is_present("AVG_CPU"); | ||||
| 	let use_dot = matches.is_present("DOT_MARKER"); | ||||
| @ -183,7 +183,7 @@ fn main() -> error::Result<()> { | ||||
| 		let temp_type = app.temperature_type.clone(); | ||||
| 		thread::spawn(move || { | ||||
| 			let tx = tx.clone(); | ||||
| 			let mut data_state = data_collection::DataState::default(); | ||||
| 			let mut data_state = data_harvester::DataState::default(); | ||||
| 			data_state.init(); | ||||
| 			data_state.set_temperature_type(temp_type); | ||||
| 			data_state.set_use_current_cpu_total(use_current_cpu_total); | ||||
| @ -193,21 +193,22 @@ fn main() -> error::Result<()> { | ||||
| 						ResetEvent::Reset => { | ||||
| 							//debug!("Received reset message");
 | ||||
| 							first_run = true; | ||||
| 							data_state.data = app::data_collection::Data::default(); | ||||
| 							data_state.data = app::data_harvester::Data::default(); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				futures::executor::block_on(data_state.update_data()); | ||||
| 				tx.send(Event::Update(Box::from(data_state.data.clone()))) | ||||
| 					.unwrap(); // TODO: [UNWRAP] Might be required, it's in a closure and idk how to deal with it
 | ||||
| 
 | ||||
| 				if first_run { | ||||
| 					// Fix for if you set a really long time for update periods (and just gives a faster first value)
 | ||||
| 					data_state.data.first_run_cleanup(); // TODO: [OPT] we can remove this later.
 | ||||
| 					thread::sleep(Duration::from_millis(250)); | ||||
| 					futures::executor::block_on(data_state.update_data()); | ||||
| 					first_run = false; | ||||
| 				} else { | ||||
| 					thread::sleep(Duration::from_millis(update_rate_in_milliseconds as u64)); | ||||
| 				} | ||||
| 				tx.send(Event::Update(Box::from(data_state.data.clone()))) | ||||
| 					.unwrap(); // TODO: [UNWRAP] Might be required, it's in a closure and idk how to deal with it
 | ||||
| 				thread::sleep(Duration::from_millis(update_rate_in_milliseconds as u64)); | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
| @ -277,12 +278,14 @@ fn main() -> error::Result<()> { | ||||
| 					// NOTE TO SELF - data is refreshed into app state HERE!  That means, if it is
 | ||||
| 					// frozen, then, app.data is never refreshed, until unfrozen!
 | ||||
| 					if !app.is_frozen { | ||||
| 						app.data_collection.eat_data(&data); | ||||
| 
 | ||||
| 						app.data = *data; | ||||
| 
 | ||||
| 						handle_process_sorting(&mut app); | ||||
| 
 | ||||
| 						// Convert all data into tui components
 | ||||
| 						let network_data = update_network_data_points(&app.data); | ||||
| 						let network_data = convert_network_data_points(&app.data_collection); | ||||
| 						app.canvas_data.network_data_rx = network_data.rx; | ||||
| 						app.canvas_data.network_data_tx = network_data.tx; | ||||
| 						app.canvas_data.rx_display = network_data.rx_display; | ||||
| @ -303,9 +306,9 @@ fn main() -> error::Result<()> { | ||||
| 		} | ||||
| 
 | ||||
| 		// Quick fix for tab updating the table headers
 | ||||
| 		if let data_collection::processes::ProcessSorting::PID = &app.process_sorting_type { | ||||
| 		if let data_harvester::processes::ProcessSorting::PID = &app.process_sorting_type { | ||||
| 			if app.is_grouped() { | ||||
| 				app.process_sorting_type = data_collection::processes::ProcessSorting::CPU; // Go back to default, negate PID for group
 | ||||
| 				app.process_sorting_type = data_harvester::processes::ProcessSorting::CPU; // Go back to default, negate PID for group
 | ||||
| 				app.process_sorting_reverse = true; | ||||
| 			} | ||||
| 		} | ||||
| @ -372,14 +375,14 @@ fn handle_process_sorting(app: &mut app::App) { | ||||
| 	); | ||||
| 
 | ||||
| 	if let Some(grouped_list_of_processes) = &mut app.data.grouped_list_of_processes { | ||||
| 		if let data_collection::processes::ProcessSorting::PID = &app.process_sorting_type { | ||||
| 			data_collection::processes::sort_processes( | ||||
| 		if let data_harvester::processes::ProcessSorting::PID = &app.process_sorting_type { | ||||
| 			data_harvester::processes::sort_processes( | ||||
| 				grouped_list_of_processes, | ||||
| 				&data_collection::processes::ProcessSorting::CPU, // Go back to default, negate PID for group
 | ||||
| 				&data_harvester::processes::ProcessSorting::CPU, // Go back to default, negate PID for group
 | ||||
| 				true, | ||||
| 			); | ||||
| 		} else { | ||||
| 			data_collection::processes::sort_processes( | ||||
| 			data_harvester::processes::sort_processes( | ||||
| 				grouped_list_of_processes, | ||||
| 				&app.process_sorting_type, | ||||
| 				app.process_sorting_reverse, | ||||
| @ -387,7 +390,7 @@ fn handle_process_sorting(app: &mut app::App) { | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	data_collection::processes::sort_processes( | ||||
| 	data_harvester::processes::sort_processes( | ||||
| 		&mut app.data.list_of_processes, | ||||
| 		&app.process_sorting_type, | ||||
| 		app.process_sorting_reverse, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user