capsula_capture_machine/
lib.rs

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