use async_graphql::Object;
use crate::{
event::{Metric, MetricValue},
sources::host_metrics,
};
pub struct MemoryMetrics(Vec<Metric>);
#[Object]
impl MemoryMetrics {
async fn total_bytes(&self) -> f64 {
filter_host_metric(&self.0, "memory_total_bytes")
}
async fn free_bytes(&self) -> f64 {
filter_host_metric(&self.0, "memory_free_bytes")
}
async fn available_bytes(&self) -> f64 {
filter_host_metric(&self.0, "memory_available_bytes")
}
async fn active_bytes(&self) -> Option<f64> {
if cfg!(any(target_os = "linux", target_os = "macos")) {
Some(filter_host_metric(&self.0, "memory_active_bytes"))
} else {
None
}
}
async fn buffers_bytes(&self) -> Option<f64> {
if cfg!(target_os = "linux") {
Some(filter_host_metric(&self.0, "memory_buffers_bytes"))
} else {
None
}
}
async fn cached_bytes(&self) -> Option<f64> {
if cfg!(target_os = "linux") {
Some(filter_host_metric(&self.0, "memory_cached_bytes"))
} else {
None
}
}
async fn shared_bytes(&self) -> Option<f64> {
if cfg!(target_os = "linux") {
Some(filter_host_metric(&self.0, "memory_shared_bytes"))
} else {
None
}
}
async fn used_bytes(&self) -> Option<f64> {
if cfg!(target_os = "linux") {
Some(filter_host_metric(&self.0, "memory_used_bytes"))
} else {
None
}
}
async fn inactive_bytes(&self) -> Option<f64> {
if cfg!(target_os = "macos") {
Some(filter_host_metric(&self.0, "memory_inactive_bytes"))
} else {
None
}
}
async fn wired_bytes(&self) -> Option<f64> {
if cfg!(target_os = "macos") {
Some(filter_host_metric(&self.0, "memory_wired_bytes"))
} else {
None
}
}
}
pub struct SwapMetrics(Vec<Metric>);
#[Object]
impl SwapMetrics {
async fn free_bytes(&self) -> f64 {
filter_host_metric(&self.0, "memory_swap_free_bytes")
}
async fn total_bytes(&self) -> f64 {
filter_host_metric(&self.0, "memory_swap_total_bytes")
}
async fn used_bytes(&self) -> f64 {
filter_host_metric(&self.0, "memory_swap_used_bytes")
}
async fn swapped_in_bytes_total(&self) -> Option<f64> {
if cfg!(not(windows)) {
Some(filter_host_metric(&self.0, "memory_swapped_in_bytes_total"))
} else {
None
}
}
async fn swapped_out_bytes_total(&self) -> Option<f64> {
if cfg!(not(windows)) {
Some(filter_host_metric(
&self.0,
"memory_swapped_out_bytes_total",
))
} else {
None
}
}
}
pub struct CpuMetrics(Vec<Metric>);
#[Object]
impl CpuMetrics {
async fn cpu_seconds_total(&self) -> f64 {
filter_host_metric(&self.0, "cpu_seconds_total")
}
}
pub struct LoadAverageMetrics(Vec<Metric>);
#[Object]
impl LoadAverageMetrics {
async fn load1(&self) -> f64 {
filter_host_metric(&self.0, "load1")
}
async fn load5(&self) -> f64 {
filter_host_metric(&self.0, "load5")
}
async fn load15(&self) -> f64 {
filter_host_metric(&self.0, "load15")
}
}
pub struct NetworkMetrics(Vec<Metric>);
#[Object]
impl NetworkMetrics {
async fn receive_bytes_total(&self) -> f64 {
filter_host_metric(&self.0, "network_receive_bytes_total")
}
async fn receive_errs_total(&self) -> f64 {
filter_host_metric(&self.0, "network_receive_errs_total")
}
async fn receive_packets_total(&self) -> f64 {
filter_host_metric(&self.0, "network_receive_packets_total")
}
async fn transmit_bytes_total(&self) -> f64 {
filter_host_metric(&self.0, "network_transmit_bytes_total")
}
async fn transmit_errs_total(&self) -> f64 {
filter_host_metric(&self.0, "network_transmit_errs_total")
}
async fn transmit_packets_drop_total(&self) -> Option<f64> {
if cfg!(any(target_os = "linux", windows)) {
Some(filter_host_metric(
&self.0,
"network_transmit_packets_drop_total",
))
} else {
None
}
}
async fn transmit_packets_total(&self) -> Option<f64> {
if cfg!(any(target_os = "linux", windows)) {
Some(filter_host_metric(
&self.0,
"network_transmit_packets_total",
))
} else {
None
}
}
}
pub struct FileSystemMetrics(Vec<Metric>);
#[Object]
impl FileSystemMetrics {
async fn free_bytes(&self) -> f64 {
filter_host_metric(&self.0, "filesystem_free_bytes")
}
async fn total_bytes(&self) -> f64 {
filter_host_metric(&self.0, "filesystem_total_bytes")
}
async fn used_bytes(&self) -> f64 {
filter_host_metric(&self.0, "filesystem_used_bytes")
}
}
pub struct DiskMetrics(Vec<Metric>);
#[Object]
impl DiskMetrics {
async fn read_bytes_total(&self) -> f64 {
filter_host_metric(&self.0, "disk_read_bytes_total")
}
async fn reads_completed_total(&self) -> f64 {
filter_host_metric(&self.0, "disk_reads_completed_total")
}
async fn written_bytes_total(&self) -> f64 {
filter_host_metric(&self.0, "disk_written_bytes_total")
}
async fn writes_completed_total(&self) -> f64 {
filter_host_metric(&self.0, "disk_writes_completed_total")
}
}
pub struct HostMetrics(host_metrics::HostMetrics);
impl HostMetrics {
pub fn new() -> Self {
let config = host_metrics::HostMetricsConfig::default();
Self(host_metrics::HostMetrics::new(config))
}
}
#[Object]
impl HostMetrics {
async fn memory(&self) -> MemoryMetrics {
let mut buffer = self.0.buffer();
self.0.memory_metrics(&mut buffer).await;
MemoryMetrics(buffer.metrics)
}
async fn swap(&self) -> SwapMetrics {
let mut buffer = self.0.buffer();
self.0.swap_metrics(&mut buffer).await;
SwapMetrics(buffer.metrics)
}
async fn cpu(&self) -> CpuMetrics {
let mut buffer = self.0.buffer();
self.0.cpu_metrics(&mut buffer).await;
CpuMetrics(buffer.metrics)
}
async fn load_average(&self) -> Option<LoadAverageMetrics> {
if cfg!(unix) {
let mut buffer = self.0.buffer();
self.0.loadavg_metrics(&mut buffer).await;
Some(LoadAverageMetrics(buffer.metrics))
} else {
None
}
}
async fn network(&self) -> NetworkMetrics {
let mut buffer = self.0.buffer();
self.0.network_metrics(&mut buffer).await;
NetworkMetrics(buffer.metrics)
}
async fn filesystem(&self) -> FileSystemMetrics {
let mut buffer = self.0.buffer();
self.0.filesystem_metrics(&mut buffer).await;
FileSystemMetrics(buffer.metrics)
}
async fn disk(&self) -> DiskMetrics {
let mut buffer = self.0.buffer();
self.0.disk_metrics(&mut buffer).await;
DiskMetrics(buffer.metrics)
}
}
fn filter_host_metric(metrics: &[Metric], name: &str) -> f64 {
metrics
.iter()
.find(|m| matches!(m.namespace(), Some(n) if n == "host") && m.name() == name)
.map(|m| match m.value() {
MetricValue::Gauge { value } => *value,
MetricValue::Counter { value } => *value,
_ => 0.00,
})
.unwrap_or_else(|| 0.00)
}