use std::{io, sync::atomic::AtomicU64};
use crate::target::TargetPidReceiver;
use serde::Deserialize;
use crate::signals::Shutdown;
#[cfg(target_os = "linux")]
mod linux;
pub(crate) static RSS_BYTES: AtomicU64 = AtomicU64::new(0);
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("erno: {0}")]
Errno(#[from] nix::errno::Errno),
#[error("IO error: {0}")]
Io(#[from] io::Error),
#[cfg(target_os = "linux")]
#[error("Linux error: {0}")]
Linux(#[from] linux::Error),
}
#[derive(Debug, Deserialize, Clone, Copy, Default, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub struct Config {}
#[derive(Debug)]
pub struct Server {
#[allow(dead_code)] config: Config,
#[allow(dead_code)] shutdown: Shutdown,
}
impl Server {
pub fn new(config: Config, shutdown: Shutdown) -> Result<Self, Error> {
Ok(Self { config, shutdown })
}
#[allow(
clippy::similar_names,
clippy::too_many_lines,
clippy::cast_possible_truncation,
clippy::cast_sign_loss
)]
#[cfg(target_os = "linux")]
pub async fn run(mut self, mut pid_snd: TargetPidReceiver) -> Result<(), Error> {
use std::time::Duration;
use crate::observer::linux::Sampler;
let target_pid = pid_snd
.recv()
.await
.expect("target failed to transmit PID, catastrophic failure");
drop(pid_snd);
let target_pid = target_pid.expect("observer cannot be used in no-target mode");
let mut sample_delay = tokio::time::interval(Duration::from_secs(1));
let mut sampler = Sampler::new(target_pid)?;
loop {
tokio::select! {
_ = sample_delay.tick() => {
sampler.sample()?;
}
_ = self.shutdown.recv() => {
tracing::info!("shutdown signal received");
return Ok(());
}
}
}
}
#[allow(clippy::unused_async)]
#[cfg(not(target_os = "linux"))]
pub async fn run(self, _pid_snd: TargetPidReceiver) -> Result<(), Error> {
tracing::warn!("observer unavailable on non-Linux system");
Ok(())
}
}