use std::fmt::Write as _;
use axum::extract::State;
use axum::http::header::CONTENT_TYPE;
use axum::response::IntoResponse;
use crate::routes::http::AppState;
use crate::routines::{svc_list_all_runs, FleetRunSummary, RunStatus};
use crate::utils::time::now_secs;
const PROMETHEUS_CONTENT_TYPE: &str = "text/plain; version=0.0.4; charset=utf-8";
const DURATION_BUCKETS_SECS: [u64; 9] = [5, 15, 30, 60, 120, 300, 600, 1800, 3600];
struct MetricsSnapshot<'input> {
uptime_secs: u64,
version: &'input str,
git_sha: &'input str,
machine: &'input str,
active_sessions: usize,
workbench_bytes: u64,
repo_cache_bytes: u64,
runs: &'input [FleetRunSummary],
cleanup_removed_total: u64,
cleanup_freed_bytes_total: u64,
}
#[utoipa::path(get, path = "/metrics",
responses((status = 200, description = "Prometheus text exposition format (version 0.0.4)", body = str)))]
pub async fn metrics(State(state): State<AppState>) -> impl IntoResponse {
let runs = svc_list_all_runs(&state.routines, Some(usize::MAX));
let machine = crate::machine::current_machine();
let (cleanup_removed_total, cleanup_freed_bytes_total) =
crate::routines::cleanup_sweep_totals();
let snapshot = MetricsSnapshot {
uptime_secs: now_secs().saturating_sub(state.uptime_start),
version: crate::build_info::VERSION,
git_sha: crate::build_info::GIT_SHA,
machine: machine.as_str(),
active_sessions: crate::routines::tmux_session_count(crate::routines::TMUX_SESSION_PREFIX),
workbench_bytes: crate::routines::workbenches_total_bytes(),
repo_cache_bytes: crate::routines::repo_cache_total_bytes(),
runs: &runs,
cleanup_removed_total,
cleanup_freed_bytes_total,
};
([(CONTENT_TYPE, PROMETHEUS_CONTENT_TYPE)], render(&snapshot))
}
#[derive(Default)]
struct RunStatusCounts {
success: u64,
failed: u64,
running: u64,
unknown: u64,
}
fn escape_label_value(value: &str) -> String {
value
.replace('\\', "\\\\")
.replace('"', "\\\"")
.replace('\n', "\\n")
}
include!("render.rs");