use std::sync::Arc;
use atomr_core::actor::ActorSystem;
use atomr_telemetry::TelemetryExtension;
use parking_lot::Mutex;
pub fn install(system: &ActorSystem, node_name: impl Into<String>) -> Arc<TelemetryExtension> {
TelemetryExtension::new(node_name, 1024).install(system)
}
#[derive(Default)]
pub struct GpuProbes {
inner: Mutex<GpuProbeState>,
}
#[derive(Default, Debug, Clone)]
pub struct GpuProbeState {
pub allocations_total: u64,
pub oom_total: u64,
pub max_generation_observed: u64,
pub kernels_in_flight: u32,
pub kernels_total: u64,
pub vram_free_bytes: u64,
pub vram_total_bytes: u64,
}
impl GpuProbes {
pub fn new() -> Arc<Self> {
Arc::new(Self::default())
}
pub fn record_alloc_ok(&self) {
let mut g = self.inner.lock();
g.allocations_total = g.allocations_total.saturating_add(1);
}
pub fn record_alloc_oom(&self) {
let mut g = self.inner.lock();
g.oom_total = g.oom_total.saturating_add(1);
}
pub fn record_generation(&self, gen: u64) {
let mut g = self.inner.lock();
if gen > g.max_generation_observed {
g.max_generation_observed = gen;
}
}
pub fn kernel_enter(&self) {
let mut g = self.inner.lock();
g.kernels_in_flight = g.kernels_in_flight.saturating_add(1);
g.kernels_total = g.kernels_total.saturating_add(1);
}
pub fn kernel_exit(&self) {
let mut g = self.inner.lock();
g.kernels_in_flight = g.kernels_in_flight.saturating_sub(1);
}
pub fn record_vram(&self, free_bytes: u64, total_bytes: u64) {
let mut g = self.inner.lock();
g.vram_free_bytes = free_bytes;
g.vram_total_bytes = total_bytes;
}
pub fn snapshot(&self) -> GpuProbeState {
self.inner.lock().clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
use atomr_config::Config;
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn install_returns_handle_and_from_system_finds_it() {
let sys = ActorSystem::create("obs-test", Config::empty())
.await
.unwrap();
let handle = install(&sys, "obs-test");
assert_eq!(handle.node, "obs-test");
let from_sys = TelemetryExtension::from_system(&sys).expect("installed");
assert_eq!(from_sys.node, "obs-test");
sys.terminate().await;
}
#[test]
fn gpu_probes_record_lifecycle() {
let p = GpuProbes::new();
p.record_alloc_ok();
p.record_alloc_ok();
p.record_alloc_oom();
p.record_generation(1);
p.record_generation(3);
p.record_generation(2); p.kernel_enter();
p.kernel_enter();
p.kernel_exit();
p.record_vram(2048, 4096);
let s = p.snapshot();
assert_eq!(s.allocations_total, 2);
assert_eq!(s.oom_total, 1);
assert_eq!(s.max_generation_observed, 3);
assert_eq!(s.kernels_in_flight, 1);
assert_eq!(s.kernels_total, 2);
assert_eq!(s.vram_free_bytes, 2048);
assert_eq!(s.vram_total_bytes, 4096);
}
}