Skip to main content

fact_rs/
lib.rs

1pub mod components;
2
3pub mod filesystem;
4
5use crate::components::{cpu, kernel, memory, mount, network, os, uptime};
6use anyhow::Result;
7use rayon::prelude::*;
8use serde_json::{Map, Value};
9
10pub trait Collector: Send + Sync {
11    fn name(&self) -> &'static str;
12    fn collect(&self) -> Result<serde_json::Value>;
13}
14
15pub fn build() -> Result<Map<String, Value>> {
16    // Register all the components here. Each component
17    // implements the Component trait
18    let components: Vec<Box<dyn Collector>> = vec![
19        Box::new(kernel::KernelComponent::new()),
20        Box::new(cpu::CPUComponent::new()),
21        Box::new(memory::MemoryComponent::new()),
22        Box::new(os::OSComponent::new()),
23        Box::new(uptime::UptimeComponent::new()),
24        Box::new(network::NetworkComponent::new()),
25        Box::new(mount::MountComponent::new()),
26    ];
27
28    // Build all the components in parallel into pairs of information
29    let pairs: Vec<(String, Value)> = components
30        .par_iter()
31        .filter_map(|c| {
32            let name = c.name().to_string();
33            match c.collect() {
34                Ok(v) => Some((name, v)),
35                Err(e) => {
36                    tracing::warn!(component = %name, error = ?e, "collector failed");
37                    None
38                }
39            }
40        })
41        .collect();
42
43    // Collect all the pairs into the main facts structure
44    let facts: Map<String, Value> = pairs.into_iter().collect();
45    Ok(facts)
46}
47
48pub fn display(facts: Map<String, Value>) -> Result<()> {
49    let _j = serde_json::to_string(&Value::Object(facts))?;
50    println!("{}", _j);
51    Ok(())
52}
53
54pub fn run() -> Result<()> {
55    let facts = build()?;
56    display(facts)?;
57    Ok(())
58}