prepare for windows impl

This commit is contained in:
Robin Appelman 2023-05-17 22:55:01 +02:00
commit d12b70d11e
16 changed files with 550 additions and 279 deletions

View file

@ -1,27 +1,28 @@
pub mod disk;
pub mod docker;
pub mod gpu;
pub mod hwmon;
pub mod power;
pub mod sensors;
use crate::disk::zfs::pools;
use crate::disk::*;
use crate::sensors::*;
use std::ffi::NulError;
use std::fmt::Write;
use std::io;
use std::num::{ParseFloatError, ParseIntError};
use std::str::Utf8Error;
use std::sync::Mutex;
use sysconf::SysconfError;
use std::string::FromUtf8Error;
pub mod data;
pub mod docker;
#[cfg(not(feature = "sysinfo"))]
mod linux;
#[cfg(feature = "sysinfo")]
mod sys;
#[cfg(not(feature = "sysinfo"))]
pub use linux::{get_metrics, Sensors};
#[cfg(feature = "sysinfo")]
pub use sys::{get_metrics, Sensors};
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
Io(#[from] io::Error),
#[error("Unsupported sysconf")]
Sysconf(SysconfError),
Io(#[from] std::io::Error),
#[error("{0}")]
Other(String),
#[error("Non UTF8 hostname")]
InvalidHostName,
#[error(transparent)]
@ -36,98 +37,14 @@ pub enum Error {
StatVfs,
}
impl From<SysconfError> for Error {
fn from(value: SysconfError) -> Self {
Error::Sysconf(value)
impl From<FromUtf8Error> for Error {
fn from(err: FromUtf8Error) -> Self {
Self::InvalidStringData(err.utf8_error())
}
}
pub type Result<T, E = Error> = std::result::Result<T, E>;
pub struct Sensors {
pub hostname: String,
cpu: Mutex<CpuTimeSource>,
temp: Mutex<TemperatureSource>,
net: Mutex<NetworkSource>,
mem: Mutex<MemorySource>,
disk_stats: Mutex<DiskStatSource>,
disk_usage: Mutex<DiskUsageSource>,
}
impl Sensors {
pub fn new() -> Result<Sensors> {
Ok(Sensors {
hostname: hostname()?,
cpu: Mutex::new(CpuTimeSource::new()?),
temp: Mutex::new(TemperatureSource::new()?),
net: Mutex::new(NetworkSource::new()?),
mem: Mutex::new(MemorySource::new()?),
disk_stats: Mutex::new(DiskStatSource::new()?),
disk_usage: Mutex::new(DiskUsageSource::new()?),
})
}
}
pub fn get_metrics(sensors: &Sensors) -> Result<String> {
let hostname = &sensors.hostname;
let mut disk_source = sensors.disk_stats.lock().unwrap();
let mut disk_usage_source = sensors.disk_usage.lock().unwrap();
let disks = disk_source.read()?;
let disk_usage = disk_usage_source.read()?;
let cpu = sensors.cpu.lock().unwrap().read()?;
let memory = sensors.mem.lock().unwrap().read()?;
let temperatures = sensors.temp.lock().unwrap().read()?;
let mut net = sensors.net.lock().unwrap();
let networks = net.read()?;
let pools = pools();
let mut result = String::with_capacity(256);
cpu.write(&mut result, &hostname);
memory.write(&mut result, &hostname);
for pool in pools {
writeln!(
&mut result,
"zfs_pool_size{{host=\"{}\", pool=\"{}\"}} {}",
hostname, pool.name, pool.size
)
.ok();
writeln!(
&mut result,
"zfs_pool_free{{host=\"{}\", pool=\"{}\"}} {}",
hostname, pool.name, pool.free
)
.ok();
}
for network in networks {
if let Ok(network) = network {
network.write(&mut result, &hostname);
}
}
for disk in disks {
if let Ok(disk) = disk {
disk.write(&mut result, hostname);
}
}
for disk in disk_usage {
if let Ok(disk) = disk {
disk.write(&mut result, hostname);
}
}
for (label, temp) in temperatures {
if temp != 0.0 {
writeln!(
&mut result,
"temperature{{host=\"{}\", sensor=\"{}\"}} {:.1}",
hostname, label, temp
)
.ok();
}
}
Ok(result)
}
pub trait SensorData {
/// Write sensor data in prometheus compatible format
fn write<W: Write>(&self, w: W, hostname: &str);
@ -147,3 +64,9 @@ pub trait MultiSensorSource {
fn read(&mut self) -> Result<Self::Iter<'_>>;
}
pub fn hostname() -> Result<String> {
hostname::get()?
.into_string()
.map_err(|_| Error::InvalidHostName)
}