capsula_capture_machine/
lib.rs

1mod config;
2mod error;
3
4use crate::error::MachineHookError;
5use capsula_core::captured::Captured;
6use capsula_core::error::CapsulaResult;
7use capsula_core::hook::{Hook, HookFactory, RuntimeParams};
8use config::{MachineHookConfig, MachineHookFactory};
9use sysinfo::{CpuRefreshKind, MemoryRefreshKind, RefreshKind, System};
10
11pub const KEY: &str = "capture-machine";
12
13#[derive(Debug, Default)]
14pub struct MachineHook;
15
16#[derive(Debug)]
17pub struct CpuInfo {
18    name: String,
19    vender_id: String,
20    brand: String,
21    frequency_mhz: u64,
22}
23
24#[derive(Debug)]
25pub struct MachineCaptured {
26    pub os: String,
27    pub os_version: String,
28    pub kernel_version: String,
29    pub architecture: String,
30    pub cpus: Vec<CpuInfo>,
31    // pub cpu_cores: usize,
32    pub total_memory: usize,
33    // pub user: String,
34    pub hostname: String,
35}
36
37impl Hook for MachineHook {
38    type Config = MachineHookConfig;
39    type Output = MachineCaptured;
40
41    fn id(&self) -> String {
42        KEY.to_string()
43    }
44
45    fn config(&self) -> &Self::Config {
46        &MachineHookConfig {}
47    }
48
49    fn run(&self, _params: &RuntimeParams) -> CapsulaResult<Self::Output> {
50        let os = System::name().ok_or(MachineHookError::OsInfoError)?;
51        let os_version = System::os_version().ok_or(MachineHookError::OsInfoError)?;
52        let kernel_version = System::kernel_version().ok_or(MachineHookError::OsInfoError)?;
53        let architecture = std::env::consts::ARCH.to_string();
54
55        let system = System::new_with_specifics(
56            RefreshKind::nothing()
57                .with_cpu(CpuRefreshKind::nothing().with_frequency())
58                .with_memory(MemoryRefreshKind::nothing().with_ram()),
59        );
60        let cpus = system
61            .cpus()
62            .iter()
63            .map(|cpu| CpuInfo {
64                name: cpu.name().to_string(),
65                vender_id: cpu.vendor_id().to_string(),
66                brand: cpu.brand().to_string(),
67                frequency_mhz: cpu.frequency(),
68            })
69            .collect::<Vec<_>>();
70
71        let total_memory = system.total_memory();
72        let hostname = System::host_name().ok_or(MachineHookError::HostnameError)?;
73
74        Ok(MachineCaptured {
75            os,
76            os_version,
77            kernel_version,
78            architecture,
79            cpus,
80            total_memory: total_memory as usize,
81            hostname,
82        })
83    }
84}
85
86impl Captured for MachineCaptured {
87    fn to_json(&self) -> serde_json::Value {
88        serde_json::json!({
89            "os": self.os,
90            "os_version": self.os_version,
91            "kernel_version": self.kernel_version,
92            "architecture": self.architecture,
93            "cpus": self.cpus.iter().map(|cpu| {
94                serde_json::json!({
95                    "name": cpu.name,
96                    "vender_id": cpu.vender_id,
97                    "brand": cpu.brand,
98                    "frequency_mhz": cpu.frequency_mhz,
99                })
100            }).collect::<Vec<_>>(),
101            "total_memory": self.total_memory,
102            "hostname": self.hostname,
103        })
104    }
105}
106
107pub fn create_factory() -> Box<dyn HookFactory> {
108    Box::new(MachineHookFactory)
109}