mirror of
https://codeberg.org/icewind/palantir.git
synced 2026-06-03 18:24:08 +02:00
docker stats
This commit is contained in:
parent
a9fd4d64a4
commit
0a571c9039
5 changed files with 484 additions and 3 deletions
61
src/docker.rs
Normal file
61
src/docker.rs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
use bollard::container::Stats;
|
||||
use bollard::Docker;
|
||||
use color_eyre::Result;
|
||||
use futures_util::stream::{iter, Stream, StreamExt};
|
||||
use std::fmt::Write;
|
||||
|
||||
pub struct Container {
|
||||
name: String,
|
||||
memory: u64,
|
||||
cpu_time: u64,
|
||||
}
|
||||
|
||||
impl From<Stats> for Container {
|
||||
fn from(stats: Stats) -> Self {
|
||||
Container {
|
||||
name: stats.name,
|
||||
memory: stats.memory_stats.usage.unwrap_or_default(),
|
||||
cpu_time: stats.cpu_stats.cpu_usage.total_usage,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Container {
|
||||
pub fn write<W: Write>(&self, mut w: W, hostname: &str) {
|
||||
writeln!(
|
||||
&mut w,
|
||||
"container_memory{{host=\"{}\", container=\"{}\"}} {}",
|
||||
hostname, self.name, self.memory
|
||||
)
|
||||
.ok();
|
||||
writeln!(
|
||||
&mut w,
|
||||
"container_cpu_time{{host=\"{}\", container=\"{}\"}} {}",
|
||||
hostname, self.name, self.cpu_time
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_docker() -> Option<Docker> {
|
||||
match Docker::connect_with_local_defaults() {
|
||||
Ok(docker) => docker
|
||||
.list_containers::<String>(None)
|
||||
.await
|
||||
.ok()
|
||||
.map(|_| docker),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn stat(docker: Docker) -> Result<impl Stream<Item = Container>> {
|
||||
let containers = docker.list_containers::<String>(None).await?;
|
||||
Ok(iter(containers.into_iter()).filter_map(move |container| {
|
||||
let docker = docker.clone();
|
||||
async move {
|
||||
let id = container.id.unwrap();
|
||||
let stats: Stats = docker.stats(&id, None).next().await?.ok()?;
|
||||
Some(stats.into())
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
pub mod docker;
|
||||
pub mod sensors;
|
||||
pub mod zfs;
|
||||
|
||||
|
|
|
|||
28
src/main.rs
28
src/main.rs
|
|
@ -1,4 +1,8 @@
|
|||
use bollard::Docker;
|
||||
use color_eyre::{Report, Result};
|
||||
use futures_util::pin_mut;
|
||||
use futures_util::StreamExt;
|
||||
use palantir::docker::{get_docker, stat, Container};
|
||||
use palantir::get_metrics;
|
||||
use warp::reject::Reject;
|
||||
use warp::{Filter, Rejection};
|
||||
|
|
@ -15,8 +19,23 @@ impl From<Report> for ReportRejection {
|
|||
|
||||
impl Reject for ReportRejection {}
|
||||
|
||||
async fn serve_metrics() -> Result<String, Rejection> {
|
||||
get_metrics()
|
||||
async fn serve_inner(docker: Option<Docker>) -> Result<String> {
|
||||
let mut metrics = get_metrics()?;
|
||||
if let Some(docker) = docker {
|
||||
let hostname = palantir::sensors::hostname()?;
|
||||
let containers = stat(docker).await?;
|
||||
pin_mut!(containers);
|
||||
while let Some(container) = containers.next().await {
|
||||
let container: Container = container;
|
||||
container.write(&mut metrics, &hostname);
|
||||
}
|
||||
}
|
||||
Ok(metrics)
|
||||
}
|
||||
|
||||
async fn serve_metrics(docker: Option<Docker>) -> Result<String, Rejection> {
|
||||
serve_inner(docker)
|
||||
.await
|
||||
.map_err(ReportRejection::from)
|
||||
.map_err(warp::reject::custom)
|
||||
}
|
||||
|
|
@ -34,7 +53,10 @@ async fn main() -> Result<()> {
|
|||
})
|
||||
.expect("Error setting Ctrl-C handler");
|
||||
|
||||
let metrics = warp::path!("metrics").and_then(serve_metrics);
|
||||
let docker = get_docker().await;
|
||||
let docker = warp::any().map(move || docker.clone());
|
||||
|
||||
let metrics = warp::path!("metrics").and(docker).and_then(serve_metrics);
|
||||
|
||||
warp::serve(metrics).run(([0, 0, 0, 0], host_port)).await;
|
||||
Ok(())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue