non zfs disk usage

This commit is contained in:
Robin Appelman 2021-03-24 22:50:03 +01:00
commit d798e23e48
3 changed files with 54 additions and 14 deletions

View file

@ -2,6 +2,7 @@ use color_eyre::eyre::WrapErr;
use color_eyre::Result; use color_eyre::Result;
use futures_util::future; use futures_util::future;
use futures_util::stream::{Stream, StreamExt}; use futures_util::stream::{Stream, StreamExt};
use heim::disk::{FileSystem, Partition};
use heim::sensors::TemperatureSensor; use heim::sensors::TemperatureSensor;
use heim::units::{information, ratio, thermodynamic_temperature}; use heim::units::{information, ratio, thermodynamic_temperature};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
@ -31,6 +32,13 @@ pub struct IOStats {
pub bytes_received: u64, pub bytes_received: u64,
} }
#[derive(Clone, Debug)]
pub struct DiskUsage {
pub name: String,
pub size: u64,
pub free: u64,
}
#[derive(Default)] #[derive(Default)]
pub struct Heim {} pub struct Heim {}
@ -113,4 +121,22 @@ impl Heim {
bytes_received: disk.read_bytes().get::<information::byte>(), bytes_received: disk.read_bytes().get::<information::byte>(),
})) }))
} }
pub async fn disk_usage(&self) -> Result<impl Stream<Item = DiskUsage>> {
Ok(heim::disk::partitions_physical()
.await?
.filter_map(|result| future::ready(result.ok()))
.filter(|partition: &Partition| {
future::ready(!partition.file_system().eq(&FileSystem::Zfs))
})
.filter_map(|partition: Partition| async move {
let name = partition.mount_point().to_string_lossy().to_string();
partition.usage().await.ok().map(|usage| (name, usage))
})
.map(|(mount_point, usage)| DiskUsage {
name: mount_point,
size: usage.total().get::<information::byte>(),
free: usage.free().get::<information::byte>(),
}))
}
} }

View file

@ -1,8 +1,8 @@
mod heim; pub mod heim;
mod zfs; mod zfs;
use crate::heim::{Heim, IOStats, Memory, TemperatureLabel}; use crate::heim::{DiskUsage, Heim, IOStats, Memory, TemperatureLabel};
use crate::zfs::{ZfsPool, ZFS}; use crate::zfs::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};
@ -24,14 +24,15 @@ 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, temperatures, disks): ( let (hostname, pools, cpu, memory, network, temperatures, disks, disk_usage): (
String, String,
Vec<ZfsPool>, Vec<DiskUsage>,
f32, f32,
Memory, Memory,
_, _,
HashMap<TemperatureLabel, f32>, HashMap<TemperatureLabel, f32>,
_, _,
_,
) = try_join! { ) = try_join! {
heim.hostname(), heim.hostname(),
zfs.pools(), zfs.pools(),
@ -40,9 +41,11 @@ async fn get_metrics(heim: Heim, zfs: ZFS) -> Result<String, ReportRejection> {
heim.network_stats(), heim.network_stats(),
heim.temperatures(), heim.temperatures(),
heim.disk_stats(), heim.disk_stats(),
heim.disk_usage(),
}?; }?;
pin_mut!(network); pin_mut!(network);
pin_mut!(disks); pin_mut!(disks);
pin_mut!(disk_usage);
let mut result = String::with_capacity(256); let mut result = String::with_capacity(256);
writeln!(&mut result, "cpu_usage{{host=\"{}\"}} {:.1}", hostname, cpu).ok(); writeln!(&mut result, "cpu_usage{{host=\"{}\"}} {:.1}", hostname, cpu).ok();
writeln!( writeln!(
@ -111,6 +114,23 @@ async fn get_metrics(heim: Heim, zfs: ZFS) -> Result<String, ReportRejection> {
.ok(); .ok();
} }
} }
while let Some(disk) = disk_usage.next().await {
let disk: DiskUsage = disk;
if disk.size > 0 {
writeln!(
&mut result,
"disk_size{{host=\"{}\", disk=\"{}\"}} {}",
hostname, disk.name, disk.size
)
.ok();
writeln!(
&mut result,
"disk_free{{host=\"{}\", disk=\"{}\"}} {}",
hostname, disk.name, disk.free
)
.ok();
}
}
for (label, temp) in temperatures { for (label, temp) in temperatures {
writeln!( writeln!(
&mut result, &mut result,

View file

@ -1,19 +1,13 @@
use crate::heim::DiskUsage;
use color_eyre::Result; use color_eyre::Result;
use std::process::Command; use std::process::Command;
use tokio::task::spawn_blocking; use tokio::task::spawn_blocking;
#[derive(Clone, Debug)]
pub struct ZfsPool {
pub name: String,
pub size: usize,
pub free: usize,
}
#[derive(Default)] #[derive(Default)]
pub struct ZFS; pub struct ZFS;
impl ZFS { impl ZFS {
pub async fn pools(self) -> Result<Vec<ZfsPool>> { pub async fn pools(self) -> Result<Vec<DiskUsage>> {
spawn_blocking(move || { spawn_blocking(move || {
let mut z = Command::new("zpool"); let mut z = Command::new("zpool");
z.args(&["list", "-p", "-H", "-o", "name,size,free"]); z.args(&["list", "-p", "-H", "-o", "name,size,free"]);
@ -30,7 +24,7 @@ impl ZFS {
let name = parts.next()?.to_string(); let name = parts.next()?.to_string();
let size = parts.next()?.parse().ok()?; let size = parts.next()?.parse().ok()?;
let free = parts.next()?.parse().ok()?; let free = parts.next()?.parse().ok()?;
Some(ZfsPool { name, size, free }) Some(DiskUsage { name, size, free })
}) })
.collect()) .collect())
} else { } else {