use std::{ sync::Arc, time::{Duration, Instant}, }; use arc_swap::ArcSwap; use chrono::{DateTime, Utc}; use tracing::{ debug, error, trace, }; use ulid::Ulid; // Metrics are named for when they're updated: // - Startup (Once, when the server state is initialized) // - Interval (About once per minute) // - Events (When a request is processed) #[derive (Debug, serde::Serialize)] pub struct Startup { // D-Bus machine ID, if we're on Linux pub machine_id: Option , // Git version that ptth_server was built from (unimplemented) pub git_version: Option , // User-assigned and human-readable name for this server. // Must be unique within a relay. pub server_name: String, // Random base64 instance ID. ptth_server generates this at process start. // It's a fallback for detecting outages without relying on any clocks. #[serde (serialize_with = "serialize_ulid")] pub instance_id: Ulid, // System UTC pub startup_utc: DateTime , } #[derive (Debug, serde::Serialize)] pub struct Interval { #[serde (skip)] pub at: Instant, pub utc: DateTime , pub rss_mib: u64, #[serde (skip)] pub cpu_usage: heim::process::CpuUsage, } pub struct Events { } impl Startup { #[must_use] pub fn new (server_name: String) -> Self { let x = Self { machine_id: get_machine_id (), git_version: None, server_name, instance_id: ulid::Ulid::new (), startup_utc: Utc::now (), }; debug! ("metrics at startup: {:?}", x); x } } fn serialize_ulid (t: &Ulid, s: S) -> Result { let t = t.to_string (); s.serialize_str (&t) } impl Interval { pub async fn new () -> Result { use tokio::join; use heim::process; use uom::si::{ information::mebibyte, ratio, time::second, }; let our_process = process::current ().await?; let cpu_usage = our_process.cpu_usage (); let (cpu_usage, mem) = join! { cpu_usage, our_process.memory () }; let cpu_usage = cpu_usage?; let mem = mem?; let rss_mib = mem.rss ().get:: (); let x = Self { at: Instant::now (), utc: Utc::now (), rss_mib, cpu_usage, }; Ok (x) } pub async fn monitor (interval_writer: Arc >>) { use uom::si::ratio::percent; let mut interval = tokio::time::interval (Duration::from_secs (60)); #[derive (Default)] struct Window { window_length: u64, next_interval: u64, last_metrics: Arc