diff --git a/Cargo.lock b/Cargo.lock index 76635b0..2e0b171 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2589,15 +2589,12 @@ dependencies = [ [[package]] name = "peach-stats" -version = "0.1.3" +version = "0.2.0" dependencies = [ - "env_logger 0.9.0", - "jsonrpc-core 18.0.0", - "jsonrpc-http-server 18.0.0", - "jsonrpc-test 18.0.0", "log 0.4.14", "miniserde", "probes 0.4.1", + "serde 1.0.130", "systemstat", ] diff --git a/peach-stats/Cargo.toml b/peach-stats/Cargo.toml index c8a4914..488d637 100644 --- a/peach-stats/Cargo.toml +++ b/peach-stats/Cargo.toml @@ -1,40 +1,31 @@ [package] name = "peach-stats" -version = "0.1.3" -authors = ["Andrew Reid "] +version = "0.2.0" +authors = ["Andrew Reid "] edition = "2018" -description = "Query system statistics using JSON-RPC over HTTP. Provides a JSON-RPC wrapper around the probes and systemstat crates." +description = "Query system statistics. Provides a wrapper around the probes and systemstat crates." +keywords = ["peachcloud", "system stats", "system statistics", "disk", "memory"] homepage = "https://opencollective.com/peachcloud" -repository = "https://github.com/peachcloud/peach-stats" +repository = "https://git.coopcloud.tech/PeachCloud/peach-workspace/src/branch/main/peach-stats" readme = "README.md" -license = "AGPL-3.0-only" +license = "LGPL-3.0-only" publish = false -[package.metadata.deb] -depends = "$auto" -extended-description = """\ -peach-stats is a system statistics microservice module for PeachCloud. \ -Query system statistics using JSON-RPC over HTTP. Provides a JSON-RPC \ -wrapper around the probes and systemstat crates.""" -maintainer-scripts="debian" -systemd-units = { unit-name = "peach-stats" } -assets = [ - ["target/release/peach-stats", "usr/bin/", "755"], - ["README.md", "usr/share/doc/peach-stats/README", "644"], -] - [badges] -travis-ci = { repository = "peachcloud/peach-stats", branch = "master" } maintenance = { status = "actively-developed" } [dependencies] -env_logger = "0.9" -jsonrpc-core = "18" -jsonrpc-http-server = "18" log = "0.4" -miniserde = "0.1.15" +miniserde = { version = "0.1.15", optional = true } probes = "0.4.1" +serde = { version = "1.0.130", features = ["derive"], optional = true } systemstat = "0.1.10" -[dev-dependencies] -jsonrpc-test = "18" +[features] +default = [] + +# Provide `Serialize` and `Deserialize` traits for library structs using `miniserde` +miniserde_support = ["miniserde"] + +# Provide `Serialize` and `Deserialize` traits for library structs using `serde` +serde_support = ["serde"] diff --git a/peach-stats/README.md b/peach-stats/README.md index b2d527e..1245532 100644 --- a/peach-stats/README.md +++ b/peach-stats/README.md @@ -1,109 +1,47 @@ # peach-stats -[![Build Status](https://travis-ci.com/peachcloud/peach-stats.svg?branch=master)](https://travis-ci.com/peachcloud/peach-stats) ![Generic badge](https://img.shields.io/badge/version-0.1.3-.svg) +![Generic badge](https://img.shields.io/badge/version-0.2.0-.svg) -System statistics microservice module for PeachCloud. Provides a JSON-RPC wrapper around the [probes](https://crates.io/crates/probes) and [systemstat](https://crates.io/crates/systemstat) crates. +System statistics library for PeachCloud. Provides a wrapper around the [probes](https://crates.io/crates/probes) and [systemstat](https://crates.io/crates/systemstat) crates. -### JSON-RPC API +Currently offers the following statistics and associated data structures: -| Method | Description | Returns | -| --- | --- | --- | -| `cpu_stats` | CPU statistics | `user`, `system`, `nice`, `idle` | -| `cpu_stats_percent` | CPU statistics as percentages | `user`, `system`, `nice`, `idle` | -| `disk_usage` | Disk usage statistics (array of disks) | `filesystem`, `one_k_blocks`, `one_k_blocks_used`, `one_k_blocks_free`, `used_percentage`, `mountpoint` | -| `load_average` | Load average statistics | `one`, `five`, `fifteen` | -| `mem_stats` | Memory statistics | `total`, `free`, `used` | -| `ping` | Microservice status | `success` if running | -| `uptime` | System uptime | `secs` | + - CPU: `user`, `system`, `nice`, `idle` (as values or percentages) + - Disk usage: `filesystem`, `one_k_blocks`, `one_k_blocks_used`, + `one_k_blocks_free`, `used_percentage`, `mountpoint` + - Load average: `one`, `five`, `fifteen` + - Memory: `total`, `free`, `used` + - Uptime: `seconds` -### Environment +## Example Usage -The JSON-RPC HTTP server address and port can be configured with the `PEACH_STATS_SERVER` environment variable: +```rust +use peach_stats::{stats, StatsError}; -`export PEACH_STATS_SERVER=127.0.0.1:5000` +fn main() -> Result<(), StatsError> { + let cpu = stats::cpu_stats()?; + let cpu_percentages = stats::cpu_stats_percent()?; + let disks = stats::disk_usage()?; + let load = stats::load_average()?; + let mem = stats::mem_stats()?; + let uptime = stats::uptime()?; -When not set, the value defaults to `127.0.0.1:5113`. + // do things with the retrieved values... -Logging is made available with `env_logger`: + Ok(()) +} +``` -`export RUST_LOG=info` +## Feature Flags -Other logging levels include `debug`, `warn` and `error`. +Feature flags are used to offer `Serialize` and `Deserialize` implementations for all `struct` data types provided by this library. These traits are not provided by default. A choice of `miniserde` and `serde` is provided. -### Setup +Define the desired feature in the `Cargo.toml` manifest of your project: -Clone this repo: +```toml +peach-stats = { version = "0.1.0", features = ["miniserde_support"] } +``` -`git clone https://github.com/peachcloud/peach-stats.git` - -Move into the repo and compile a release build: - -`cd peach-stats` -`cargo build --release` - -Run the binary: - -`./target/release/peach-stats` - -### Debian Packaging - -A `systemd` service file and Debian maintainer scripts are included in the `debian` directory, allowing `peach-stats` to be easily bundled as a Debian package (`.deb`). The `cargo-deb` [crate](https://crates.io/crates/cargo-deb) can be used to achieve this. - -Install `cargo-deb`: - -`cargo install cargo-deb` - -Move into the repo: - -`cd peach-stats` - -Build the package: - -`cargo deb` - -The output will be written to `target/debian/peach-stats_0.1.0_arm64.deb` (or similar). - -Build the package (aarch64): - -`cargo deb --target aarch64-unknown-linux-gnu` - -Install the package as follows: - -`sudo dpkg -i target/debian/peach-stats_0.1.0_arm64.deb` - -The service will be automatically enabled and started. - -Uninstall the service: - -`sudo apt-get remove peach-stats` - -Remove configuration files (not removed with `apt-get remove`): - -`sudo apt-get purge peach-stats` - -### Example Usage - -**Get CPU Statistics** - -With microservice running, open a second terminal window and use `curl` to call server methods: - -`curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "cpu_stats", "id":1 }' 127.0.0.1:5113` - -Server responds with: - -`{"jsonrpc":"2.0","result":"{\"user\":4661083,\"system\":1240371,\"idle\":326838290,\"nice\":0}","id":1}` - -**Get System Uptime** - -With microservice running, open a second terminal window and use `curl` to call server methods: - -`curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "uptime", "id":1 }' 127.0.0.1:5113` - -Server responds with: - -`{"jsonrpc":"2.0","result":"{\"secs\":840968}","id":1}` - -### Licensing - -AGPL-3.0 +## License +LGPL-3.0. diff --git a/peach-stats/debian/peach-stats.service b/peach-stats/debian/peach-stats.service deleted file mode 100644 index a32c506..0000000 --- a/peach-stats/debian/peach-stats.service +++ /dev/null @@ -1,27 +0,0 @@ -[Unit] -Description=Query system statistics using JSON-RPC over HTTP. - -[Service] -Type=simple -User=peach-stats -Environment="RUST_LOG=error" -ExecStart=/usr/bin/peach-stats -Restart=always -CapabilityBoundingSet=~CAP_SYS_ADMIN CAP_SYS_PTRACE CAP_SYS_BOOT CAP_SYS_TIME CAP_KILL CAP_WAKE_ALARM CAP_LINUX_IMMUTABLE CAP_BLOCK_SUSPEND CAP_LEASE CAP_SYS_NICE CAP_SYS_RESOURCE CAP_RAWIO CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_DAC_* CAP_FOWNER CAP_IPC_OWNER CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_AUDIT_* -InaccessibleDirectories=/home -LockPersonality=yes -NoNewPrivileges=yes -PrivateDevices=yes -PrivateTmp=yes -PrivateUsers=yes -ProtectControlGroups=yes -ProtectHome=yes -ProtectKernelModules=yes -ProtectKernelTunables=yes -ProtectSystem=yes -ReadOnlyDirectories=/var -RestrictAddressFamilies=~AF_INET6 AF_UNIX -SystemCallFilter=~@reboot @clock @debug @module @mount @swap @resources @privileged - -[Install] -WantedBy=multi-user.target diff --git a/peach-stats/src/error.rs b/peach-stats/src/error.rs index b558364..d782e35 100644 --- a/peach-stats/src/error.rs +++ b/peach-stats/src/error.rs @@ -1,69 +1,44 @@ -use std::{error, fmt, io}; +//! Custom error type for `peach-stats`. -use jsonrpc_core::{types::error::Error, ErrorCode}; use probes::ProbeError; +use std::{error, fmt, io::Error as IoError}; +/// Custom error type encapsulating all possible errors when retrieving system +/// statistics. #[derive(Debug)] -pub enum StatError { - CpuStat { source: ProbeError }, - DiskUsage { source: ProbeError }, - LoadAvg { source: ProbeError }, - MemStat { source: ProbeError }, - Uptime { source: io::Error }, +pub enum StatsError { + /// Failed to retrieve CPU statistics. + CpuStat(ProbeError), + /// Failed to retrieve disk usage statistics. + DiskUsage(ProbeError), + /// Failed to retrieve load average statistics. + LoadAvg(ProbeError), + /// Failed to retrieve memory usage statistics. + MemStat(ProbeError), + /// Failed to retrieve system uptime. + Uptime(IoError), } -impl error::Error for StatError {} +impl error::Error for StatsError {} -impl fmt::Display for StatError { +impl fmt::Display for StatsError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - StatError::CpuStat { ref source } => { + StatsError::CpuStat(ref source) => { write!(f, "Failed to retrieve CPU statistics: {}", source) } - StatError::DiskUsage { ref source } => { + StatsError::DiskUsage(ref source) => { write!(f, "Failed to retrieve disk usage statistics: {}", source) } - StatError::LoadAvg { ref source } => { + StatsError::LoadAvg(ref source) => { write!(f, "Failed to retrieve load average statistics: {}", source) } - StatError::MemStat { ref source } => { + StatsError::MemStat(ref source) => { write!(f, "Failed to retrieve memory statistics: {}", source) } - StatError::Uptime { ref source } => { + StatsError::Uptime(ref source) => { write!(f, "Failed to retrieve system uptime: {}", source) } } } } - -impl From for Error { - fn from(err: StatError) -> Self { - match &err { - StatError::CpuStat { source } => Error { - code: ErrorCode::ServerError(-32001), - message: format!("Failed to retrieve CPU statistics: {}", source), - data: None, - }, - StatError::DiskUsage { source } => Error { - code: ErrorCode::ServerError(-32001), - message: format!("Failed to retrieve disk usage statistics: {}", source), - data: None, - }, - StatError::LoadAvg { source } => Error { - code: ErrorCode::ServerError(-32001), - message: format!("Failed to retrieve load average statistics: {}", source), - data: None, - }, - StatError::MemStat { source } => Error { - code: ErrorCode::ServerError(-32001), - message: format!("Failed to retrieve memory statistics: {}", source), - data: None, - }, - StatError::Uptime { source } => Error { - code: ErrorCode::ServerError(-32001), - message: format!("Failed to retrieve system uptime: {}", source), - data: None, - }, - } - } -} diff --git a/peach-stats/src/lib.rs b/peach-stats/src/lib.rs index 00ce6a1..cae7d50 100644 --- a/peach-stats/src/lib.rs +++ b/peach-stats/src/lib.rs @@ -1,103 +1,48 @@ -mod error; -mod stats; -mod structs; +#![warn(missing_docs)] -use std::{env, result::Result}; +//! # peach-stats +//! +//! System statistics retrieval library; designed for use with the PeachCloud platform. +//! +//! Currently offers the following statistics and associated data structures: +//! +//! - CPU: `user`, `system`, `nice`, `idle` (as values or percentages) +//! - Disk usage: `filesystem`, `one_k_blocks`, `one_k_blocks_used`, +//! `one_k_blocks_free`, `used_percentage`, `mountpoint` +//! - Load average: `one`, `five`, `fifteen` +//! - Memory: `total`, `free`, `used` +//! - Uptime: `seconds` +//! +//! ## Example Usage +//! +//! ```rust +//! use peach_stats::{stats, StatsError}; +//! +//! fn main() -> Result<(), StatsError> { +//! let cpu = stats::cpu_stats()?; +//! let cpu_percentages = stats::cpu_stats_percent()?; +//! let disks = stats::disk_usage()?; +//! let load = stats::load_average()?; +//! let mem = stats::mem_stats()?; +//! let uptime = stats::uptime()?; +//! +//! Ok(()) +//! } +//! ``` +//! +//! ## Feature Flags +//! +//! Feature flags are used to offer `Serialize` and `Deserialize` implementations +//! for all `struct` data types provided by this library. These traits are not +//! provided by default. A choice of `miniserde` and `serde` is provided. +//! +//! Define the desired feature in the `Cargo.toml` manifest of your project: +//! +//! ```toml +//! peach-stats = { version = "0.1.0", features = ["miniserde_support"] } +//! ``` -use jsonrpc_core::{IoHandler, Value}; -use jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation, ServerBuilder}; -use log::info; +pub mod error; +pub mod stats; -use crate::error::StatError; - -pub fn run() -> Result<(), StatError> { - info!("Starting up."); - - info!("Creating JSON-RPC I/O handler."); - let mut io = IoHandler::default(); - - io.add_method("cpu_stats", move |_| async { - info!("Fetching CPU statistics."); - let stats = stats::cpu_stats()?; - - Ok(Value::String(stats)) - }); - - io.add_method("cpu_stats_percent", move |_| async { - info!("Fetching CPU statistics as percentages."); - let stats = stats::cpu_stats_percent()?; - - Ok(Value::String(stats)) - }); - - io.add_method("disk_usage", move |_| async { - info!("Fetching disk usage statistics."); - let disks = stats::disk_usage()?; - - Ok(Value::String(disks)) - }); - - io.add_method("load_average", move |_| async { - info!("Fetching system load average statistics."); - let avg = stats::load_average()?; - - Ok(Value::String(avg)) - }); - - io.add_method("mem_stats", move |_| async { - info!("Fetching current memory statistics."); - let mem = stats::mem_stats()?; - - Ok(Value::String(mem)) - }); - - io.add_method("ping", |_| async { - Ok(Value::String("success".to_string())) - }); - - io.add_method("uptime", move |_| async { - info!("Fetching system uptime."); - let uptime = stats::uptime()?; - - Ok(Value::String(uptime)) - }); - - let http_server = env::var("PEACH_OLED_STATS").unwrap_or_else(|_| "127.0.0.1:5113".to_string()); - - info!("Starting JSON-RPC server on {}.", http_server); - let server = ServerBuilder::new(io) - .cors(DomainsValidation::AllowOnly(vec![ - AccessControlAllowOrigin::Null, - ])) - .start_http( - &http_server - .parse() - .expect("Invalid HTTP address and port combination"), - ) - .expect("Unable to start RPC server"); - - info!("Listening for requests."); - server.wait(); - - Ok(()) -} - -#[cfg(test)] -mod tests { - use super::*; - use jsonrpc_test as test_rpc; - - // test to ensure correct success response - #[test] - fn rpc_success() { - let rpc = { - let mut io = IoHandler::new(); - io.add_method("rpc_success_response", |_| async { - Ok(Value::String("success".into())) - }); - test_rpc::Rpc::from(io) - }; - - assert_eq!(rpc.request("rpc_success_response", &()), r#""success""#); - } -} +pub use crate::error::StatsError; diff --git a/peach-stats/src/main.rs b/peach-stats/src/main.rs deleted file mode 100644 index 55a11ec..0000000 --- a/peach-stats/src/main.rs +++ /dev/null @@ -1,14 +0,0 @@ -use std::process; - -use log::error; - -fn main() { - // initialize the logger - env_logger::init(); - - // handle errors returned from `run` - if let Err(e) = peach_stats::run() { - error!("Application error: {}", e); - process::exit(1); - } -} diff --git a/peach-stats/src/stats.rs b/peach-stats/src/stats.rs index 15c9031..0a0914d 100644 --- a/peach-stats/src/stats.rs +++ b/peach-stats/src/stats.rs @@ -1,14 +1,96 @@ +//! System statistics retrieval functions and associated data types. + use std::result::Result; -use miniserde::json; +#[cfg(feature = "miniserde_support")] +use miniserde::{Deserialize, Serialize}; + +#[cfg(feature = "serde_support")] +use serde::{Deserialize, Serialize}; + use probes::{cpu, disk_usage, load, memory}; use systemstat::{Platform, System}; -use crate::error::StatError; -use crate::structs::{CpuStat, CpuStatPercentages, DiskUsage, LoadAverage, MemStat}; +use crate::error::StatsError; -pub fn cpu_stats() -> Result { - let cpu_stats = cpu::proc::read().map_err(|source| StatError::CpuStat { source })?; +/// CPU statistics. +#[derive(Debug)] +#[cfg_attr(feature = "miniserde_support", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] +pub struct CpuStat { + /// Time spent running user space (application) code. + pub user: u64, + /// Time spent running kernel code. + pub system: u64, + /// Time spent doing nothing. + pub idle: u64, + /// Time spent running user space processes which have been niced. + pub nice: u64, +} + +/// CPU statistics as percentages. +#[derive(Debug)] +#[cfg_attr(feature = "miniserde_support", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] +pub struct CpuStatPercentages { + /// Time spent running user space (application) code. + pub user: f32, + /// Time spent running kernel code. + pub system: f32, + /// Time spent doing nothing. + pub idle: f32, + /// Time spent running user space processes which have been niced. + pub nice: f32, +} + +/// Disk usage statistics. +#[derive(Debug)] +#[cfg_attr(feature = "miniserde_support", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] +pub struct DiskUsage { + /// Filesystem device path. + pub filesystem: Option, + /// Total amount of disk space as a number of 1,000 kilobyte blocks. + pub one_k_blocks: u64, + /// Total amount of used disk space as a number of 1,000 kilobyte blocks. + pub one_k_blocks_used: u64, + /// Total amount of free / available disk space as a number of 1,000 kilobyte blocks. + pub one_k_blocks_free: u64, + /// Total amount of used disk space as a percentage. + pub used_percentage: u32, + /// Mountpoint of the disk / partition. + pub mountpoint: String, +} + +/// Load average statistics. +#[derive(Debug)] +#[cfg_attr(feature = "miniserde_support", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] +pub struct LoadAverage { + /// Average computational work performed over the past minute. + pub one: f32, + /// Average computational work performed over the past five minutes. + pub five: f32, + /// Average computational work performed over the past fifteen minutes. + pub fifteen: f32, +} + +/// Memory statistics. +#[derive(Debug)] +#[cfg_attr(feature = "miniserde_support", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))] +pub struct MemStat { + /// Total amount of physical memory in kilobytes. + pub total: u64, + /// Total amount of free / available physical memory in kilobytes. + pub free: u64, + /// Total amount of used physical memory in kilobytes. + pub used: u64, +} + +/// Retrieve the current CPU statistics. +pub fn cpu_stats() -> Result { + let cpu_stats = cpu::proc::read().map_err(StatsError::CpuStat)?; let s = cpu_stats.stat; let cpu = CpuStat { user: s.user, @@ -16,13 +98,13 @@ pub fn cpu_stats() -> Result { nice: s.nice, idle: s.idle, }; - let json_cpu = json::to_string(&cpu); - Ok(json_cpu) + Ok(cpu) } -pub fn cpu_stats_percent() -> Result { - let cpu_stats = cpu::proc::read().map_err(|source| StatError::CpuStat { source })?; +/// Retrieve the current CPU statistics as percentages. +pub fn cpu_stats_percent() -> Result { + let cpu_stats = cpu::proc::read().map_err(StatsError::CpuStat)?; let s = cpu_stats.stat.in_percentages(); let cpu = CpuStatPercentages { user: s.user, @@ -30,13 +112,13 @@ pub fn cpu_stats_percent() -> Result { nice: s.nice, idle: s.idle, }; - let json_cpu = json::to_string(&cpu); - Ok(json_cpu) + Ok(cpu) } -pub fn disk_usage() -> Result { - let disks = disk_usage::read().map_err(|source| StatError::DiskUsage { source })?; +/// Retrieve the current disk usage statistics for each available disk / partition. +pub fn disk_usage() -> Result, StatsError> { + let disks = disk_usage::read().map_err(StatsError::DiskUsage)?; let mut disk_usages = Vec::new(); for d in disks { let disk = DiskUsage { @@ -49,42 +131,39 @@ pub fn disk_usage() -> Result { }; disk_usages.push(disk); } - let json_disks = json::to_string(&disk_usages); - Ok(json_disks) + Ok(disk_usages) } -pub fn load_average() -> Result { - let l = load::read().map_err(|source| StatError::LoadAvg { source })?; +/// Retrieve the current load average statistics. +pub fn load_average() -> Result { + let l = load::read().map_err(StatsError::LoadAvg)?; let load_avg = LoadAverage { one: l.one, five: l.five, fifteen: l.fifteen, }; - let json_load_avg = json::to_string(&load_avg); - Ok(json_load_avg) + Ok(load_avg) } -pub fn mem_stats() -> Result { - let m = memory::read().map_err(|source| StatError::MemStat { source })?; +/// Retrieve the current memory usage statistics. +pub fn mem_stats() -> Result { + let m = memory::read().map_err(StatsError::MemStat)?; let mem = MemStat { total: m.total(), free: m.free(), used: m.used(), }; - let json_mem = json::to_string(&mem); - Ok(json_mem) + Ok(mem) } -pub fn uptime() -> Result { +/// Retrieve the system uptime in seconds. +pub fn uptime() -> Result { let sys = System::new(); - let uptime = sys - .uptime() - .map_err(|source| StatError::Uptime { source })?; + let uptime = sys.uptime().map_err(StatsError::Uptime)?; let uptime_secs = uptime.as_secs(); - let json_uptime = json::to_string(&uptime_secs); - Ok(json_uptime) + Ok(uptime_secs) } diff --git a/peach-stats/src/structs.rs b/peach-stats/src/structs.rs deleted file mode 100644 index f307879..0000000 --- a/peach-stats/src/structs.rs +++ /dev/null @@ -1,41 +0,0 @@ -use miniserde::Serialize; - -#[derive(Debug, Serialize)] -pub struct CpuStat { - pub user: u64, - pub system: u64, - pub idle: u64, - pub nice: u64, -} - -#[derive(Debug, Serialize)] -pub struct CpuStatPercentages { - pub user: f32, - pub system: f32, - pub idle: f32, - pub nice: f32, -} - -#[derive(Debug, Serialize)] -pub struct DiskUsage { - pub filesystem: Option, - pub one_k_blocks: u64, - pub one_k_blocks_used: u64, - pub one_k_blocks_free: u64, - pub used_percentage: u32, - pub mountpoint: String, -} - -#[derive(Debug, Serialize)] -pub struct LoadAverage { - pub one: f32, - pub five: f32, - pub fifteen: f32, -} - -#[derive(Debug, Serialize)] -pub struct MemStat { - pub total: u64, - pub free: u64, - pub used: u64, -}