From d639d98735ccce2f59b7ae0ac1a64d150af210a0 Mon Sep 17 00:00:00 2001 From: Gints Polis Date: Sun, 15 Feb 2026 17:53:17 +0200 Subject: [PATCH 1/2] Sort connections by ammount --- src/aggregators/connections.rs | 22 +++++++--- tests/connections.rs | 52 +++++++++++++++++++++++ {testdata => tests/files}/connections.log | 0 3 files changed, 68 insertions(+), 6 deletions(-) rename {testdata => tests/files}/connections.log (100%) diff --git a/src/aggregators/connections.rs b/src/aggregators/connections.rs index d4297c9..e407ff7 100644 --- a/src/aggregators/connections.rs +++ b/src/aggregators/connections.rs @@ -156,24 +156,34 @@ impl Aggregator for ConnectionsAggregator { ); println!("Total connection failures: {}", self.connection_failures); println!("Connections by host:"); - for (host, count) in &self.connections_by_host { + let mut entries: Vec<_> = self.connections_by_host.iter().collect(); + entries.sort_by(|a, b| b.1.cmp(a.1)); + for (host, count) in entries { println!(" {count:>6} {host}"); } println!("Connections by database:"); - for (db, count) in &self.connections_by_database { + let mut entries: Vec<_> = self.connections_by_database.iter().collect(); + entries.sort_by(|a, b| b.1.cmp(a.1)); + for (db, count) in entries { println!(" {count:>6} {db}"); } println!("Connections by user:"); - for (user, count) in &self.connections_by_user { + let mut entries: Vec<_> = self.connections_by_user.iter().collect(); + entries.sort_by(|a, b| b.1.cmp(a.1)); + for (user, count) in entries { println!(" {count:>6} {user}"); } println!("Connections by application name:"); - for (appname, count) in &self.connections_by_appname { + let mut entries: Vec<_> = self.connections_by_appname.iter().collect(); + entries.sort_by(|a, b| b.1.cmp(a.1)); + for (appname, count) in entries { println!(" {count:>6} {appname}"); } println!("Connections by time bucket:"); - for (appname, count) in &self.connection_attempts_by_time_bucket { - println!(" {count:>6} {appname}"); + let mut entries: Vec<_> = self.connection_attempts_by_time_bucket.iter().collect(); + entries.sort_by(|a, b| a.0.cmp(b.0)); + for (bucket, count) in entries { + println!(" {count:>6} {bucket}"); } } diff --git a/tests/connections.rs b/tests/connections.rs index 14ea345..f78c1be 100644 --- a/tests/connections.rs +++ b/tests/connections.rs @@ -13,3 +13,55 @@ fn simple_connection_aggregate() -> Result<(), Box> { Ok(()) } + +#[test] +fn connections_output_sorted_by_count() -> Result<(), Box> { + let output = Command::new(cargo::cargo_bin!("pgweasel")) + .args(["conn", "./tests/files/connections.log"]) + .output()?; + + assert!(output.status.success()); + let stdout = String::from_utf8(output.stdout)?; + + let count_sorted_sections = [ + "Connections by host:", + "Connections by database:", + "Connections by user:", + "Connections by application name:", + ]; + + for section in count_sorted_sections { + let section_start = stdout + .find(section) + .unwrap_or_else(|| panic!("Section '{section}' not found")); + let after_header = &stdout[section_start + section.len()..]; + let section_end = after_header + .find("\nConnections by ") + .unwrap_or(after_header.len()); + let section_text = &after_header[..section_end]; + + let counts: Vec = section_text + .lines() + .filter_map(|line| { + let trimmed = line.trim(); + if trimmed.is_empty() { + return None; + } + trimmed.split_whitespace().next()?.parse::().ok() + }) + .collect(); + + assert!( + counts.len() > 1, + "Section '{section}' should have more than one entry for sorting to matter" + ); + for i in 1..counts.len() { + assert!( + counts[i - 1] >= counts[i], + "Section '{section}' not sorted descending: {counts:?}" + ); + } + } + + Ok(()) +} diff --git a/testdata/connections.log b/tests/files/connections.log similarity index 100% rename from testdata/connections.log rename to tests/files/connections.log From b780b814cfa0b66c61429075abddf41347b348fe Mon Sep 17 00:00:00 2001 From: Gints Polis Date: Sun, 15 Feb 2026 17:56:05 +0200 Subject: [PATCH 2/2] Addint sort of buckets too --- src/aggregators/connections.rs | 2 +- tests/connections.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/aggregators/connections.rs b/src/aggregators/connections.rs index e407ff7..3a6203b 100644 --- a/src/aggregators/connections.rs +++ b/src/aggregators/connections.rs @@ -181,7 +181,7 @@ impl Aggregator for ConnectionsAggregator { } println!("Connections by time bucket:"); let mut entries: Vec<_> = self.connection_attempts_by_time_bucket.iter().collect(); - entries.sort_by(|a, b| a.0.cmp(b.0)); + entries.sort_by(|a, b| b.1.cmp(a.1)); for (bucket, count) in entries { println!(" {count:>6} {bucket}"); } diff --git a/tests/connections.rs b/tests/connections.rs index f78c1be..cf3fd9f 100644 --- a/tests/connections.rs +++ b/tests/connections.rs @@ -28,6 +28,7 @@ fn connections_output_sorted_by_count() -> Result<(), Box "Connections by database:", "Connections by user:", "Connections by application name:", + "Connections by time bucket:", ]; for section in count_sorted_sections {