use crate::analyzer::AnalysisResult;
use std::cmp::Reverse;
use std::io::{self, Write};
pub fn print_results(result: &AnalysisResult, show_trends: bool, show_stats: bool) {
for line in &result.matched_lines {
println!("{}", line);
}
println!("\nFelled: {} logs", result.count);
if show_trends && !result.time_trends.is_empty() {
println!("\nTime trends:");
let mut trend_entries: Vec<_> = result.time_trends.iter().collect();
trend_entries.sort_by(|a, b| a.0.cmp(b.0));
for (hour, count) in trend_entries {
println!(
" {} - {} log{} occurred during this hour",
hour,
count,
if *count == 1 { "" } else { "s" } );
}
}
if show_stats {
println!("\nStats summary:");
if !result.levels_count.is_empty() {
println!("\n Log levels:");
let mut level_entries: Vec<_> = result.levels_count.iter().collect();
level_entries.sort_by_key(|&(_, count)| Reverse(*count));
for (level, level_count) in level_entries {
println!(
" {}: {} log{}",
level,
level_count,
if *level_count == 1 { "" } else { "s" }
);
}
}
if !result.error_types.is_empty() {
println!("\n Top error types:");
let mut error_entries: Vec<_> = result.error_types.iter().collect();
error_entries.sort_by_key(|&(_, count)| Reverse(*count));
for (idx, (error, error_count)) in error_entries.iter().take(5).enumerate() {
println!(
" {}. {}: {} occurrence{}",
idx + 1,
error,
error_count,
if **error_count == 1 { "" } else { "s" }
);
}
}
println!("\n Unique messages: {}", result.unique_messages.len());
println!(
" Repetition ratio: {:.1}%",
if result.count > 0 {
(1.0 - (result.unique_messages.len() as f64 / result.count as f64)) * 100.0
} else {
0.0
}
);
}
println!("\nTimber finished chopping the log! 🪵");
}
pub fn print_results_to_writer<W: Write>(
result: &AnalysisResult,
show_trends: bool,
show_stats: bool,
writer: &mut W,
) -> io::Result<()> {
for line in &result.matched_lines {
writeln!(writer, "{}", line)?;
}
writeln!(writer, "\nFelled: {} logs", result.count)?;
if show_trends && !result.time_trends.is_empty() {
writeln!(writer, "\nTime trends:")?;
let mut trend_entries: Vec<_> = result.time_trends.iter().collect();
trend_entries.sort_by(|a, b| a.0.cmp(b.0));
for (hour, count) in trend_entries {
writeln!(
writer,
" {} - {} log{} occurred during this hour",
hour,
count,
if *count == 1 { "" } else { "s" } )?;
}
}
if show_stats {
writeln!(writer, "\nStats summary:")?;
if !result.levels_count.is_empty() {
writeln!(writer, "\n Log levels:")?;
let mut level_entries: Vec<_> = result.levels_count.iter().collect();
level_entries.sort_by_key(|&(_, count)| Reverse(*count));
for (level, level_count) in level_entries {
writeln!(
writer,
" {}: {} log{}",
level,
level_count,
if *level_count == 1 { "" } else { "s" }
)?;
}
}
if !result.error_types.is_empty() {
writeln!(writer, "\n Top error types:")?;
let mut error_entries: Vec<_> = result.error_types.iter().collect();
error_entries.sort_by_key(|&(_, count)| Reverse(*count));
for (idx, (error, error_count)) in error_entries.iter().take(5).enumerate() {
writeln!(
writer,
" {}. {}: {} occurrence{}",
idx + 1,
error,
error_count,
if **error_count == 1 { "" } else { "s" }
)?;
}
}
writeln!(
writer,
"\n Unique messages: {}",
result.unique_messages.len()
)?;
writeln!(
writer,
" Repetition ratio: {:.1}%",
if result.count > 0 {
(1.0 - (result.unique_messages.len() as f64 / result.count as f64)) * 100.0
} else {
0.0
}
)?;
}
writeln!(writer, "\nTimber finished chopping the log! 🪵")?;
Ok(())
}