Skip to main content

cronoq_core/
snapshot.rs

1//! Point-in-time metrics: pool state plus quality signals computed over a sliding window.
2
3use core::time::Duration;
4use std::sync::Arc;
5
6use crate::engine::Totals;
7use crate::spec::Priority;
8use crate::time::Time;
9
10/// State and windowed quality metrics of one pool.
11///
12/// Counters and ratios cover the last [`PoolSnapshot::window`]
13/// (`CoreConfig::metrics_window`); `worker_seconds` and `cost` accumulate since start.
14#[derive(Clone, Debug)]
15pub struct PoolSnapshot {
16    /// Pool name.
17    pub name: Arc<str>,
18    /// Workers currently available to the pool.
19    pub capacity: u32,
20    /// Workers currently running a task.
21    pub busy: u32,
22    /// Workers held free for upcoming fixed-start tasks.
23    pub held: u32,
24    /// Last autoscaler target (equals capacity without autoscaling).
25    pub desired: u32,
26    /// Tasks not yet running (blocked, scheduled, ready or retrying), by priority class.
27    pub pending_by_class: [usize; Priority::COUNT],
28    /// Tasks ready to run right now (queued or due).
29    pub ready: usize,
30    /// Active fixed-start reservations.
31    pub reservations: usize,
32    /// Length of the metrics window.
33    pub window: Duration,
34    /// Attempts started in the window.
35    pub dispatched: u64,
36    /// Tasks that succeeded in the window.
37    pub succeeded: u64,
38    /// Attempts that failed in the window (including ones that will be retried).
39    pub failed: u64,
40    /// Retries scheduled in the window.
41    pub retried: u64,
42    /// Fraction of dispatches where no strictly higher class was waiting in the pool.
43    pub priority_adherence: f64,
44    /// Fraction of fixed-start tasks started within tolerance (first attempts only).
45    pub fixed_start_hit_rate: f64,
46    /// Busy slot-seconds / capacity slot-seconds.
47    pub utilization: f64,
48    /// Completed work seconds / capacity slot-seconds.
49    pub schedule_efficiency: f64,
50    /// Mean time from submission to first start.
51    pub wait_mean: Duration,
52    /// Median time from submission to first start.
53    pub wait_p50: Duration,
54    /// 90th-percentile time from submission to first start.
55    pub wait_p90: Duration,
56    /// 99th-percentile time from submission to first start.
57    pub wait_p99: Duration,
58    /// Median runtime of successful attempts.
59    pub run_p50: Duration,
60    /// 99th-percentile runtime of successful attempts.
61    pub run_p99: Duration,
62    /// Capacity slot-seconds provisioned since start.
63    pub worker_seconds: f64,
64    /// `worker_seconds × AutoscaleConfig::cost_per_worker_second` since start.
65    pub cost: f64,
66    /// Worker groups by label set (the unlabeled group first).
67    pub groups: Vec<GroupSnapshot>,
68}
69
70impl PoolSnapshot {
71    /// Total tasks not yet running.
72    pub fn pending(&self) -> usize {
73        self.pending_by_class.iter().sum()
74    }
75}
76
77/// Engine-wide snapshot returned by [`Core::snapshot`](crate::Core::snapshot).
78#[derive(Clone, Debug)]
79pub struct Snapshot {
80    /// Engine time of the snapshot.
81    pub at: Time,
82    /// Per-pool state, in configuration order.
83    pub pools: Vec<PoolSnapshot>,
84    /// Tasks not yet in a terminal status.
85    pub live_tasks: usize,
86    /// Attempts currently running.
87    pub running: usize,
88    /// Tasks not yet running.
89    pub pending: usize,
90    /// Counters since start.
91    pub totals: Totals,
92}
93
94impl Snapshot {
95    /// The snapshot of the pool named `name`.
96    pub fn pool(&self, name: &str) -> Option<&PoolSnapshot> {
97        self.pools.iter().find(|p| &*p.name == name)
98    }
99}
100
101/// Capacity of the workers of a pool that share one label set.
102#[derive(Clone, Debug, Default, PartialEq)]
103pub struct GroupSnapshot {
104    /// The group's labels, sorted (empty for unlabeled workers).
105    pub labels: Vec<(Arc<str>, Arc<str>)>,
106    /// Slots of the group's workers.
107    pub capacity: u32,
108    /// Slots running a task.
109    pub busy: u32,
110}