runnerd_core/api/
stats.rs1use super::{Stats, StatsRow};
6
7#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
9pub struct StatsSummary {
10 pub start: u64,
12 pub jobs: u64,
14 pub succeeded: u64,
16 pub failed: u64,
18 pub cancelled: u64,
20 pub queue_seconds: u64,
22 pub run_seconds: u64,
24 pub memory_peak: Option<u64>,
26}
27
28impl StatsSummary {
29 fn add(&mut self, row: &StatsRow) {
30 self.jobs += row.jobs;
31 self.succeeded += row.succeeded;
32 self.failed += row.failed;
33 self.cancelled += row.cancelled;
34 self.queue_seconds += row.queue_seconds;
35 self.run_seconds += row.run_seconds;
36 self.memory_peak = self
37 .memory_peak
38 .max((row.memory_peak > 0).then_some(row.memory_peak));
39 }
40
41 pub fn of(summaries: &[StatsSummary]) -> StatsSummary {
43 summaries.iter().fold(
44 StatsSummary {
45 start: summaries.first().map_or(0, |summary| summary.start),
46 ..StatsSummary::default()
47 },
48 |total, summary| StatsSummary {
49 start: total.start,
50 jobs: total.jobs + summary.jobs,
51 succeeded: total.succeeded + summary.succeeded,
52 failed: total.failed + summary.failed,
53 cancelled: total.cancelled + summary.cancelled,
54 queue_seconds: total.queue_seconds + summary.queue_seconds,
55 run_seconds: total.run_seconds + summary.run_seconds,
56 memory_peak: total.memory_peak.max(summary.memory_peak),
57 },
58 )
59 }
60
61 pub fn other(&self) -> u64 {
63 self.jobs
64 .saturating_sub(self.succeeded + self.failed + self.cancelled)
65 }
66
67 pub fn success_percent(&self) -> Option<u64> {
69 (self.succeeded * 100).checked_div(self.jobs)
70 }
71
72 pub fn average_run(&self) -> Option<u64> {
74 self.run_seconds.checked_div(self.jobs)
75 }
76
77 pub fn average_wait(&self) -> Option<u64> {
79 self.queue_seconds.checked_div(self.jobs)
80 }
81}
82
83impl Stats {
84 pub fn daily(&self, first: u64, days: u64) -> Vec<StatsSummary> {
87 let mut summaries: Vec<StatsSummary> = (0..days)
88 .map(|day| StatsSummary {
89 start: first + day * 86_400,
90 ..StatsSummary::default()
91 })
92 .collect();
93 for row in &self.rows {
94 if let Some(summary) = summaries
95 .iter_mut()
96 .find(|summary| summary.start == row.start)
97 {
98 summary.add(row);
99 }
100 }
101 summaries
102 }
103}
104
105#[cfg(test)]
106mod tests;