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",
|
"color-eyre",
|
||||||
"ctrlc",
|
"ctrlc",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
|
"futures-lite",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"heim",
|
"heim",
|
||||||
"libzetta",
|
"libzetta",
|
||||||
|
"parse-display",
|
||||||
"tokio",
|
"tokio",
|
||||||
"warp",
|
"warp",
|
||||||
]
|
]
|
||||||
|
|
@ -1254,6 +1256,31 @@ version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
|
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]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,5 @@ tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
||||||
ctrlc = { version = "3", features = ["termination"] }
|
ctrlc = { version = "3", features = ["termination"] }
|
||||||
dotenv = "0.15"
|
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 color_eyre::Result;
|
||||||
|
use futures_util::future;
|
||||||
use futures_util::stream::{Stream, StreamExt};
|
use futures_util::stream::{Stream, StreamExt};
|
||||||
use futures_util::{future, TryStreamExt};
|
use heim::sensors::TemperatureSensor;
|
||||||
use heim::units::{information, ratio, thermodynamic_temperature};
|
use heim::units::{information, ratio, thermodynamic_temperature};
|
||||||
|
use parse_display::Display;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Hash, Eq, PartialEq, Display)]
|
||||||
|
#[display(style = "lowercase")]
|
||||||
pub enum TemperatureLabel {
|
pub enum TemperatureLabel {
|
||||||
CPU,
|
CPU,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Temperature {
|
|
||||||
pub sensor: TemperatureLabel,
|
|
||||||
pub temperature: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Memory {
|
pub struct Memory {
|
||||||
pub total: u64,
|
pub total: u64,
|
||||||
|
|
@ -34,26 +33,28 @@ pub struct NetworkStats {
|
||||||
pub struct Heim {}
|
pub struct Heim {}
|
||||||
|
|
||||||
impl Heim {
|
impl Heim {
|
||||||
#[allow(dead_code)]
|
pub async fn temperatures(&self) -> Result<HashMap<TemperatureLabel, f32>> {
|
||||||
pub async fn temperatures() -> Result<Vec<Temperature>> {
|
// ugly workaround problems between async-fs and tokio
|
||||||
let mut temperatures = Vec::new();
|
let results = tokio::task::spawn_blocking(|| {
|
||||||
let results: Vec<_> = heim::sensors::temperatures().try_collect().await?;
|
futures_lite::future::block_on(
|
||||||
// let results: Vec<TemperatureSensor> = Vec::new();
|
heim::sensors::temperatures()
|
||||||
// pin_mut!(results);
|
.collect::<Vec<Result<TemperatureSensor, heim::Error>>>(),
|
||||||
for sensor in results {
|
)
|
||||||
if let Some(temp) = match (sensor.unit(), sensor.label()) {
|
})
|
||||||
("k10temp", Some("Tdie")) => Some(Temperature {
|
.await
|
||||||
sensor: TemperatureLabel::CPU,
|
.wrap_err("Failed to resolve future")?
|
||||||
temperature: sensor
|
.into_iter()
|
||||||
.current()
|
.filter_map(|result| result.ok())
|
||||||
.get::<thermodynamic_temperature::degree_celsius>(),
|
.filter_map(|sensor| match (sensor.unit(), sensor.label()) {
|
||||||
}),
|
("k10temp", Some("Tdie")) => Some((
|
||||||
_ => None,
|
TemperatureLabel::CPU,
|
||||||
} {
|
sensor
|
||||||
temperatures.push(temp);
|
.current()
|
||||||
}
|
.get::<thermodynamic_temperature::degree_celsius>(),
|
||||||
}
|
)),
|
||||||
Ok(temperatures)
|
_ => None,
|
||||||
|
});
|
||||||
|
Ok(results.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn memory(&self) -> Result<Memory> {
|
pub async fn memory(&self) -> Result<Memory> {
|
||||||
|
|
|
||||||
55
src/main.rs
55
src/main.rs
|
|
@ -1,11 +1,12 @@
|
||||||
mod heim;
|
mod heim;
|
||||||
mod zfs;
|
mod zfs;
|
||||||
|
|
||||||
use crate::heim::{Heim, Memory, NetworkStats};
|
use crate::heim::{Heim, Memory, NetworkStats, TemperatureLabel};
|
||||||
use crate::zfs::{ZfsPool, ZFS};
|
use crate::zfs::{ZfsPool, ZFS};
|
||||||
use color_eyre::{Report, Result};
|
use color_eyre::{Report, Result};
|
||||||
use futures_util::stream::StreamExt;
|
use futures_util::stream::StreamExt;
|
||||||
use futures_util::{pin_mut, try_join};
|
use futures_util::{pin_mut, try_join};
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use warp::reject::Reject;
|
use warp::reject::Reject;
|
||||||
use warp::{Filter, Rejection};
|
use warp::{Filter, Rejection};
|
||||||
|
|
@ -15,6 +16,7 @@ struct ReportRejection(Report);
|
||||||
|
|
||||||
impl From<Report> for ReportRejection {
|
impl From<Report> for ReportRejection {
|
||||||
fn from(report: Report) -> Self {
|
fn from(report: Report) -> Self {
|
||||||
|
eprintln!("{:#}", report);
|
||||||
ReportRejection(report)
|
ReportRejection(report)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -22,16 +24,24 @@ impl From<Report> for ReportRejection {
|
||||||
impl Reject for ReportRejection {}
|
impl Reject for ReportRejection {}
|
||||||
|
|
||||||
async fn get_metrics(heim: Heim, zfs: ZFS) -> Result<String, 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(),
|
heim.hostname(),
|
||||||
zfs.pools(),
|
zfs.pools(),
|
||||||
heim.cpu_usage(),
|
heim.cpu_usage(),
|
||||||
heim.memory(),
|
heim.memory(),
|
||||||
heim.network_stats(),
|
heim.network_stats(),
|
||||||
|
heim.temperatures(),
|
||||||
}?;
|
}?;
|
||||||
pin_mut!(network);
|
pin_mut!(network);
|
||||||
let mut result = String::with_capacity(256);
|
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!(
|
writeln!(
|
||||||
&mut result,
|
&mut result,
|
||||||
"memory_total{{host=\"{}\"}} {}",
|
"memory_total{{host=\"{}\"}} {}",
|
||||||
|
|
@ -65,31 +75,30 @@ async fn get_metrics(heim: Heim, zfs: ZFS) -> Result<String, ReportRejection> {
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
while let Some(network) = network.next().await {
|
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!(
|
writeln!(
|
||||||
&mut result,
|
&mut result,
|
||||||
"net_sent{{host=\"{}\", network=\"{}\"}} {}",
|
"temperature{{host=\"{}\", sensor=\"{}\"}} {:.1}",
|
||||||
hostname, network.interface, network.bytes_sent
|
hostname, label, temp
|
||||||
)
|
|
||||||
.ok();
|
|
||||||
writeln!(
|
|
||||||
&mut result,
|
|
||||||
"net_received{{host=\"{}\", network=\"{}\"}} {}",
|
|
||||||
hostname, network.interface, network.bytes_received
|
|
||||||
)
|
)
|
||||||
.ok();
|
.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)
|
Result::<_, ReportRejection>::Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
28
src/zfs.rs
28
src/zfs.rs
|
|
@ -1,5 +1,6 @@
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use libzetta::zpool::{ZpoolEngine, ZpoolOpen3};
|
use libzetta::zpool::{ZpoolEngine, ZpoolOpen3};
|
||||||
|
use tokio::task::spawn_blocking;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ZfsPool {
|
pub struct ZfsPool {
|
||||||
|
|
@ -21,18 +22,21 @@ impl Default for ZFS {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ZFS {
|
impl ZFS {
|
||||||
pub async fn pools(&self) -> Result<Vec<ZfsPool>> {
|
pub async fn pools(self) -> Result<Vec<ZfsPool>> {
|
||||||
let pools = self.engine.all()?;
|
spawn_blocking(move || {
|
||||||
pools
|
let pools = self.engine.all()?;
|
||||||
.into_iter()
|
pools
|
||||||
.map(|pool| {
|
.into_iter()
|
||||||
let props = self.engine.read_properties(pool.name())?;
|
.map(|pool| {
|
||||||
Ok(ZfsPool {
|
let props = self.engine.read_properties(pool.name())?;
|
||||||
name: pool.name().to_string(),
|
Ok(ZfsPool {
|
||||||
size: *props.size(),
|
name: pool.name().to_string(),
|
||||||
free: *props.size() * (*props.capacity() as usize) / 100,
|
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