pub mod components;
pub mod filesystem;
use crate::components::{cpu, kernel, memory, mount, network, os, uptime};
use anyhow::Result;
use rayon::prelude::*;
use serde_json::{Map, Value};
pub trait Collector: Send + Sync {
fn name(&self) -> &'static str;
fn collect(&self) -> Result<serde_json::Value>;
}
pub fn build() -> Result<Map<String, Value>> {
let components: Vec<Box<dyn Collector>> = vec![
Box::new(kernel::KernelComponent::new()),
Box::new(cpu::CPUComponent::new()),
Box::new(memory::MemoryComponent::new()),
Box::new(os::OSComponent::new()),
Box::new(uptime::UptimeComponent::new()),
Box::new(network::NetworkComponent::new()),
Box::new(mount::MountComponent::new()),
];
let pairs: Vec<(String, Value)> = components
.par_iter()
.filter_map(|c| {
let name = c.name().to_string();
match c.collect() {
Ok(v) => Some((name, v)),
Err(e) => {
tracing::warn!(component = %name, error = ?e, "collector failed");
None
}
}
})
.collect();
let facts: Map<String, Value> = pairs.into_iter().collect();
Ok(facts)
}
pub fn display(facts: Map<String, Value>) -> Result<()> {
let _j = serde_json::to_string(&Value::Object(facts))?;
println!("{}", _j);
Ok(())
}
pub fn run() -> Result<()> {
let facts = build()?;
display(facts)?;
Ok(())
}