diff --git a/src/afterfact.rs b/src/afterfact.rs index e31601ea..4d0d6d72 100644 --- a/src/afterfact.rs +++ b/src/afterfact.rs @@ -392,6 +392,9 @@ fn emit_csv( println!(); _print_detection_summary_by_computer(detect_counts_by_computer_and_level, &color_map); + println!(); + + _print_detection_summary_by_rule(detect_counts_by_rule_and_level, &color_map); Ok(()) } @@ -587,6 +590,55 @@ fn _print_detection_summary_by_computer( buf_wtr.print(&wtr).ok(); } +/// 各レベルごとで検出数が多かったルールのタイトルを出力する関数 +fn _print_detection_summary_by_rule( + detect_counts_by_rule_and_level: HashMap>, + color_map: &HashMap, +) { + let buf_wtr = BufferWriter::stdout(ColorChoice::Always); + let mut wtr = buf_wtr.buffer(); + wtr.set_color(ColorSpec::new().set_fg(None)).ok(); + let level_cnt = detect_counts_by_rule_and_level.len(); + for (idx, level) in LEVEL_ABBR.values().enumerate() { + // output_levelsはlevelsからundefinedを除外した配列であり、各要素は必ず初期化されているのでSomeであることが保証されているのでunwrapをそのまま実施 + let detections_by_computer = detect_counts_by_rule_and_level.get(level).unwrap(); + let mut result_vec: Vec = Vec::new(); + let mut sorted_detections: Vec<(&String, &i128)> = detections_by_computer.iter().collect(); + + sorted_detections.sort_by(|a, b| (-a.1).cmp(&(-b.1))); + + for x in sorted_detections.iter().take(5) { + result_vec.push(format!( + "{} ({})", + x.0, + x.1.to_formatted_string(&Locale::en) + )); + } + let result_str = if result_vec.is_empty() { + "None".to_string() + } else { + result_vec.join("\n") + }; + + wtr.set_color(ColorSpec::new().set_fg(_get_output_color( + color_map, + LEVEL_FULL.get(level.as_str()).unwrap(), + ))) + .ok(); + writeln!( + wtr, + "Top {} alerts:\n{}", + LEVEL_FULL.get(level.as_str()).unwrap(), + &result_str + ) + .ok(); + if idx != level_cnt - 1 { + writeln!(wtr).ok(); + } + } + buf_wtr.print(&wtr).ok(); +} + /// get timestamp to input datetime. fn _get_timestamp(time: &DateTime) -> i64 { if configs::CONFIG.read().unwrap().args.utc { diff --git a/src/main.rs b/src/main.rs index 05a97cc2..539b8973 100644 --- a/src/main.rs +++ b/src/main.rs @@ -305,7 +305,6 @@ impl App { let analysis_end_time: DateTime = Local::now(); let analysis_duration = analysis_end_time.signed_duration_since(analysis_start_time); - println!(); write_color_buffer( &BufferWriter::stdout(ColorChoice::Always), None,