micromegas_telemetry_sink/
system_monitor.rs1use micromegas_tracing::{fmetric, imetric};
2use std::time::{Duration, Instant};
3use sysinfo::{CpuRefreshKind, MemoryRefreshKind, RefreshKind, System};
4
5const SLOW_SAMPLE_INTERVAL: Duration = Duration::from_secs(5);
12
13pub fn should_sample_slow(elapsed_since_last_sample: Duration) -> bool {
19 elapsed_since_last_sample >= SLOW_SAMPLE_INTERVAL
20}
21
22pub fn emit_process_memory_stats(system: &mut System) {
29 use sysinfo::{ProcessRefreshKind, ProcessesToUpdate};
30 let Ok(pid) = sysinfo::get_current_pid() else {
31 return;
32 };
33 system.refresh_processes_specifics(
34 ProcessesToUpdate::Some(&[pid]),
35 false,
36 ProcessRefreshKind::nothing().with_memory(),
37 );
38 if let Some(process) = system.process(pid) {
39 imetric!("process_resident_bytes", "bytes", process.memory());
40 imetric!("process_virtual_bytes", "bytes", process.virtual_memory());
41 }
42}
43
44#[cfg(all(feature = "jemalloc", not(target_os = "windows")))]
48pub fn emit_jemalloc_stats() {
49 use tikv_jemalloc_ctl::{epoch, stats};
50 if epoch::advance().is_err() {
53 return;
54 }
55 if let Ok(v) = stats::allocated::read() {
56 imetric!("jemalloc_allocated_bytes", "bytes", v as u64);
57 }
58 if let Ok(v) = stats::resident::read() {
59 imetric!("jemalloc_resident_bytes", "bytes", v as u64);
60 }
61 if let Ok(v) = stats::mapped::read() {
62 imetric!("jemalloc_mapped_bytes", "bytes", v as u64);
63 }
64 if let Ok(v) = stats::retained::read() {
65 imetric!("jemalloc_retained_bytes", "bytes", v as u64);
66 }
67}
68
69#[cfg(not(all(feature = "jemalloc", not(target_os = "windows"))))]
70pub fn emit_jemalloc_stats() {}
71
72pub fn send_system_metrics_forever() {
80 let what_to_refresh = RefreshKind::nothing()
81 .with_cpu(CpuRefreshKind::nothing().with_cpu_usage())
82 .with_memory(MemoryRefreshKind::nothing().with_ram());
83 let mut system = System::new_with_specifics(what_to_refresh);
84 imetric!("total_memory", "bytes", system.total_memory());
85 let mut process_system = System::new();
86 let mut last_slow_sample = Instant::now();
87 loop {
88 std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
89 system.refresh_specifics(what_to_refresh);
90 imetric!("used_memory", "bytes", system.used_memory());
91 imetric!("free_memory", "bytes", system.free_memory());
92 fmetric!("cpu_usage", "percent", system.global_cpu_usage() as f64);
93
94 if should_sample_slow(last_slow_sample.elapsed()) {
95 emit_process_memory_stats(&mut process_system);
96 emit_jemalloc_stats();
97 last_slow_sample = Instant::now();
98 }
99 }
100}
101
102pub fn spawn_system_monitor() {
106 std::thread::spawn(send_system_metrics_forever);
107}