Skip to content

StatBeacon

StatBeacon is a lightweight system monitoring agent written in Rust. It runs as a long-lived process, periodically sampling CPU usage, memory consumption, and hardware temperatures via the sysinfo crate, then POSTing structured JSON payloads to configurable HTTP endpoints. When any metric crosses a user-defined threshold, StatBeacon fires a separate alert request with Slack-compatible message formatting — colour-coded attachments, field cards, and all — so it drops straight into a channel without any middleware.

The entire application lives in a single main.rs (~300 lines) with zero framework overhead: just tokio for the async runtime, reqwest for HTTP, sysinfo for cross-platform metrics, and chrono for timestamps.

  • Live System Metrics — Samples global CPU usage, total/used memory, and per-component hardware temperatures every n seconds (configurable via interval_seconds)
  • Dual-Endpoint Publishing — Stats go to target_stat_url; threshold-triggered alerts go to a separate target_alert_url, keeping monitoring data and incident notifications cleanly separated
  • Configurable Alert Thresholds — Independent thresholds for CPU (cpu_alert_threshold), memory (memory_alert_threshold), and temperature (temperature_alert_threshold) — an alert fires when any metric exceeds its limit
  • Slack-Ready Alert Payloads — Alerts are structured as Slack attachments with colour coding (#ff0000 for warnings, #228B22 for info), field cards for each metric, and a footer — ready to POST directly to a Slack incoming webhook
  • TOML Configuration — Everything lives in a single StatBeacon.toml file with clear, flat keys — no nested sections or complex syntax
  • Optional HTTP Proxy — Set a proxy field in the config and all outbound requests route through it, useful for corporate networks or debugging with tools like mitmproxy
  • Automated GitHub Releases — A CI workflow builds the Linux binary on every published release and uploads it as a .tar.gz asset
StatBeacon.toml
name = "My Application"
interval_seconds = 4
target_stat_url = "https://example.com/api/stats"
target_alert_url = "http://example.com/api/alerts"
cpu_alert_threshold = 60
memory_alert_threshold = 80
temperature_alert_threshold = 70
# proxy = "http://localhost:8080"

The core loop in main.rs is straightforward async Rust:

loop {
sys.refresh_all();
let cpu = sys.global_cpu_usage();
let memory = (used_memory as f32 / total_memory as f32) * 100.0;
// Collect per-component temperatures and average them
components.refresh();
let average_temperature = temperature_data.iter()
.fold(0.0, |acc, x| acc + x.temperature)
/ temperature_data.len() as f32;
// POST stats to the monitoring endpoint
client.post(&config.target_stat_url).json(&msg).send().await;
// Fire alert if any threshold is exceeded
if cpu > config.cpu_alert_threshold
|| memory > config.memory_alert_threshold
|| average_temperature > config.temperature_alert_threshold
{
client.post(&config.target_alert_url).json(&alert_msg).send().await;
}
tokio::time::sleep(Duration::from_secs(config.interval_seconds)).await;
}

The StatsLog struct converts into an AlertMessage via a From impl that switches colour and copy based on alert level — a clean Rust pattern that keeps serialisation concerns separate from monitoring logic.

LanguageRust (2021 edition)
Async RuntimeTokio
HTTP ClientReqwest (with JSON + proxy features)
System Metricssysinfo 0.32
SerialisationSerde + serde_json
Config FormatTOML (toml 0.8)
Timestampschrono
CI/CDGitHub Actions — automated release builds

The source code is available on the project’s GitHub repository.