feat: guest metrics support (#46)

* feat: initial support for idm send in daemon

* feat: implement IdmClient backend support

* feat: daemon idm now uses IdmClient

* fix: implement channel destruction propagation

* feat: implement request response idm system

* feat: implement metrics support

* proto: move metrics into GuestMetrics for reusability

* fix: log level of guest agent was trace

* feat: metrics tree with process information
This commit is contained in:
Alex Zenla
2024-04-12 00:34:46 -07:00
committed by GitHub
parent ec9060d872
commit 5e16f3149f
27 changed files with 1211 additions and 278 deletions

View File

@ -1,16 +1,20 @@
use crate::{
childwait::{ChildEvent, ChildWait},
death,
metrics::MetricsCollector,
};
use anyhow::Result;
use cgroups_rs::Cgroup;
use krata::idm::{
client::IdmClient,
protocol::{idm_event::Event, IdmEvent, IdmExitEvent, IdmPacket},
protocol::{
idm_event::Event, idm_request::Request, idm_response::Response, IdmEvent, IdmExitEvent,
IdmMetricsResponse, IdmPingResponse, IdmRequest,
},
};
use log::error;
use log::debug;
use nix::unistd::Pid;
use tokio::select;
use tokio::{select, sync::broadcast};
pub struct GuestBackground {
idm: IdmClient,
@ -30,16 +34,37 @@ impl GuestBackground {
}
pub async fn run(&mut self) -> Result<()> {
let mut event_subscription = self.idm.subscribe().await?;
let mut requests_subscription = self.idm.requests().await?;
loop {
select! {
x = self.idm.receiver.recv() => match x {
Some(_packet) => {
x = event_subscription.recv() => match x {
Ok(_event) => {
},
None => {
error!("idm packet channel closed");
Err(broadcast::error::RecvError::Closed) => {
debug!("idm packet channel closed");
break;
},
_ => {
continue;
}
},
x = requests_subscription.recv() => match x {
Ok(request) => {
self.handle_idm_request(request).await?;
},
Err(broadcast::error::RecvError::Closed) => {
debug!("idm packet channel closed");
break;
},
_ => {
continue;
}
},
@ -54,14 +79,34 @@ impl GuestBackground {
Ok(())
}
async fn handle_idm_request(&mut self, packet: IdmRequest) -> Result<()> {
let id = packet.id;
match packet.request {
Some(Request::Ping(_)) => {
self.idm
.respond(id, Response::Ping(IdmPingResponse {}))
.await?;
}
Some(Request::Metrics(_)) => {
let metrics = MetricsCollector::new()?;
let root = metrics.collect()?;
let response = IdmMetricsResponse { root: Some(root) };
self.idm.respond(id, Response::Metrics(response)).await?;
}
None => {}
}
Ok(())
}
async fn child_event(&mut self, event: ChildEvent) -> Result<()> {
if event.pid == self.child {
self.idm
.sender
.send(IdmPacket {
event: Some(IdmEvent {
event: Some(Event::Exit(IdmExitEvent { code: event.status })),
}),
.emit(IdmEvent {
event: Some(Event::Exit(IdmExitEvent { code: event.status })),
})
.await?;
death(event.status).await?;