mirror of
https://codeberg.org/icewind/palantir.git
synced 2026-06-03 18:24:08 +02:00
crimes to async
This commit is contained in:
parent
8bc385c143
commit
cd6e103337
5 changed files with 107 additions and 64 deletions
27
Cargo.lock
generated
27
Cargo.lock
generated
|
|
@ -1241,9 +1241,11 @@ dependencies = [
|
|||
"color-eyre",
|
||||
"ctrlc",
|
||||
"dotenv",
|
||||
"futures-lite",
|
||||
"futures-util",
|
||||
"heim",
|
||||
"libzetta",
|
||||
"parse-display",
|
||||
"tokio",
|
||||
"warp",
|
||||
]
|
||||
|
|
@ -1254,6 +1256,31 @@ version = "2.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
|
||||
|
||||
[[package]]
|
||||
name = "parse-display"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7271152b3c46c07c729698e7a5248e2744466b3446d222c97a0b1315925a97b1"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"parse-display-derive",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-display-derive"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6a9f3e41b237b77c99c09686481c235964ff5878229412b226c451f3e809f4f"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"regex-syntax",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
|
|
|
|||
|
|
@ -12,4 +12,6 @@ warp = "0.3"
|
|||
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
||||
ctrlc = { version = "3", features = ["termination"] }
|
||||
dotenv = "0.15"
|
||||
futures-util = "0.3"
|
||||
futures-util = "0.3"
|
||||
futures-lite = "1"
|
||||
parse-display = "0.4"
|
||||
57
src/heim.rs
57
src/heim.rs
|
|
@ -1,21 +1,20 @@
|
|||
use color_eyre::eyre::WrapErr;
|
||||
use color_eyre::Result;
|
||||
use futures_util::future;
|
||||
use futures_util::stream::{Stream, StreamExt};
|
||||
use futures_util::{future, TryStreamExt};
|
||||
use heim::sensors::TemperatureSensor;
|
||||
use heim::units::{information, ratio, thermodynamic_temperature};
|
||||
use parse_display::Display;
|
||||
use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
use tokio::time::sleep;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq, Display)]
|
||||
#[display(style = "lowercase")]
|
||||
pub enum TemperatureLabel {
|
||||
CPU,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Temperature {
|
||||
pub sensor: TemperatureLabel,
|
||||
pub temperature: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Memory {
|
||||
pub total: u64,
|
||||
|
|
@ -34,26 +33,28 @@ pub struct NetworkStats {
|
|||
pub struct Heim {}
|
||||
|
||||
impl Heim {
|
||||
#[allow(dead_code)]
|
||||
pub async fn temperatures() -> Result<Vec<Temperature>> {
|
||||
let mut temperatures = Vec::new();
|
||||
let results: Vec<_> = heim::sensors::temperatures().try_collect().await?;
|
||||
// let results: Vec<TemperatureSensor> = Vec::new();
|
||||
// pin_mut!(results);
|
||||
for sensor in results {
|
||||
if let Some(temp) = match (sensor.unit(), sensor.label()) {
|
||||
("k10temp", Some("Tdie")) => Some(Temperature {
|
||||
sensor: TemperatureLabel::CPU,
|
||||
temperature: sensor
|
||||
.current()
|
||||
.get::<thermodynamic_temperature::degree_celsius>(),
|
||||
}),
|
||||
_ => None,
|
||||
} {
|
||||
temperatures.push(temp);
|
||||
}
|
||||
}
|
||||
Ok(temperatures)
|
||||
pub async fn temperatures(&self) -> Result<HashMap<TemperatureLabel, f32>> {
|
||||
// ugly workaround problems between async-fs and tokio
|
||||
let results = tokio::task::spawn_blocking(|| {
|
||||
futures_lite::future::block_on(
|
||||
heim::sensors::temperatures()
|
||||
.collect::<Vec<Result<TemperatureSensor, heim::Error>>>(),
|
||||
)
|
||||
})
|
||||
.await
|
||||
.wrap_err("Failed to resolve future")?
|
||||
.into_iter()
|
||||
.filter_map(|result| result.ok())
|
||||
.filter_map(|sensor| match (sensor.unit(), sensor.label()) {
|
||||
("k10temp", Some("Tdie")) => Some((
|
||||
TemperatureLabel::CPU,
|
||||
sensor
|
||||
.current()
|
||||
.get::<thermodynamic_temperature::degree_celsius>(),
|
||||
)),
|
||||
_ => None,
|
||||
});
|
||||
Ok(results.collect())
|
||||
}
|
||||
|
||||
pub async fn memory(&self) -> Result<Memory> {
|
||||
|
|
|
|||
55
src/main.rs
55
src/main.rs
|
|
@ -1,11 +1,12 @@
|
|||
mod heim;
|
||||
mod zfs;
|
||||
|
||||
use crate::heim::{Heim, Memory, NetworkStats};
|
||||
use crate::heim::{Heim, Memory, NetworkStats, TemperatureLabel};
|
||||
use crate::zfs::{ZfsPool, ZFS};
|
||||
use color_eyre::{Report, Result};
|
||||
use futures_util::stream::StreamExt;
|
||||
use futures_util::{pin_mut, try_join};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Write;
|
||||
use warp::reject::Reject;
|
||||
use warp::{Filter, Rejection};
|
||||
|
|
@ -15,6 +16,7 @@ struct ReportRejection(Report);
|
|||
|
||||
impl From<Report> for ReportRejection {
|
||||
fn from(report: Report) -> Self {
|
||||
eprintln!("{:#}", report);
|
||||
ReportRejection(report)
|
||||
}
|
||||
}
|
||||
|
|
@ -22,16 +24,24 @@ impl From<Report> for ReportRejection {
|
|||
impl Reject for ReportRejection {}
|
||||
|
||||
async fn get_metrics(heim: Heim, zfs: ZFS) -> Result<String, ReportRejection> {
|
||||
let (hostname, pools, cpu, memory, network): (String, Vec<ZfsPool>, f32, Memory, _) = try_join! {
|
||||
let (hostname, pools, cpu, memory, network, temperatures): (
|
||||
String,
|
||||
Vec<ZfsPool>,
|
||||
f32,
|
||||
Memory,
|
||||
_,
|
||||
HashMap<TemperatureLabel, f32>,
|
||||
) = try_join! {
|
||||
heim.hostname(),
|
||||
zfs.pools(),
|
||||
heim.cpu_usage(),
|
||||
heim.memory(),
|
||||
heim.network_stats(),
|
||||
heim.temperatures(),
|
||||
}?;
|
||||
pin_mut!(network);
|
||||
let mut result = String::with_capacity(256);
|
||||
writeln!(&mut result, "cpu_usage{{host=\"{}\"}} {}", hostname, cpu).ok();
|
||||
writeln!(&mut result, "cpu_usage{{host=\"{}\"}} {:.1}", hostname, cpu).ok();
|
||||
writeln!(
|
||||
&mut result,
|
||||
"memory_total{{host=\"{}\"}} {}",
|
||||
|
|
@ -65,31 +75,30 @@ async fn get_metrics(heim: Heim, zfs: ZFS) -> Result<String, ReportRejection> {
|
|||
.ok();
|
||||
}
|
||||
while let Some(network) = network.next().await {
|
||||
let network: NetworkStats = network;
|
||||
if network.bytes_received > 0 || network.bytes_sent > 0 {
|
||||
let network: NetworkStats = network;
|
||||
writeln!(
|
||||
&mut result,
|
||||
"net_sent{{host=\"{}\", network=\"{}\"}} {}",
|
||||
hostname, network.interface, network.bytes_sent
|
||||
)
|
||||
.ok();
|
||||
writeln!(
|
||||
&mut result,
|
||||
"net_received{{host=\"{}\", network=\"{}\"}} {}",
|
||||
hostname, network.interface, network.bytes_received
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
for (label, temp) in temperatures {
|
||||
writeln!(
|
||||
&mut result,
|
||||
"net_sent{{host=\"{}\", network=\"{}\"}} {}",
|
||||
hostname, network.interface, network.bytes_sent
|
||||
)
|
||||
.ok();
|
||||
writeln!(
|
||||
&mut result,
|
||||
"net_received{{host=\"{}\", network=\"{}\"}} {}",
|
||||
hostname, network.interface, network.bytes_received
|
||||
"temperature{{host=\"{}\", sensor=\"{}\"}} {:.1}",
|
||||
hostname, label, temp
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
// haunted ↓
|
||||
// for temperature in Heim::temperatures().await? {
|
||||
// match temperature.sensor {
|
||||
// TemperatureLabel::CPU => writeln!(
|
||||
// &mut result,
|
||||
// "temperature{{host=\"{}\", sensor=\"cpu\"}} {}",
|
||||
// hostname, temperature.temperature
|
||||
// )
|
||||
// .ok(),
|
||||
// };
|
||||
// }
|
||||
Result::<_, ReportRejection>::Ok(result)
|
||||
}
|
||||
|
||||
|
|
|
|||
28
src/zfs.rs
28
src/zfs.rs
|
|
@ -1,5 +1,6 @@
|
|||
use color_eyre::Result;
|
||||
use libzetta::zpool::{ZpoolEngine, ZpoolOpen3};
|
||||
use tokio::task::spawn_blocking;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ZfsPool {
|
||||
|
|
@ -21,18 +22,21 @@ impl Default for ZFS {
|
|||
}
|
||||
|
||||
impl ZFS {
|
||||
pub async fn pools(&self) -> Result<Vec<ZfsPool>> {
|
||||
let pools = self.engine.all()?;
|
||||
pools
|
||||
.into_iter()
|
||||
.map(|pool| {
|
||||
let props = self.engine.read_properties(pool.name())?;
|
||||
Ok(ZfsPool {
|
||||
name: pool.name().to_string(),
|
||||
size: *props.size(),
|
||||
free: *props.size() * (*props.capacity() as usize) / 100,
|
||||
pub async fn pools(self) -> Result<Vec<ZfsPool>> {
|
||||
spawn_blocking(move || {
|
||||
let pools = self.engine.all()?;
|
||||
pools
|
||||
.into_iter()
|
||||
.map(|pool| {
|
||||
let props = self.engine.read_properties(pool.name())?;
|
||||
Ok(ZfsPool {
|
||||
name: pool.name().to_string(),
|
||||
size: *props.size(),
|
||||
free: *props.size() * (*props.capacity() as usize) / 100,
|
||||
})
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
.collect()
|
||||
})
|
||||
.await?
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue