Merge pull request 'Remove jsonrpc from peach-stats' (#43) from separate_stats_logic into main
Reviewed-on: #43
This commit is contained in:
commit
06e48deb3a
|
@ -2589,15 +2589,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "peach-stats"
|
name = "peach-stats"
|
||||||
version = "0.1.3"
|
version = "0.2.0"
|
||||||
dependencies = [
|
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",
|
"log 0.4.14",
|
||||||
"miniserde",
|
"miniserde",
|
||||||
"probes 0.4.1",
|
"probes 0.4.1",
|
||||||
|
"serde 1.0.130",
|
||||||
"systemstat",
|
"systemstat",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -1,40 +1,31 @@
|
||||||
[package]
|
[package]
|
||||||
name = "peach-stats"
|
name = "peach-stats"
|
||||||
version = "0.1.3"
|
version = "0.2.0"
|
||||||
authors = ["Andrew Reid <gnomad@cryptolab.net>"]
|
authors = ["Andrew Reid <glyph@mycelial.technology>"]
|
||||||
edition = "2018"
|
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"
|
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"
|
readme = "README.md"
|
||||||
license = "AGPL-3.0-only"
|
license = "LGPL-3.0-only"
|
||||||
publish = false
|
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]
|
[badges]
|
||||||
travis-ci = { repository = "peachcloud/peach-stats", branch = "master" }
|
|
||||||
maintenance = { status = "actively-developed" }
|
maintenance = { status = "actively-developed" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
env_logger = "0.9"
|
|
||||||
jsonrpc-core = "18"
|
|
||||||
jsonrpc-http-server = "18"
|
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
miniserde = "0.1.15"
|
miniserde = { version = "0.1.15", optional = true }
|
||||||
probes = "0.4.1"
|
probes = "0.4.1"
|
||||||
|
serde = { version = "1.0.130", features = ["derive"], optional = true }
|
||||||
systemstat = "0.1.10"
|
systemstat = "0.1.10"
|
||||||
|
|
||||||
[dev-dependencies]
|
[features]
|
||||||
jsonrpc-test = "18"
|
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"]
|
||||||
|
|
|
@ -1,109 +1,47 @@
|
||||||
# peach-stats
|
# 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-<COLOR>.svg)
|
![Generic badge](https://img.shields.io/badge/version-0.2.0-<COLOR>.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: `user`, `system`, `nice`, `idle` (as values or percentages)
|
||||||
| --- | --- | --- |
|
- Disk usage: `filesystem`, `one_k_blocks`, `one_k_blocks_used`,
|
||||||
| `cpu_stats` | CPU statistics | `user`, `system`, `nice`, `idle` |
|
`one_k_blocks_free`, `used_percentage`, `mountpoint`
|
||||||
| `cpu_stats_percent` | CPU statistics as percentages | `user`, `system`, `nice`, `idle` |
|
- Load average: `one`, `five`, `fifteen`
|
||||||
| `disk_usage` | Disk usage statistics (array of disks) | `filesystem`, `one_k_blocks`, `one_k_blocks_used`, `one_k_blocks_free`, `used_percentage`, `mountpoint` |
|
- Memory: `total`, `free`, `used`
|
||||||
| `load_average` | Load average statistics | `one`, `five`, `fifteen` |
|
- Uptime: `seconds`
|
||||||
| `mem_stats` | Memory statistics | `total`, `free`, `used` |
|
|
||||||
| `ping` | Microservice status | `success` if running |
|
|
||||||
| `uptime` | System uptime | `secs` |
|
|
||||||
|
|
||||||
### 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`
|
## License
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
LGPL-3.0.
|
||||||
|
|
|
@ -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
|
|
|
@ -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 probes::ProbeError;
|
||||||
|
use std::{error, fmt, io::Error as IoError};
|
||||||
|
|
||||||
|
/// Custom error type encapsulating all possible errors when retrieving system
|
||||||
|
/// statistics.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum StatError {
|
pub enum StatsError {
|
||||||
CpuStat { source: ProbeError },
|
/// Failed to retrieve CPU statistics.
|
||||||
DiskUsage { source: ProbeError },
|
CpuStat(ProbeError),
|
||||||
LoadAvg { source: ProbeError },
|
/// Failed to retrieve disk usage statistics.
|
||||||
MemStat { source: ProbeError },
|
DiskUsage(ProbeError),
|
||||||
Uptime { source: io::Error },
|
/// 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 {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
StatError::CpuStat { ref source } => {
|
StatsError::CpuStat(ref source) => {
|
||||||
write!(f, "Failed to retrieve CPU statistics: {}", 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)
|
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)
|
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)
|
write!(f, "Failed to retrieve memory statistics: {}", source)
|
||||||
}
|
}
|
||||||
StatError::Uptime { ref source } => {
|
StatsError::Uptime(ref source) => {
|
||||||
write!(f, "Failed to retrieve system uptime: {}", source)
|
write!(f, "Failed to retrieve system uptime: {}", source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<StatError> 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,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,103 +1,48 @@
|
||||||
mod error;
|
#![warn(missing_docs)]
|
||||||
mod stats;
|
|
||||||
mod structs;
|
|
||||||
|
|
||||||
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};
|
pub mod error;
|
||||||
use jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation, ServerBuilder};
|
pub mod stats;
|
||||||
use log::info;
|
|
||||||
|
|
||||||
use crate::error::StatError;
|
pub use crate::error::StatsError;
|
||||||
|
|
||||||
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""#);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +1,96 @@
|
||||||
|
//! System statistics retrieval functions and associated data types.
|
||||||
|
|
||||||
use std::result::Result;
|
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 probes::{cpu, disk_usage, load, memory};
|
||||||
use systemstat::{Platform, System};
|
use systemstat::{Platform, System};
|
||||||
|
|
||||||
use crate::error::StatError;
|
use crate::error::StatsError;
|
||||||
use crate::structs::{CpuStat, CpuStatPercentages, DiskUsage, LoadAverage, MemStat};
|
|
||||||
|
|
||||||
pub fn cpu_stats() -> Result<String, StatError> {
|
/// CPU statistics.
|
||||||
let cpu_stats = cpu::proc::read().map_err(|source| StatError::CpuStat { source })?;
|
#[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<String>,
|
||||||
|
/// 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<CpuStat, StatsError> {
|
||||||
|
let cpu_stats = cpu::proc::read().map_err(StatsError::CpuStat)?;
|
||||||
let s = cpu_stats.stat;
|
let s = cpu_stats.stat;
|
||||||
let cpu = CpuStat {
|
let cpu = CpuStat {
|
||||||
user: s.user,
|
user: s.user,
|
||||||
|
@ -16,13 +98,13 @@ pub fn cpu_stats() -> Result<String, StatError> {
|
||||||
nice: s.nice,
|
nice: s.nice,
|
||||||
idle: s.idle,
|
idle: s.idle,
|
||||||
};
|
};
|
||||||
let json_cpu = json::to_string(&cpu);
|
|
||||||
|
|
||||||
Ok(json_cpu)
|
Ok(cpu)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cpu_stats_percent() -> Result<String, StatError> {
|
/// Retrieve the current CPU statistics as percentages.
|
||||||
let cpu_stats = cpu::proc::read().map_err(|source| StatError::CpuStat { source })?;
|
pub fn cpu_stats_percent() -> Result<CpuStatPercentages, StatsError> {
|
||||||
|
let cpu_stats = cpu::proc::read().map_err(StatsError::CpuStat)?;
|
||||||
let s = cpu_stats.stat.in_percentages();
|
let s = cpu_stats.stat.in_percentages();
|
||||||
let cpu = CpuStatPercentages {
|
let cpu = CpuStatPercentages {
|
||||||
user: s.user,
|
user: s.user,
|
||||||
|
@ -30,13 +112,13 @@ pub fn cpu_stats_percent() -> Result<String, StatError> {
|
||||||
nice: s.nice,
|
nice: s.nice,
|
||||||
idle: s.idle,
|
idle: s.idle,
|
||||||
};
|
};
|
||||||
let json_cpu = json::to_string(&cpu);
|
|
||||||
|
|
||||||
Ok(json_cpu)
|
Ok(cpu)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disk_usage() -> Result<String, StatError> {
|
/// Retrieve the current disk usage statistics for each available disk / partition.
|
||||||
let disks = disk_usage::read().map_err(|source| StatError::DiskUsage { source })?;
|
pub fn disk_usage() -> Result<Vec<DiskUsage>, StatsError> {
|
||||||
|
let disks = disk_usage::read().map_err(StatsError::DiskUsage)?;
|
||||||
let mut disk_usages = Vec::new();
|
let mut disk_usages = Vec::new();
|
||||||
for d in disks {
|
for d in disks {
|
||||||
let disk = DiskUsage {
|
let disk = DiskUsage {
|
||||||
|
@ -49,42 +131,39 @@ pub fn disk_usage() -> Result<String, StatError> {
|
||||||
};
|
};
|
||||||
disk_usages.push(disk);
|
disk_usages.push(disk);
|
||||||
}
|
}
|
||||||
let json_disks = json::to_string(&disk_usages);
|
|
||||||
|
|
||||||
Ok(json_disks)
|
Ok(disk_usages)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_average() -> Result<String, StatError> {
|
/// Retrieve the current load average statistics.
|
||||||
let l = load::read().map_err(|source| StatError::LoadAvg { source })?;
|
pub fn load_average() -> Result<LoadAverage, StatsError> {
|
||||||
|
let l = load::read().map_err(StatsError::LoadAvg)?;
|
||||||
let load_avg = LoadAverage {
|
let load_avg = LoadAverage {
|
||||||
one: l.one,
|
one: l.one,
|
||||||
five: l.five,
|
five: l.five,
|
||||||
fifteen: l.fifteen,
|
fifteen: l.fifteen,
|
||||||
};
|
};
|
||||||
let json_load_avg = json::to_string(&load_avg);
|
|
||||||
|
|
||||||
Ok(json_load_avg)
|
Ok(load_avg)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mem_stats() -> Result<String, StatError> {
|
/// Retrieve the current memory usage statistics.
|
||||||
let m = memory::read().map_err(|source| StatError::MemStat { source })?;
|
pub fn mem_stats() -> Result<MemStat, StatsError> {
|
||||||
|
let m = memory::read().map_err(StatsError::MemStat)?;
|
||||||
let mem = MemStat {
|
let mem = MemStat {
|
||||||
total: m.total(),
|
total: m.total(),
|
||||||
free: m.free(),
|
free: m.free(),
|
||||||
used: m.used(),
|
used: m.used(),
|
||||||
};
|
};
|
||||||
let json_mem = json::to_string(&mem);
|
|
||||||
|
|
||||||
Ok(json_mem)
|
Ok(mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uptime() -> Result<String, StatError> {
|
/// Retrieve the system uptime in seconds.
|
||||||
|
pub fn uptime() -> Result<u64, StatsError> {
|
||||||
let sys = System::new();
|
let sys = System::new();
|
||||||
let uptime = sys
|
let uptime = sys.uptime().map_err(StatsError::Uptime)?;
|
||||||
.uptime()
|
|
||||||
.map_err(|source| StatError::Uptime { source })?;
|
|
||||||
let uptime_secs = uptime.as_secs();
|
let uptime_secs = uptime.as_secs();
|
||||||
let json_uptime = json::to_string(&uptime_secs);
|
|
||||||
|
|
||||||
Ok(json_uptime)
|
Ok(uptime_secs)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<String>,
|
|
||||||
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,
|
|
||||||
}
|
|
Loading…
Reference in New Issue