use forge::signal::compactor;
use once_cell::sync::Lazy;
use regex::Regex;
static INFO_WARN_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"(?m)^‼[^\n]*\n?").unwrap());
static VERSION_MISMATCH_RE: Lazy<Regex> =
Lazy::new(|| Regex::new(r"(?m)^(?:client|server) version:[^\n]*\n?").unwrap());
pub fn compress_check(raw: &str) -> String {
let cleaned = compactor::normalise(raw);
let s = INFO_WARN_RE.replace_all(&cleaned, "");
let s = VERSION_MISMATCH_RE.replace_all(&s, "");
let mut pass_count = 0usize;
let mut failures: Vec<String> = Vec::new();
let mut categories: Vec<String> = Vec::new();
for line in s.lines() {
let t = line.trim();
if t.is_empty() {
continue;
}
if t.starts_with('√') || t.starts_with("ok") {
pass_count += 1;
} else if t.starts_with('×')
|| t.starts_with("×")
|| t.contains("FAILED")
|| t.contains("error")
{
failures.push(t.to_string());
} else if t.ends_with(':') || (t.len() < 60 && !t.contains(' ')) {
categories.push(t.to_string());
}
}
let mut out: Vec<String> = Vec::new();
if pass_count > 0 {
out.push(format!(" ✔ {} checks passed", pass_count));
}
out.extend(failures);
if out.is_empty() {
return compactor::collapse_blanks(&s);
}
out.join("\n")
}
pub fn compress_stat(raw: &str) -> String {
let cleaned = compactor::normalise(raw);
let lines: Vec<&str> = cleaned.lines().filter(|l| !l.trim().is_empty()).collect();
if lines.len() > 30 {
return format!(
"{}\n… [{} more rows]",
lines[..30].join("\n"),
lines.len() - 30
);
}
lines.join("\n")
}
pub fn compress_inject(raw: &str) -> String {
compactor::collapse_blanks(&compactor::normalise(raw))
}
pub fn compress_linkerd(subcmd: &str, raw: &str) -> String {
let sub = subcmd.trim();
if sub.starts_with("check") {
return compress_check(raw);
}
if sub.starts_with("stat") || sub.starts_with("top") {
return compress_stat(raw);
}
if sub.starts_with("inject") {
return compress_inject(raw);
}
let cleaned = compactor::normalise(raw);
let s = INFO_WARN_RE.replace_all(&cleaned, "");
compactor::collapse_blanks(&s)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_summarises_passes_and_shows_failures() {
let raw = "linkerd-config\n√ control plane Namespace exists\n√ control plane ClusterRoles exist\n√ control plane ClusterRoleBindings exist\n‼ gap in control plane version\nlinkerd-identity\n√ certificate config is valid\n× certificate is expiring soon: cert expires in 3 days\n";
let out = compress_check(raw);
assert!(!out.contains('‼'), "{out}");
assert!(out.contains("passed") || out.contains('√'), "{out}");
assert!(out.contains("expiring") || out.contains('×'), "{out}");
}
#[test]
fn stat_truncates_long_table() {
let mut lines = vec![
"NAME MESHED SUCCESS RPS LATENCY_P50 LATENCY_P95 LATENCY_P99 TCP_CONN"
.to_string(),
];
for i in 0..35 {
lines.push(format!("svc-{i} 1/1 100.00% 1.5rps 1ms 2ms 4ms 3"));
}
let out = compress_stat(&lines.join("\n"));
assert!(out.contains("more rows"), "{out}");
}
}