output timeline histogram (#535)
* added krapslog in cargo * added output timeline histgram feature #533 * added termilan_size to cargo * adjust timeline histgram width size to terminal width #533 * added section output in timeline histogram #533 * centering timeline histgram title #533
This commit is contained in:
116
Cargo.lock
generated
116
Cargo.lock
generated
@@ -271,12 +271,36 @@ dependencies = [
|
||||
"ansi_term",
|
||||
"atty",
|
||||
"bitflags",
|
||||
"strsim",
|
||||
"textwrap",
|
||||
"strsim 0.8.0",
|
||||
"textwrap 0.11.0",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_lex",
|
||||
"indexmap",
|
||||
"strsim 0.10.0",
|
||||
"termcolor",
|
||||
"textwrap 0.15.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
@@ -662,7 +686,7 @@ dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"chrono",
|
||||
"clap",
|
||||
"clap 2.34.0",
|
||||
"crc",
|
||||
"dialoguer",
|
||||
"encoding",
|
||||
@@ -711,6 +735,16 @@ dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "file-chunker"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92828425bb36590609d28014a252d6f0f71b698875a2b131fae367c627b6c656"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"memmap2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.23"
|
||||
@@ -886,7 +920,7 @@ version = "1.2.2"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"chrono",
|
||||
"clap",
|
||||
"clap 2.34.0",
|
||||
"csv",
|
||||
"dotenv",
|
||||
"downcast-rs",
|
||||
@@ -897,6 +931,7 @@ dependencies = [
|
||||
"hex 0.4.3",
|
||||
"hhmmss",
|
||||
"is_elevated",
|
||||
"krapslog",
|
||||
"lazy_static",
|
||||
"linked-hash-map",
|
||||
"num_cpus",
|
||||
@@ -911,6 +946,7 @@ dependencies = [
|
||||
"slack-hook",
|
||||
"static_vcruntime",
|
||||
"termcolor",
|
||||
"terminal_size",
|
||||
"tokio 1.18.2",
|
||||
"yaml-rust",
|
||||
]
|
||||
@@ -1059,6 +1095,18 @@ dependencies = [
|
||||
"hashbrown 0.11.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indicatif"
|
||||
version = "0.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d207dc617c7a380ab07ff572a6e52fa202a2a8f355860ac9c38e23f8196be1b"
|
||||
dependencies = [
|
||||
"console",
|
||||
"lazy_static",
|
||||
"number_prefix",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indoc"
|
||||
version = "1.0.6"
|
||||
@@ -1144,6 +1192,27 @@ dependencies = [
|
||||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "krapslog"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70d4d54b2c8b875b6692487e5269cb66f12cd51af11fe1807f135ad0d6b771de"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"atty",
|
||||
"chrono",
|
||||
"clap 3.1.18",
|
||||
"file-chunker",
|
||||
"indicatif",
|
||||
"memmap2",
|
||||
"num_cpus",
|
||||
"progress-streams",
|
||||
"rayon",
|
||||
"regex",
|
||||
"tempfile",
|
||||
"terminal_size",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
@@ -1248,6 +1317,15 @@ version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "057a3db23999c867821a7a59feb06a578fcb03685e983dff90daf9e7d24ac08f"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.5.6"
|
||||
@@ -1403,6 +1481,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "number_prefix"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.28.4"
|
||||
@@ -1473,6 +1557,12 @@ dependencies = [
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "029d8d0b2f198229de29dca79676f2738ff952edf3fde542eb8bf94d8c21b435"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.9.0"
|
||||
@@ -1587,6 +1677,12 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "progress-streams"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e965d96c8162c607b0cd8d66047ad3c9fd35273c134d994327882c6e47f986a7"
|
||||
|
||||
[[package]]
|
||||
name = "publicsuffix"
|
||||
version = "1.5.6"
|
||||
@@ -2208,6 +2304,12 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.95"
|
||||
@@ -2284,6 +2386,12 @@ dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.31"
|
||||
|
||||
@@ -33,6 +33,8 @@ hex = "0.4.*"
|
||||
git2="0.13"
|
||||
termcolor="*"
|
||||
prettytable-rs = "0.8"
|
||||
krapslog="*"
|
||||
terminal_size = "*"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
is_elevated = "0.1.2"
|
||||
|
||||
@@ -5,6 +5,7 @@ use crate::detections::utils;
|
||||
use chrono::{DateTime, Local, TimeZone, Utc};
|
||||
use csv::QuoteStyle;
|
||||
use hashbrown::HashMap;
|
||||
use krapslog::{build_sparkline, build_time_markers};
|
||||
use lazy_static::lazy_static;
|
||||
use serde::Serialize;
|
||||
use std::error::Error;
|
||||
@@ -14,6 +15,7 @@ use std::io::BufWriter;
|
||||
use std::io::Write;
|
||||
use std::process;
|
||||
use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor};
|
||||
use terminal_size::{terminal_size, Width};
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
@@ -98,6 +100,30 @@ fn _get_output_color(color_map: &HashMap<String, Color>, level: &str) -> Option<
|
||||
color
|
||||
}
|
||||
|
||||
/// print timeline histogram
|
||||
fn _print_timeline_hist(timestamps: Vec<i64>, marker_count: usize, length: usize) {
|
||||
if timestamps.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let buf_wtr = BufferWriter::stdout(ColorChoice::Always);
|
||||
let mut wtr = buf_wtr.buffer();
|
||||
|
||||
let title = "Event Frequency Timeline";
|
||||
let header_row_space = (length - title.len()) / 2;
|
||||
writeln!(wtr).ok();
|
||||
write!(wtr, "{}", " ".repeat(header_row_space)).ok();
|
||||
writeln!(wtr, "{}", title).ok();
|
||||
writeln!(wtr).ok();
|
||||
|
||||
let (header, footer) = build_time_markers(×tamps, marker_count, length);
|
||||
let sparkline = build_sparkline(×tamps, length);
|
||||
writeln!(wtr, "{}", header).ok();
|
||||
writeln!(wtr, "{}", sparkline.unwrap_or_default()).ok();
|
||||
writeln!(wtr, "{}", footer).ok();
|
||||
buf_wtr.print(&wtr).ok();
|
||||
}
|
||||
|
||||
pub fn after_fact() {
|
||||
let fn_emit_csv_err = |err: Box<dyn Error>| {
|
||||
AlertMessage::alert(
|
||||
@@ -151,8 +177,10 @@ fn emit_csv<W: std::io::Write>(
|
||||
let mut detected_rule_files: Vec<String> = Vec::new();
|
||||
|
||||
println!();
|
||||
let mut timestamps: Vec<i64> = Vec::new();
|
||||
let mut plus_header = true;
|
||||
for (time, detect_infos) in messages.iter() {
|
||||
timestamps.push(_get_timestamp(time));
|
||||
for detect_info in detect_infos {
|
||||
let mut level = detect_info.level.to_string();
|
||||
if level == "informational" {
|
||||
@@ -224,6 +252,13 @@ fn emit_csv<W: std::io::Write>(
|
||||
wtr.flush()?;
|
||||
}
|
||||
println!();
|
||||
let size = terminal_size();
|
||||
let terminal_width = match size {
|
||||
Some((Width(w), _)) => w as usize,
|
||||
None => 100,
|
||||
};
|
||||
_print_timeline_hist(timestamps, 10, terminal_width);
|
||||
println!();
|
||||
_print_unique_results(
|
||||
total_detect_counts_by_level,
|
||||
"Total".to_string(),
|
||||
@@ -325,6 +360,15 @@ fn format_time(time: &DateTime<Utc>) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// get timestamp to input datetime.
|
||||
fn _get_timestamp(time: &DateTime<Utc>) -> i64 {
|
||||
if configs::CONFIG.read().unwrap().args.is_present("utc") {
|
||||
time.timestamp()
|
||||
} else {
|
||||
time.with_timezone(&Local).timestamp()
|
||||
}
|
||||
}
|
||||
|
||||
/// return rfc time format string by option
|
||||
fn format_rfc<Tz: TimeZone>(time: &DateTime<Tz>) -> String
|
||||
where
|
||||
|
||||
Reference in New Issue
Block a user