use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::session_manager::{ManagedSessionState, SessionRecord};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PendingDecision {
pub session_id: String,
pub tmux_name: String,
pub question: String,
pub proposed_default: Option<String>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct SupervisorRunStats {
pub sweeps: u64,
pub auto_resumed: u64,
pub resume_failures: u64,
pub classified: u64,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct FleetMetrics {
pub provisioning: u64,
pub active: u64,
pub stopped: u64,
pub errored: u64,
pub decommissioned: u64,
pub total: u64,
pub pending_decisions: Vec<PendingDecision>,
pub last_activity_at: Option<DateTime<Utc>>,
pub run_stats: SupervisorRunStats,
}
impl FleetMetrics {
pub fn from_records(records: &[SessionRecord]) -> Self {
let mut m = FleetMetrics {
total: records.len() as u64,
..Default::default()
};
for r in records {
match r.state {
ManagedSessionState::Provisioning => m.provisioning += 1,
ManagedSessionState::Active => m.active += 1,
ManagedSessionState::Stopped => m.stopped += 1,
ManagedSessionState::Errored => m.errored += 1,
ManagedSessionState::Decommissioned => m.decommissioned += 1,
}
if let Some(ref question) = r.pending_decision {
m.pending_decisions.push(PendingDecision {
session_id: r.id.to_string(),
tmux_name: r.tmux_name.clone(),
question: question.clone(),
proposed_default: r.proposed_default.clone(),
});
}
if let Some(ts) = r.last_activity_at {
m.last_activity_at = Some(match m.last_activity_at {
Some(cur) if cur >= ts => cur,
_ => ts,
});
}
}
m
}
}