2019-09-15 03:48:29 +02:00
|
|
|
//! This is the main file to house data collection functions.
|
|
|
|
|
2019-12-26 05:02:21 +01:00
|
|
|
use crate::{constants, utils::error::Result};
|
2019-10-07 03:06:53 +02:00
|
|
|
use std::{collections::HashMap, time::Instant};
|
2019-09-14 23:07:18 +02:00
|
|
|
use sysinfo::{System, SystemExt};
|
|
|
|
|
2019-09-12 02:41:11 +02:00
|
|
|
pub mod cpu;
|
|
|
|
pub mod disks;
|
|
|
|
pub mod mem;
|
|
|
|
pub mod network;
|
|
|
|
pub mod processes;
|
|
|
|
pub mod temperature;
|
2019-09-14 23:07:18 +02:00
|
|
|
|
2019-12-26 05:02:21 +01:00
|
|
|
fn set_if_valid<T: std::clone::Clone>(result: &Result<T>, value_to_set: &mut T) {
|
2019-09-14 23:07:18 +02:00
|
|
|
if let Ok(result) = result {
|
|
|
|
*value_to_set = (*result).clone();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-26 05:02:21 +01:00
|
|
|
fn push_if_valid<T: std::clone::Clone>(result: &Result<T>, vector_to_push: &mut Vec<T>) {
|
2019-09-14 23:07:18 +02:00
|
|
|
if let Ok(result) = result {
|
|
|
|
vector_to_push.push(result.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-20 07:28:30 +01:00
|
|
|
#[derive(Clone, Debug, Default)]
|
2019-09-14 23:07:18 +02:00
|
|
|
pub struct Data {
|
2019-12-06 06:57:04 +01:00
|
|
|
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>,
|
2020-01-20 07:28:30 +01:00
|
|
|
pub network: network::NetworkStorage,
|
2020-01-08 06:28:11 +01:00
|
|
|
pub list_of_processes: Vec<processes::ProcessData>,
|
|
|
|
pub grouped_list_of_processes: Option<Vec<processes::ProcessData>>,
|
2020-01-20 07:28:30 +01:00
|
|
|
pub list_of_disks: Vec<disks::DiskData>,
|
2019-09-14 23:07:18 +02:00
|
|
|
}
|
|
|
|
|
2020-01-22 05:10:32 +01:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-14 23:07:18 +02:00
|
|
|
pub struct DataState {
|
2019-12-06 06:57:04 +01:00
|
|
|
pub data: Data,
|
|
|
|
first_run: bool,
|
|
|
|
sys: System,
|
|
|
|
stale_max_seconds: u64,
|
|
|
|
prev_pid_stats: HashMap<String, (f64, Instant)>,
|
|
|
|
prev_idle: f64,
|
|
|
|
prev_non_idle: f64,
|
|
|
|
temperature_type: temperature::TemperatureType,
|
|
|
|
last_clean: Instant, // Last time stale data was cleared
|
2020-01-01 04:24:54 +01:00
|
|
|
use_current_cpu_total: bool,
|
2019-09-14 23:07:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for DataState {
|
|
|
|
fn default() -> Self {
|
|
|
|
DataState {
|
2019-12-06 06:57:04 +01:00
|
|
|
data: Data::default(),
|
|
|
|
first_run: true,
|
|
|
|
sys: System::new(),
|
|
|
|
stale_max_seconds: constants::STALE_MAX_MILLISECONDS / 1000,
|
|
|
|
prev_pid_stats: HashMap::new(),
|
|
|
|
prev_idle: 0_f64,
|
|
|
|
prev_non_idle: 0_f64,
|
|
|
|
temperature_type: temperature::TemperatureType::Celsius,
|
|
|
|
last_clean: Instant::now(),
|
2020-01-01 04:24:54 +01:00
|
|
|
use_current_cpu_total: false,
|
2019-09-14 23:07:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DataState {
|
2019-12-06 06:57:04 +01:00
|
|
|
pub fn set_temperature_type(&mut self, temperature_type: temperature::TemperatureType) {
|
2019-09-14 23:07:18 +02:00
|
|
|
self.temperature_type = temperature_type;
|
|
|
|
}
|
|
|
|
|
2020-01-01 04:24:54 +01:00
|
|
|
pub fn set_use_current_cpu_total(&mut self, use_current_cpu_total: bool) {
|
|
|
|
self.use_current_cpu_total = use_current_cpu_total;
|
|
|
|
}
|
|
|
|
|
2019-09-14 23:07:18 +02:00
|
|
|
pub fn init(&mut self) {
|
2019-12-26 05:02:21 +01:00
|
|
|
self.sys.refresh_all();
|
2019-09-14 23:07:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn update_data(&mut self) {
|
|
|
|
self.sys.refresh_system();
|
|
|
|
|
2019-09-16 22:18:42 +02:00
|
|
|
if !cfg!(target_os = "linux") {
|
|
|
|
// For now, might be just windows tbh
|
|
|
|
self.sys.refresh_processes();
|
2019-12-26 05:02:21 +01:00
|
|
|
self.sys.refresh_network();
|
2019-09-16 22:18:42 +02:00
|
|
|
}
|
|
|
|
|
2020-01-10 03:59:52 +01:00
|
|
|
let current_instant = std::time::Instant::now();
|
|
|
|
|
2020-01-20 07:28:30 +01:00
|
|
|
// Network
|
|
|
|
let new_network_data = network::get_network_data(
|
|
|
|
&self.sys,
|
|
|
|
&self.data.network.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(prev_data) = self
|
|
|
|
.data
|
|
|
|
.network
|
|
|
|
.data_points
|
|
|
|
.get(&self.data.network.last_collection_time)
|
|
|
|
{
|
|
|
|
// If not empty, inject joining points
|
|
|
|
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();
|
|
|
|
|
2020-01-22 04:59:42 +01:00
|
|
|
let num_points = 50;
|
|
|
|
for idx in (0..num_points).rev() {
|
2020-01-20 07:28:30 +01:00
|
|
|
new_joining_points.push(network::NetworkJoinPoint {
|
2020-01-22 04:59:42 +01:00
|
|
|
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,
|
2020-01-20 07:28:30 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
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
|
|
|
|
.insert(current_instant, (new_network_data, joining_points));
|
|
|
|
|
2019-09-14 23:07:18 +02:00
|
|
|
// What we want to do: For timed data, if there is an error, just do not add. For other data, just don't update!
|
2020-01-08 05:39:52 +01:00
|
|
|
push_if_valid(
|
2020-01-10 03:59:52 +01:00
|
|
|
&cpu::get_cpu_data_list(&self.sys, ¤t_instant),
|
2020-01-08 05:39:52 +01:00
|
|
|
&mut self.data.list_of_cpu_packages,
|
|
|
|
);
|
2019-09-14 23:07:18 +02:00
|
|
|
|
2020-01-10 03:59:52 +01:00
|
|
|
push_if_valid(
|
|
|
|
&mem::get_mem_data_list(¤t_instant).await,
|
|
|
|
&mut self.data.memory,
|
|
|
|
);
|
|
|
|
push_if_valid(
|
|
|
|
&mem::get_swap_data_list(¤t_instant).await,
|
|
|
|
&mut self.data.swap,
|
|
|
|
);
|
2019-09-14 23:07:18 +02:00
|
|
|
set_if_valid(
|
2020-01-01 04:24:54 +01:00
|
|
|
&processes::get_sorted_processes_list(
|
|
|
|
&self.sys,
|
|
|
|
&mut self.prev_idle,
|
|
|
|
&mut self.prev_non_idle,
|
|
|
|
&mut self.prev_pid_stats,
|
|
|
|
self.use_current_cpu_total,
|
2020-01-10 03:59:52 +01:00
|
|
|
¤t_instant,
|
2020-01-01 04:24:54 +01:00
|
|
|
),
|
2019-09-14 23:07:18 +02:00
|
|
|
&mut self.data.list_of_processes,
|
|
|
|
);
|
|
|
|
|
2020-01-08 05:39:52 +01:00
|
|
|
set_if_valid(
|
|
|
|
&disks::get_disk_usage_list().await,
|
|
|
|
&mut self.data.list_of_disks,
|
|
|
|
);
|
|
|
|
push_if_valid(
|
|
|
|
&disks::get_io_usage_list(false).await,
|
|
|
|
&mut self.data.list_of_io,
|
|
|
|
);
|
2019-09-25 06:27:43 +02:00
|
|
|
set_if_valid(
|
|
|
|
&temperature::get_temperature_data(&self.sys, &self.temperature_type).await,
|
|
|
|
&mut self.data.list_of_temperature_sensor,
|
|
|
|
);
|
2019-09-14 23:07:18 +02:00
|
|
|
|
|
|
|
if self.first_run {
|
2020-01-22 05:10:32 +01:00
|
|
|
self.data.first_run_cleanup();
|
2019-09-14 23:07:18 +02:00
|
|
|
self.first_run = false;
|
|
|
|
}
|
|
|
|
|
2020-01-11 06:42:03 +01:00
|
|
|
// Filter out stale timed entries
|
|
|
|
let clean_instant = Instant::now();
|
|
|
|
if clean_instant.duration_since(self.last_clean).as_secs() > self.stale_max_seconds {
|
2019-12-06 06:57:04 +01:00
|
|
|
let stale_list: Vec<_> = self
|
2019-10-10 01:19:39 +02:00
|
|
|
.prev_pid_stats
|
|
|
|
.iter()
|
2020-01-08 05:39:52 +01:00
|
|
|
.filter(|&(_, &v)| {
|
2020-01-11 06:42:03 +01:00
|
|
|
clean_instant.duration_since(v.1).as_secs() > self.stale_max_seconds
|
2020-01-08 05:39:52 +01:00
|
|
|
})
|
2019-10-10 01:19:39 +02:00
|
|
|
.map(|(k, _)| k.clone())
|
|
|
|
.collect();
|
|
|
|
for stale in stale_list {
|
|
|
|
self.prev_pid_stats.remove(&stale);
|
|
|
|
}
|
|
|
|
|
2020-01-20 07:28:30 +01:00
|
|
|
// TODO: [OPT] cleaning stale network
|
|
|
|
|
2019-10-10 01:19:39 +02:00
|
|
|
self.data.list_of_cpu_packages = self
|
|
|
|
.data
|
|
|
|
.list_of_cpu_packages
|
|
|
|
.iter()
|
|
|
|
.cloned()
|
2020-01-08 05:39:52 +01:00
|
|
|
.filter(|entry| {
|
2020-01-11 06:42:03 +01:00
|
|
|
clean_instant.duration_since(entry.instant).as_secs() <= self.stale_max_seconds
|
2020-01-08 05:39:52 +01:00
|
|
|
})
|
2019-10-10 01:19:39 +02:00
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
self.data.memory = self
|
|
|
|
.data
|
|
|
|
.memory
|
|
|
|
.iter()
|
|
|
|
.cloned()
|
2020-01-08 05:39:52 +01:00
|
|
|
.filter(|entry| {
|
2020-01-11 06:42:03 +01:00
|
|
|
clean_instant.duration_since(entry.instant).as_secs() <= self.stale_max_seconds
|
2020-01-08 05:39:52 +01:00
|
|
|
})
|
2019-10-10 01:19:39 +02:00
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
self.data.swap = self
|
|
|
|
.data
|
|
|
|
.swap
|
|
|
|
.iter()
|
|
|
|
.cloned()
|
2020-01-08 05:39:52 +01:00
|
|
|
.filter(|entry| {
|
2020-01-11 06:42:03 +01:00
|
|
|
clean_instant.duration_since(entry.instant).as_secs() <= self.stale_max_seconds
|
2020-01-08 05:39:52 +01:00
|
|
|
})
|
2019-10-10 01:19:39 +02:00
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
self.data.list_of_io = self
|
|
|
|
.data
|
|
|
|
.list_of_io
|
|
|
|
.iter()
|
|
|
|
.cloned()
|
2020-01-08 05:39:52 +01:00
|
|
|
.filter(|entry| {
|
2020-01-11 06:42:03 +01:00
|
|
|
clean_instant.duration_since(entry.instant).as_secs() <= self.stale_max_seconds
|
2020-01-08 05:39:52 +01:00
|
|
|
})
|
2019-10-10 01:19:39 +02:00
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
2020-01-11 06:42:03 +01:00
|
|
|
self.last_clean = clean_instant;
|
2019-10-07 03:06:53 +02:00
|
|
|
}
|
2019-09-14 23:07:18 +02:00
|
|
|
}
|
|
|
|
}
|