refactor(irtt-stats): consolidate snapshot types and rename summary to snapshot

This commit is contained in:
Nils Andreas Svee committed 2026-05-13 12:21:51 +07:00
1 parent 197903fb8e
commit 542e67bf74
4 files changed
+28 -40

No files matched your search

+3 -3
View File
@@ -237,7 +237,7 @@ impl<W: Write> EventOutput<'_, W> {
self.out, self.out,
"{}", "{}",
irtt_cli::summary::format_summary_with_options( irtt_cli::summary::format_summary_with_options(
&self.stats.summary(), &self.stats.snapshot(),
irtt_cli::summary::SummaryFormatOptions { irtt_cli::summary::SummaryFormatOptions {
verbose: self.human_options.verbose, verbose: self.human_options.verbose,
}, },
@@ -390,7 +390,7 @@ mod tests {
} }
let rendered = String::from_utf8(out).unwrap(); let rendered = String::from_utf8(out).unwrap();
let summary = stats.summary(); let summary = stats.snapshot();
assert_eq!(rendered, "1200\n"); assert_eq!(rendered, "1200\n");
assert_eq!(summary.packets.packets_sent, 1); assert_eq!(summary.packets.packets_sent, 1);
assert_eq!(summary.packets.unique_replies, 1); assert_eq!(summary.packets.unique_replies, 1);
@@ -462,7 +462,7 @@ mod tests {
}); });
} }
assert_eq!(collector.summary().rtt.primary.median_ns, None); assert_eq!(collector.snapshot().rtt.primary.median_ns, None);
} }
#[test] #[test]
+6 -11
View File
@@ -1,10 +1,8 @@
use std::fmt::Write as _; use std::fmt::Write as _;
use irtt_stats::{ use irtt_stats::{DurationStats, DurationStatsWithMedian, SignedDurationStatsWithMedian, Snapshot};
DurationStats, DurationStatsWithMedian, FiniteSummary, SignedDurationStatsWithMedian,
};
pub fn format_summary(summary: &FiniteSummary) -> String { pub fn format_summary(summary: &Snapshot) -> String {
format_summary_with_options(summary, SummaryFormatOptions::default()) format_summary_with_options(summary, SummaryFormatOptions::default())
} }
@@ -13,10 +11,7 @@ pub struct SummaryFormatOptions {
pub verbose: bool, pub verbose: bool,
} }
pub fn format_summary_with_options( pub fn format_summary_with_options(summary: &Snapshot, options: SummaryFormatOptions) -> String {
summary: &FiniteSummary,
options: SummaryFormatOptions,
) -> String {
let mut out = String::new(); let mut out = String::new();
let packets = summary.packets; let packets = summary.packets;
let loss = summary.loss; let loss = summary.loss;
@@ -207,7 +202,7 @@ mod tests {
#[test] #[test]
fn empty_summary_omits_optional_metric_sections() { fn empty_summary_omits_optional_metric_sections() {
let summary = StatsCollector::new(StatsConfig::finite()).summary(); let summary = StatsCollector::new(StatsConfig::finite()).snapshot();
let output = format_summary(&summary); let output = format_summary(&summary);
assert!(output.contains("Metric")); assert!(output.contains("Metric"));
@@ -263,7 +258,7 @@ mod tests {
packet_meta: PacketMeta::default(), packet_meta: PacketMeta::default(),
}); });
let output = format_summary(&collector.summary()); let output = format_summary(&collector.snapshot());
assert!(output.contains("packets: sent=1 received=1 unique=1 lost=0 loss=0.00%")); assert!(output.contains("packets: sent=1 received=1 unique=1 lost=0 loss=0.00%"));
assert!(output.contains("bytes: sent=64 received=64")); assert!(output.contains("bytes: sent=64 received=64"));
@@ -303,7 +298,7 @@ mod tests {
}); });
let output = format_summary_with_options( let output = format_summary_with_options(
&collector.summary(), &collector.snapshot(),
SummaryFormatOptions { verbose: true }, SummaryFormatOptions { verbose: true },
); );
+7 -14
View File
@@ -104,25 +104,18 @@ impl StatsCollector {
update update
} }
pub fn cumulative(&self) -> CumulativeSnapshot { pub fn snapshot(&self) -> Snapshot {
self.cumulative.snapshot() self.cumulative.snapshot()
} }
pub fn rolling_count(&self) -> Option<RollingSnapshot> { pub fn rolling_count(&self) -> Option<Snapshot> {
self.rolling_count.as_ref().map(snapshot_window) self.rolling_count.as_ref().map(snapshot_window)
} }
pub fn rolling_time(&self) -> Option<RollingSnapshot> { pub fn rolling_time(&self) -> Option<Snapshot> {
self.rolling_time.as_ref().map(snapshot_window) self.rolling_time.as_ref().map(snapshot_window)
} }
pub fn summary(&self) -> FiniteSummary {
self.cumulative()
} }
}
pub type RollingSnapshot = CumulativeSnapshot;
pub type FiniteSummary = CumulativeSnapshot;
#[derive(Debug, Clone, PartialEq, Eq, Default)] #[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct EventStatsUpdate { pub struct EventStatsUpdate {
@@ -140,7 +133,7 @@ pub struct IpdvPairUpdate {
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct CumulativeSnapshot { pub struct Snapshot {
pub events: EventCounts, pub events: EventCounts,
pub packets: PacketCounts, pub packets: PacketCounts,
pub loss: LossStats, pub loss: LossStats,
@@ -462,9 +455,9 @@ impl CoreStats {
}) })
} }
fn snapshot(&self) -> CumulativeSnapshot { fn snapshot(&self) -> Snapshot {
let packets = self.packets; let packets = self.packets;
CumulativeSnapshot { Snapshot {
events: self.events, events: self.events,
packets, packets,
loss: loss_stats(packets), loss: loss_stats(packets),
@@ -812,7 +805,7 @@ impl RunningI128 {
} }
} }
fn snapshot_window(events: &VecDeque<WindowEvent>) -> CumulativeSnapshot { fn snapshot_window(events: &VecDeque<WindowEvent>) -> Snapshot {
let mut core = CoreStats::new(MedianMode::Disabled); let mut core = CoreStats::new(MedianMode::Disabled);
for event in events { for event in events {
core.apply(event.clone()); core.apply(event.clone());
+12 -12
View File
@@ -12,7 +12,7 @@ fn disabled_median_avoids_finite_retention() {
collector.process(&reply(0, 10, 9)); collector.process(&reply(0, 10, 9));
collector.process(&reply(1, 20, 19)); collector.process(&reply(1, 20, 19));
let snapshot = collector.cumulative(); let snapshot = collector.snapshot();
assert_eq!(snapshot.rtt.primary.median_ns, None); assert_eq!(snapshot.rtt.primary.median_ns, None);
assert_eq!(snapshot.rtt.raw.median_ns, None); assert_eq!(snapshot.rtt.raw.median_ns, None);
assert_eq!(snapshot.rtt.adjusted.median_ns, None); assert_eq!(snapshot.rtt.adjusted.median_ns, None);
@@ -28,7 +28,7 @@ fn continuous_mode_tracks_samples_without_exact_medians() {
collector.process(&reply(seq, 10, 10)); collector.process(&reply(seq, 10, 10));
} }
let snapshot = collector.cumulative(); let snapshot = collector.snapshot();
assert_eq!(snapshot.rtt.primary.stats.count, 4104); assert_eq!(snapshot.rtt.primary.stats.count, 4104);
assert_eq!(snapshot.ipdv.round_trip.stats.count, 4103); assert_eq!(snapshot.ipdv.round_trip.stats.count, 4103);
assert_eq!(snapshot.rtt.primary.median_ns, None); assert_eq!(snapshot.rtt.primary.median_ns, None);
@@ -41,7 +41,7 @@ fn cumulative_rtt_uses_signed_effective_and_tracks_raw() {
collector.process(&reply(0, 1, -2)); collector.process(&reply(0, 1, -2));
collector.process(&reply(1, 10, 8)); collector.process(&reply(1, 10, 8));
let snapshot = collector.cumulative(); let snapshot = collector.snapshot();
assert_eq!(snapshot.rtt.primary.stats.count, 2); assert_eq!(snapshot.rtt.primary.stats.count, 2);
assert_eq!(snapshot.rtt.primary.stats.min_ns, Some(-2_000_000)); assert_eq!(snapshot.rtt.primary.stats.min_ns, Some(-2_000_000));
assert_eq!(snapshot.rtt.primary.median_ns, Some(3_000_000.0)); assert_eq!(snapshot.rtt.primary.median_ns, Some(3_000_000.0));
@@ -62,7 +62,7 @@ fn late_unique_counts_and_duplicates_do_not_update_measurements() {
bytes: 64, bytes: 64,
}); });
let snapshot = collector.cumulative(); let snapshot = collector.snapshot();
assert_eq!(snapshot.packets.packets_sent, 2); assert_eq!(snapshot.packets.packets_sent, 2);
assert_eq!(snapshot.packets.packets_received, 3); assert_eq!(snapshot.packets.packets_received, 3);
assert_eq!(snapshot.packets.unique_replies, 2); assert_eq!(snapshot.packets.unique_replies, 2);
@@ -85,7 +85,7 @@ fn final_loss_uses_sent_minus_unique_replies_not_echo_loss_events() {
}); });
collector.process(&late_reply(0, 10, 9)); collector.process(&late_reply(0, 10, 9));
let snapshot = collector.summary(); let snapshot = collector.snapshot();
assert_eq!(snapshot.events.loss_events, 1); assert_eq!(snapshot.events.loss_events, 1);
assert_eq!(snapshot.packets.unique_replies, 1); assert_eq!(snapshot.packets.unique_replies, 1);
assert_eq!(snapshot.loss.lost_packets, 1); assert_eq!(snapshot.loss.lost_packets, 1);
@@ -117,7 +117,7 @@ fn ipdv_is_sequence_adjacent_and_gap_preserving() {
let gap = collector.process(&reply(2, 15, 15)); let gap = collector.process(&reply(2, 15, 15));
let adjacent = collector.process(&reply(3, 12, 12)); let adjacent = collector.process(&reply(3, 12, 12));
let snapshot = collector.cumulative(); let snapshot = collector.snapshot();
assert!(first.contributed_sample); assert!(first.contributed_sample);
assert_no_ipdv_pairs(&first); assert_no_ipdv_pairs(&first);
@@ -136,7 +136,7 @@ fn late_reply_can_complete_ipdv_pair() {
collector.process(&reply(1, 20, 20)); collector.process(&reply(1, 20, 20));
let update = collector.process(&late_reply(0, 10, 10)); let update = collector.process(&late_reply(0, 10, 10));
let snapshot = collector.cumulative(); let snapshot = collector.snapshot();
assert!(update.contributed_sample); assert!(update.contributed_sample);
assert_one_ipdv_pair(&update, 0, 1, Duration::from_millis(10)); assert_one_ipdv_pair(&update, 0, 1, Duration::from_millis(10));
@@ -183,7 +183,7 @@ fn gap_fill_update_exposes_both_completed_ipdv_pairs() {
assert_eq!(fill.ipdv_pairs[1].current_seq, 2); assert_eq!(fill.ipdv_pairs[1].current_seq, 2);
assert_eq!(fill.ipdv_pairs[1].rtt_ipdv, Duration::from_millis(7)); assert_eq!(fill.ipdv_pairs[1].rtt_ipdv, Duration::from_millis(7));
let snapshot = collector.cumulative(); let snapshot = collector.snapshot();
assert_eq!(snapshot.ipdv.round_trip.stats.count, 2); assert_eq!(snapshot.ipdv.round_trip.stats.count, 2);
assert_eq!(snapshot.ipdv.round_trip.stats.total_ns, 10_000_000); assert_eq!(snapshot.ipdv.round_trip.stats.total_ns, 10_000_000);
} }
@@ -206,7 +206,7 @@ fn server_processing_and_one_way_require_available_samples() {
packet_meta: PacketMeta::default(), packet_meta: PacketMeta::default(),
}); });
let snapshot = collector.cumulative(); let snapshot = collector.snapshot();
assert_eq!(snapshot.server_processing.processing.count, 1); assert_eq!(snapshot.server_processing.processing.count, 1);
assert_eq!(snapshot.one_way_delay.send_delay.stats.count, 1); assert_eq!(snapshot.one_way_delay.send_delay.stats.count, 1);
assert_eq!(snapshot.events.untracked_late_replies, 1); assert_eq!(snapshot.events.untracked_late_replies, 1);
@@ -246,12 +246,12 @@ fn rolling_time_eviction_uses_event_timestamps() {
#[test] #[test]
fn empty_and_all_lost_edges_are_defined() { fn empty_and_all_lost_edges_are_defined() {
let empty = StatsCollector::new(StatsConfig::finite()).summary(); let empty = StatsCollector::new(StatsConfig::finite()).snapshot();
assert_eq!(empty.loss.packet_loss_percent, 0.0); assert_eq!(empty.loss.packet_loss_percent, 0.0);
let mut collector = StatsCollector::new(StatsConfig::finite()); let mut collector = StatsCollector::new(StatsConfig::finite());
collector.process(&sent(0, ts(0))); collector.process(&sent(0, ts(0)));
let all_lost = collector.summary(); let all_lost = collector.snapshot();
assert_eq!(all_lost.loss.lost_packets, 1); assert_eq!(all_lost.loss.lost_packets, 1);
assert_eq!(all_lost.loss.packet_loss_percent, 100.0); assert_eq!(all_lost.loss.packet_loss_percent, 100.0);
} }
@@ -263,7 +263,7 @@ fn directional_loss_uses_server_received_count_when_available() {
collector.process(&sent(1, ts(10))); collector.process(&sent(1, ts(10)));
collector.process(&reply(0, 10, 10)); collector.process(&reply(0, 10, 10));
let loss = collector.summary().loss; let loss = collector.snapshot().loss;
assert_eq!(loss.upstream_loss_packets, Some(1)); assert_eq!(loss.upstream_loss_packets, Some(1));
assert_eq!(loss.downstream_loss_packets, Some(0)); assert_eq!(loss.downstream_loss_packets, Some(0));
assert_eq!(loss.upstream_loss_percent, 50.0); assert_eq!(loss.upstream_loss_percent, 50.0);