#![feature(str_as_str, try_blocks_heterogeneous)]
use anyhow::{Context as _, Result, anyhow};
use mimalloc::MiMalloc;
use nil_log::{Directives, Layers};
use nil_server::remote;
use std::time::Duration;
use sysinfo::{ProcessRefreshKind, ProcessesToUpdate, RefreshKind, System};
use tokio::runtime::Handle;
use tokio::task::spawn;
use tokio::time::sleep;
#[global_allocator]
static ALLOCATOR: MiMalloc = MiMalloc;
#[tokio::main]
async fn main() -> Result<()> {
let _guard = nil_log::setup()
.directives(Directives::all())
.debug_layers(Layers::STDERR)
.release_layers(Layers::FILE)
.call()?;
watch_process()?;
let result = try bikeshed Result<()> {
let database_url = nil_env::database_url()?;
remote::start(database_url.as_str()).await?;
};
if let Err(err) = &result {
tracing::error!(message = %err, error = ?err);
}
result
}
fn watch_process() -> Result<()> {
let pid = sysinfo::get_current_pid()
.map_err(|err| anyhow!("{err}"))
.context("Failed to get process pid")?;
let mut sys = System::new_with_specifics(
RefreshKind::nothing().with_processes(
ProcessRefreshKind::nothing()
.with_cpu()
.with_memory(),
),
);
spawn(async move {
loop {
sys.refresh_processes_specifics(
ProcessesToUpdate::Some(&[pid]),
true,
ProcessRefreshKind::nothing()
.with_cpu()
.with_memory(),
);
if let Some(process) = sys.process(pid) {
let runtime = Handle::current();
let metrics = runtime.metrics();
tracing::info!(
name = %process.name().to_string_lossy(),
cpu_usage = %process.cpu_usage(),
memory = %process.memory(),
run_time = %process.run_time(),
tokio_num_alive_tasks = %metrics.num_alive_tasks(),
tokio_num_workers = %metrics.num_workers(),
);
}
sleep(Duration::from_mins(1)).await;
}
});
Ok(())
}