Temporarily(?) switch from heim+uom to sysinfo (#2954)

* Switch from heim to sysinfo

* WIP

* more cleanup

* fmt

* lint
This commit is contained in:
Jonathan Turner
2021-01-20 20:18:38 +13:00
committed by GitHub
parent 430da53f0b
commit b435075e09
11 changed files with 295 additions and 853 deletions

View File

@ -55,7 +55,6 @@ futures-util = "0.3.8"
futures_codec = "0.4.1"
getset = "0.1.1"
glob = "0.3.0"
heim = { version = "0.1.0-rc.1", optional = true }
htmlescape = "0.3.1"
ical = "0.7.0"
ichwh = { version = "0.3.4", optional = true }
@ -98,7 +97,6 @@ titlecase = "1.0"
toml = "0.5.6"
trash = { version = "1.2.0", optional = true }
unicode-segmentation = "1.6.0"
uom = { version = "0.30.0", features = ["f64", "try-from"] }
url = "2.1.1"
uuid_crate = { package = "uuid", version = "0.8.1", features = ["v4"], optional = true }
which = { version = "4.0.2", optional = true }
@ -130,7 +128,6 @@ quickcheck_macros = "0.9.1"
[features]
default = ["shadow-rs"]
clipboard-cli = ["arboard"]
rich-benchmark = ["heim"]
rustyline-support = ["rustyline", "nu-engine/rustyline-support"]
stable = []
trash-support = ["trash"]

View File

@ -54,7 +54,6 @@ futures-util = "0.3.8"
futures_codec = "0.4.1"
getset = "0.1.1"
glob = "0.3.0"
heim = { version = "0.1.0-rc.1", optional = true }
htmlescape = "0.3.1"
ical = "0.7.0"
ichwh = { version = "0.3.4", optional = true }
@ -97,7 +96,6 @@ titlecase = "1.0"
toml = "0.5.6"
trash = { version = "1.2.0", optional = true }
unicode-segmentation = "1.6.0"
uom = { version = "0.30.0", features = ["f64", "try-from"] }
url = "2.1.1"
uuid_crate = { package = "uuid", version = "0.8.1", features = ["v4"], optional = true }
which = { version = "4.0.2", optional = true }
@ -127,7 +125,6 @@ quickcheck_macros = "0.9.1"
[features]
clipboard-cli = ["arboard"]
rich-benchmark = ["heim"]
rustyline-support = ["rustyline"]
stable = []
trash-support = ["trash"]

View File

@ -1,6 +1,6 @@
use crate::prelude::*;
#[cfg(feature = "rich-benchmark")]
use heim::cpu::time;
// #[cfg(feature = "rich-benchmark")]
// use heim::cpu::time;
use nu_engine::run_block;
use nu_engine::WholeStreamCommand;
use nu_errors::ShellError;
@ -81,22 +81,22 @@ async fn benchmark(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
let start_time = Instant::now();
#[cfg(feature = "rich-benchmark")]
let start = time().await;
// #[cfg(feature = "rich-benchmark")]
// let start = time().await;
context.scope.enter_scope();
let result = run_block(&block.block, &context, input).await;
context.scope.exit_scope();
let output = result?.into_vec().await;
#[cfg(feature = "rich-benchmark")]
let end = time().await;
// #[cfg(feature = "rich-benchmark")]
// let end = time().await;
let end_time = Instant::now();
context.clear_errors();
// return basic runtime
#[cfg(not(feature = "rich-benchmark"))]
//#[cfg(not(feature = "rich-benchmark"))]
{
let mut indexmap = IndexMap::with_capacity(1);
@ -105,28 +105,28 @@ async fn benchmark(raw_args: CommandArgs) -> Result<OutputStream, ShellError> {
benchmark_output(indexmap, output, passthrough, &tag, &mut context).await
}
// return advanced stats
#[cfg(feature = "rich-benchmark")]
if let (Ok(start), Ok(end)) = (start, end) {
let mut indexmap = IndexMap::with_capacity(4);
// #[cfg(feature = "rich-benchmark")]
// if let (Ok(start), Ok(end)) = (start, end) {
// let mut indexmap = IndexMap::with_capacity(4);
let real_time = into_big_int(end_time - start_time);
indexmap.insert("real time".to_string(), real_time);
// let real_time = into_big_int(end_time - start_time);
// indexmap.insert("real time".to_string(), real_time);
let user_time = into_big_int(end.user() - start.user());
indexmap.insert("user time".to_string(), user_time);
// let user_time = into_big_int(end.user() - start.user());
// indexmap.insert("user time".to_string(), user_time);
let system_time = into_big_int(end.system() - start.system());
indexmap.insert("system time".to_string(), system_time);
// let system_time = into_big_int(end.system() - start.system());
// indexmap.insert("system time".to_string(), system_time);
let idle_time = into_big_int(end.idle() - start.idle());
indexmap.insert("idle time".to_string(), idle_time);
// let idle_time = into_big_int(end.idle() - start.idle());
// indexmap.insert("idle time".to_string(), idle_time);
benchmark_output(indexmap, output, passthrough, &tag, &mut context).await
} else {
Err(ShellError::untagged_runtime_error(
"Could not retrieve CPU time",
))
}
// benchmark_output(indexmap, output, passthrough, &tag, &mut context).await
// } else {
// Err(ShellError::untagged_runtime_error(
// "Could not retrieve CPU time",
// ))
// }
}
async fn benchmark_output<T, Output>(

View File

@ -170,10 +170,10 @@ fn features_enabled() -> Vec<String> {
names.push("ptree".to_string());
}
#[cfg(feature = "rich-benchmark")]
{
names.push("rich-benchmark".to_string());
}
// #[cfg(feature = "rich-benchmark")]
// {
// names.push("rich-benchmark".to_string());
// }
#[cfg(feature = "rustyline-support")]
{

View File

@ -1,5 +1,6 @@
use nu_protocol::{outln, CallInfo, Value};
use nu_protocol::{CallInfo, Value};
use serde::{Deserialize, Serialize};
use std::io::Write;
#[derive(Debug, Serialize, Deserialize)]
pub struct JsonRpc<T> {
@ -22,10 +23,16 @@ pub fn send_response<T: Serialize>(result: T) {
let response = JsonRpc::new("response", result);
let response_raw = serde_json::to_string(&response);
let mut stdout = std::io::stdout();
match response_raw {
Ok(response) => outln!("{}", response),
Err(err) => outln!("{}", err),
}
Ok(response) => {
let _ = writeln!(stdout, "{}", response);
}
Err(err) => {
let _ = writeln!(stdout, "{}", err);
}
};
}
#[derive(Debug, Serialize, Deserialize)]

View File

@ -19,10 +19,6 @@ num-bigint = "0.3.0"
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
futures-timer = "3.0.2"
[dependencies.heim]
default-features = false
features = ["process"]
version = "0.1.0-rc.1"
sysinfo = "0.15.9"
[build-dependencies]

View File

@ -1,15 +1,7 @@
use futures::{StreamExt, TryStreamExt};
use heim::process::{self as process, Process, ProcessResult};
use heim::units::{information, ratio, time, Ratio};
use std::usize;
use nu_errors::ShellError;
use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value};
use nu_source::Tag;
use num_bigint::BigInt;
use std::time::Duration;
use sysinfo::{ProcessExt, System, SystemExt};
#[derive(Default)]
pub struct Ps;
@ -20,88 +12,41 @@ impl Ps {
}
}
async fn usage(process: Process) -> ProcessResult<(process::Process, Ratio, process::Memory)> {
let usage_1 = process.cpu_usage().await?;
futures_timer::Delay::new(Duration::from_millis(100)).await;
let usage_2 = process.cpu_usage().await?;
let memory = process.memory().await?;
Ok((process, usage_2 - usage_1, memory))
}
pub async fn ps(tag: Tag, long: bool) -> Result<Vec<Value>, ShellError> {
let processes = process::processes()
.await
.map_err(|_| {
ShellError::labeled_error(
"Unable to get process list",
"could not load process list",
tag.span,
)
})?
.map_ok(|process| {
// Note that there is no `.await` here,
// as we want to pass the returned future
// into the `.try_buffer_unordered`.
usage(process)
})
.try_buffer_unordered(usize::MAX);
futures::pin_mut!(processes);
let mut sys = System::new_all();
sys.refresh_all();
let duration = std::time::Duration::from_millis(500);
std::thread::sleep(duration);
sys.refresh_all();
let mut output = vec![];
while let Some(res) = processes.next().await {
if let Ok((process, usage, memory)) = res {
let mut dict = TaggedDictBuilder::new(&tag);
dict.insert_untagged("pid", UntaggedValue::int(process.pid()));
if let Ok(name) = process.name().await {
dict.insert_untagged("name", UntaggedValue::string(name));
}
if let Ok(status) = process.status().await {
dict.insert_untagged("status", UntaggedValue::string(format!("{:?}", status)));
}
dict.insert_untagged(
"cpu",
UntaggedValue::decimal_from_float(usage.get::<ratio::percent>() as f64, tag.span),
);
dict.insert_untagged(
"mem",
UntaggedValue::filesize(memory.rss().get::<information::byte>()),
);
dict.insert_untagged(
"virtual",
UntaggedValue::filesize(memory.vms().get::<information::byte>()),
);
if long {
if let Ok(cpu_time) = process.cpu_time().await {
let user_time = cpu_time.user().get::<time::nanosecond>().round() as i64;
let system_time = cpu_time.system().get::<time::nanosecond>().round() as i64;
dict.insert_untagged(
"cpu_time",
UntaggedValue::duration(BigInt::from(user_time + system_time)),
)
}
if let Ok(parent_pid) = process.parent_pid().await {
dict.insert_untagged("parent", UntaggedValue::int(parent_pid))
}
let result = sys.get_processes();
if let Ok(exe) = process.exe().await {
dict.insert_untagged("exe", UntaggedValue::string(exe.to_string_lossy()))
}
for (pid, process) in result.iter() {
let mut dict = TaggedDictBuilder::new(&tag);
dict.insert_untagged("pid", UntaggedValue::int(*pid));
dict.insert_untagged("name", UntaggedValue::string(process.name()));
dict.insert_untagged(
"status",
UntaggedValue::string(format!("{:?}", process.status())),
);
dict.insert_untagged(
"cpu",
UntaggedValue::decimal_from_float(process.cpu_usage() as f64, tag.span),
);
dict.insert_untagged("mem", UntaggedValue::filesize(process.memory()));
dict.insert_untagged("virtual", UntaggedValue::filesize(process.virtual_memory()));
#[cfg(not(windows))]
{
if let Ok(command) = process.command().await {
dict.insert_untagged(
"command",
UntaggedValue::string(command.to_os_string().to_string_lossy()),
);
}
}
if long {
if let Some(parent) = process.parent() {
dict.insert_untagged("parent", UntaggedValue::int(parent));
}
output.push(dict.into_value());
dict.insert_untagged("exe", UntaggedValue::filepath(process.exe()));
dict.insert_untagged("command", UntaggedValue::string(process.cmd().join(" ")));
}
output.push(dict.into_value());
}
Ok(output)

View File

@ -15,15 +15,9 @@ nu-plugin = {path = "../nu-plugin", version = "0.25.2"}
nu-protocol = {path = "../nu-protocol", version = "0.25.2"}
nu-source = {path = "../nu-source", version = "0.25.2"}
battery = "0.7.6"
futures = {version = "0.3.5", features = ["compat", "io-compat"]}
futures-util = "0.3.5"
num-bigint = "0.3.0"
[dependencies.heim]
default-features = false
version = "0.1.0-beta.3"
features = ["host", "cpu", "memory", "disk", "net", "sensors"]
sysinfo = "0.15.9"
[build-dependencies]

View File

@ -1,11 +1,6 @@
use futures_util::StreamExt;
use heim::units::{frequency, information, thermodynamic_temperature, time};
use heim::{disk, host, memory, net, sensors};
use nu_errors::ShellError;
use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value};
use nu_source::Tag;
use num_bigint::BigInt;
use std::ffi::OsStr;
use sysinfo::{ComponentExt, DiskExt, NetworkExt, ProcessorExt, System, SystemExt, UserExt};
#[derive(Default)]
pub struct Sys;
@ -16,225 +11,25 @@ impl Sys {
}
}
async fn cpu(tag: Tag) -> Option<Value> {
let span = tag.span;
match futures::future::try_join(heim::cpu::logical_count(), heim::cpu::frequency()).await {
Ok((num_cpu, cpu_speed)) => {
let mut cpu_idx = TaggedDictBuilder::with_capacity(tag, 4);
cpu_idx.insert_untagged("cores", UntaggedValue::int(num_cpu));
pub fn disks(sys: &mut System, tag: Tag) -> Option<UntaggedValue> {
sys.refresh_disks();
let current_speed =
(cpu_speed.current().get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0)
.round()
/ 100.0;
cpu_idx.insert_untagged(
"current ghz",
UntaggedValue::decimal_from_float(current_speed, span),
);
if let Some(min_speed) = cpu_speed.min() {
let min_speed =
(min_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round()
/ 100.0;
cpu_idx.insert_untagged(
"min ghz",
UntaggedValue::decimal_from_float(min_speed, span),
);
}
if let Some(max_speed) = cpu_speed.max() {
let max_speed =
(max_speed.get::<frequency::hertz>() as f64 / 1_000_000_000.0 * 100.0).round()
/ 100.0;
cpu_idx.insert_untagged(
"max ghz",
UntaggedValue::decimal_from_float(max_speed, span),
);
}
Some(cpu_idx.into_value())
}
Err(_) => None,
}
}
async fn mem(tag: Tag) -> Value {
let mut dict = TaggedDictBuilder::with_capacity(tag, 4);
let (memory_result, swap_result) =
futures::future::join(memory::memory(), memory::swap()).await;
if let Ok(memory) = memory_result {
dict.insert_untagged(
"total",
UntaggedValue::filesize(memory.total().get::<information::byte>()),
);
dict.insert_untagged(
"free",
UntaggedValue::filesize(memory.free().get::<information::byte>()),
);
}
if let Ok(swap) = swap_result {
dict.insert_untagged(
"swap total",
UntaggedValue::filesize(swap.total().get::<information::byte>()),
);
dict.insert_untagged(
"swap free",
UntaggedValue::filesize(swap.free().get::<information::byte>()),
);
}
dict.into_value()
}
async fn host(tag: Tag) -> Result<Value, ShellError> {
let mut dict = TaggedDictBuilder::with_capacity(&tag, 6);
let (platform_result, uptime_result) =
futures::future::join(host::platform(), host::uptime()).await;
// OS
if let Ok(platform) = platform_result {
dict.insert_untagged("name", UntaggedValue::string(platform.system()));
dict.insert_untagged("release", UntaggedValue::string(platform.release()));
dict.insert_untagged("version", UntaggedValue::string(platform.version()));
dict.insert_untagged("hostname", UntaggedValue::string(platform.hostname()));
dict.insert_untagged(
"arch",
UntaggedValue::string(platform.architecture().as_str()),
);
}
// Uptime
if let Ok(uptime) = uptime_result {
let uptime = uptime.get::<time::nanosecond>().round() as i64;
dict.insert_untagged("uptime", UntaggedValue::duration(BigInt::from(uptime)));
}
// Sessions
// note: the heim host module has nomenclature "users"
let users = host::users().await.map_err(|_| {
ShellError::labeled_error("Unable to get users", "could not load users", tag.span)
})?;
futures::pin_mut!(users);
let mut user_vec = vec![];
while let Some(user) = users.next().await {
if let Ok(user) = user {
user_vec.push(Value {
value: UntaggedValue::string(user.username()),
tag: tag.clone(),
});
}
}
let user_list = UntaggedValue::Table(user_vec);
dict.insert_untagged("sessions", user_list);
Ok(dict.into_value())
}
async fn disks(tag: Tag) -> Result<Option<UntaggedValue>, ShellError> {
let mut output = vec![];
let partitions = disk::partitions_physical().await.map_err(|_| {
ShellError::labeled_error(
"Unable to get disk list",
"could not load disk list",
tag.span,
)
})?;
futures::pin_mut!(partitions);
while let Some(part) = partitions.next().await {
if let Ok(part) = part {
let mut dict = TaggedDictBuilder::with_capacity(&tag, 6);
dict.insert_untagged(
"device",
UntaggedValue::string(
part.device()
.unwrap_or_else(|| OsStr::new("N/A"))
.to_string_lossy(),
),
);
dict.insert_untagged("type", UntaggedValue::string(part.file_system().as_str()));
dict.insert_untagged(
"mount",
UntaggedValue::string(part.mount_point().to_string_lossy()),
);
if let Ok(usage) = disk::usage(part.mount_point().to_path_buf()).await {
dict.insert_untagged(
"total",
UntaggedValue::filesize(usage.total().get::<information::byte>()),
);
dict.insert_untagged(
"used",
UntaggedValue::filesize(usage.used().get::<information::byte>()),
);
dict.insert_untagged(
"free",
UntaggedValue::filesize(usage.free().get::<information::byte>()),
);
}
output.push(dict.into_value());
}
for disk in sys.get_disks() {
let mut dict = TaggedDictBuilder::new(&tag);
dict.insert_untagged(
"device",
UntaggedValue::string(disk.get_name().to_string_lossy()),
);
dict.insert_untagged(
"type",
UntaggedValue::string(String::from_utf8_lossy(disk.get_file_system())),
);
dict.insert_untagged("mount", UntaggedValue::filepath(disk.get_mount_point()));
dict.insert_untagged("total", UntaggedValue::filesize(disk.get_total_space()));
dict.insert_untagged("free", UntaggedValue::filesize(disk.get_available_space()));
output.push(dict.into_value());
}
if !output.is_empty() {
Ok(Some(UntaggedValue::Table(output)))
} else {
Ok(None)
}
}
async fn battery(tag: Tag) -> Option<UntaggedValue> {
let mut output = vec![];
let span = tag.span;
if let Ok(manager) = battery::Manager::new() {
if let Ok(batteries) = manager.batteries() {
for battery in batteries {
if let Ok(battery) = battery {
let mut dict = TaggedDictBuilder::new(&tag);
if let Some(vendor) = battery.vendor() {
dict.insert_untagged("vendor", UntaggedValue::string(vendor));
}
if let Some(model) = battery.model() {
dict.insert_untagged("model", UntaggedValue::string(model));
}
if let Some(cycles) = battery.cycle_count() {
dict.insert_untagged("cycles", UntaggedValue::int(cycles));
}
if let Some(time_to_full) = battery.time_to_full() {
dict.insert_untagged(
"mins to full",
UntaggedValue::decimal_from_float(
time_to_full.get::<battery::units::time::minute>() as f64,
span,
),
);
}
if let Some(time_to_empty) = battery.time_to_empty() {
dict.insert_untagged(
"mins to empty",
UntaggedValue::decimal_from_float(
time_to_empty.get::<battery::units::time::minute>() as f64,
span,
),
);
}
output.push(dict.into_value());
}
}
}
}
if !output.is_empty() {
Some(UntaggedValue::Table(output))
} else {
@ -242,54 +37,21 @@ async fn battery(tag: Tag) -> Option<UntaggedValue> {
}
}
async fn temp(tag: Tag) -> Option<UntaggedValue> {
pub fn net(sys: &mut System, tag: Tag) -> Option<UntaggedValue> {
sys.refresh_networks();
let mut output = vec![];
let span = tag.span;
for (iface, data) in sys.get_networks() {
let mut dict = TaggedDictBuilder::new(&tag);
dict.insert_untagged("name", UntaggedValue::string(iface));
dict.insert_untagged(
"sent",
UntaggedValue::filesize(data.get_total_transmitted()),
);
dict.insert_untagged("recv", UntaggedValue::filesize(data.get_total_received()));
let sensors = sensors::temperatures();
futures::pin_mut!(sensors);
while let Some(sensor) = sensors.next().await {
if let Ok(sensor) = sensor {
let mut dict = TaggedDictBuilder::new(&tag);
dict.insert_untagged("unit", UntaggedValue::string(sensor.unit()));
if let Some(label) = sensor.label() {
dict.insert_untagged("label", UntaggedValue::string(label));
}
dict.insert_untagged(
"temp",
UntaggedValue::decimal_from_float(
sensor
.current()
.get::<thermodynamic_temperature::degree_celsius>()
as f64,
span,
),
);
if let Some(high) = sensor.high() {
dict.insert_untagged(
"high",
UntaggedValue::decimal_from_float(
high.get::<thermodynamic_temperature::degree_celsius>() as f64,
span,
),
);
}
if let Some(critical) = sensor.critical() {
dict.insert_untagged(
"critical",
UntaggedValue::decimal_from_float(
critical.get::<thermodynamic_temperature::degree_celsius>() as f64,
span,
),
);
}
output.push(dict.into_value());
}
output.push(dict.into_value());
}
if !output.is_empty() {
Some(UntaggedValue::Table(output))
} else {
@ -297,71 +59,136 @@ async fn temp(tag: Tag) -> Option<UntaggedValue> {
}
}
async fn net(tag: Tag) -> Result<Option<UntaggedValue>, ShellError> {
pub fn cpu(sys: &mut System, tag: Tag) -> Option<UntaggedValue> {
sys.refresh_cpu();
let mut output = vec![];
let io_counters = net::io_counters().await.map_err(|_| {
ShellError::labeled_error(
"Unable to get network device list",
"could not load network device list",
tag.span,
)
})?;
for cpu in sys.get_processors() {
let mut dict = TaggedDictBuilder::new(&tag);
dict.insert_untagged("name", UntaggedValue::string(cpu.get_name()));
dict.insert_untagged("brand", UntaggedValue::string(cpu.get_brand()));
dict.insert_untagged("freq", UntaggedValue::int(cpu.get_frequency()));
futures::pin_mut!(io_counters);
while let Some(nic) = io_counters.next().await {
if let Ok(nic) = nic {
let mut network_idx = TaggedDictBuilder::with_capacity(&tag, 3);
network_idx.insert_untagged("name", UntaggedValue::string(nic.interface()));
network_idx.insert_untagged(
"sent",
UntaggedValue::filesize(nic.bytes_sent().get::<information::byte>()),
);
network_idx.insert_untagged(
"recv",
UntaggedValue::filesize(nic.bytes_recv().get::<information::byte>()),
);
output.push(network_idx.into_value());
}
output.push(dict.into_value());
}
if !output.is_empty() {
Ok(Some(UntaggedValue::Table(output)))
Some(UntaggedValue::Table(output))
} else {
Ok(None)
None
}
}
pub fn mem(sys: &mut System, tag: Tag) -> Option<UntaggedValue> {
sys.refresh_memory();
let mut dict = TaggedDictBuilder::new(tag);
let total_mem = sys.get_total_memory();
let free_mem = sys.get_free_memory();
let total_swap = sys.get_total_swap();
let free_swap = sys.get_free_swap();
dict.insert_untagged("total", UntaggedValue::filesize(total_mem));
dict.insert_untagged("free", UntaggedValue::filesize(free_mem));
dict.insert_untagged("swap total", UntaggedValue::filesize(total_swap));
dict.insert_untagged("swap free", UntaggedValue::filesize(free_swap));
Some(dict.into_untagged_value())
}
pub fn host(sys: &mut System, tag: Tag) -> Option<UntaggedValue> {
sys.refresh_users_list();
let mut dict = TaggedDictBuilder::new(&tag);
if let Some(name) = sys.get_name() {
dict.insert_untagged("name", UntaggedValue::string(name));
}
if let Some(version) = sys.get_version() {
dict.insert_untagged("version", UntaggedValue::string(version));
}
if let Some(hostname) = sys.get_host_name() {
dict.insert_untagged("hostname", UntaggedValue::string(hostname));
}
dict.insert_untagged(
"uptime",
UntaggedValue::duration(1000000000 * sys.get_uptime()),
);
let mut users = vec![];
for user in sys.get_users() {
let mut user_dict = TaggedDictBuilder::new(&tag);
user_dict.insert_untagged("name", UntaggedValue::string(user.get_name()));
let mut groups = vec![];
for group in user.get_groups() {
groups.push(UntaggedValue::string(group).into_value(&tag));
}
user_dict.insert_untagged("groups", UntaggedValue::Table(groups));
users.push(user_dict.into_value());
}
if !users.is_empty() {
dict.insert_untagged("sessions", UntaggedValue::Table(users));
}
Some(dict.into_untagged_value())
}
pub fn temp(sys: &mut System, tag: Tag) -> Option<UntaggedValue> {
sys.refresh_components();
sys.refresh_components_list();
let mut output = vec![];
for component in sys.get_components() {
let mut dict = TaggedDictBuilder::new(&tag);
dict.insert_untagged("unit", UntaggedValue::string(component.get_label()));
dict.insert_untagged(
"temp",
UntaggedValue::decimal_from_float(component.get_temperature() as f64, tag.span),
);
dict.insert_untagged(
"high",
UntaggedValue::decimal_from_float(component.get_max() as f64, tag.span),
);
if let Some(critical) = component.get_critical() {
dict.insert_untagged(
"critical",
UntaggedValue::decimal_from_float(critical as f64, tag.span),
);
}
output.push(dict.into_value());
}
if !output.is_empty() {
Some(UntaggedValue::Table(output))
} else {
None
}
}
pub async fn sysinfo(tag: Tag) -> Vec<Value> {
let mut sysinfo = TaggedDictBuilder::with_capacity(&tag, 7);
let mut sys = System::new_all();
let (host, cpu, disks, memory, temp) = futures::future::join5(
host(tag.clone()),
cpu(tag.clone()),
disks(tag.clone()),
mem(tag.clone()),
temp(tag.clone()),
)
.await;
let (net, battery) = futures::future::join(net(tag.clone()), battery(tag.clone())).await;
let mut sysinfo = TaggedDictBuilder::with_capacity(&tag, 6);
if let Ok(host) = host {
if let Some(host) = host(&mut sys, tag.clone()) {
sysinfo.insert_value("host", host);
}
if let Some(cpu) = cpu {
sysinfo.insert_value("cpu", cpu);
if let Some(cpus) = cpu(&mut sys, tag.clone()) {
sysinfo.insert_value("cpu", cpus);
}
if let Ok(Some(disks)) = disks {
sysinfo.insert_untagged("disks", disks);
if let Some(disks) = disks(&mut sys, tag.clone()) {
sysinfo.insert_value("disks", disks);
}
sysinfo.insert_value("mem", memory);
if let Some(temp) = temp {
sysinfo.insert_untagged("temp", temp);
if let Some(mem) = mem(&mut sys, tag.clone()) {
sysinfo.insert_value("mem", mem);
}
if let Ok(Some(net)) = net {
sysinfo.insert_untagged("net", net);
if let Some(temp) = temp(&mut sys, tag.clone()) {
sysinfo.insert_value("temp", temp);
}
if let Some(battery) = battery {
sysinfo.insert_untagged("battery", battery);
if let Some(net) = net(&mut sys, tag) {
sysinfo.insert_value("net", net);
}
vec![sysinfo.into_value()]